Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

heenam

자바스크립트를 이용한 미니 게임 만들기(골 넣기 게임) 본문

Wep Programming/JavaScript

자바스크립트를 이용한 미니 게임 만들기(골 넣기 게임)

znzltiq 2020. 7. 18. 17:26

 HTML 요소 생성하기

  먼저 게임에 필요한 HTML 요소를 생성해야 한다. 필요한 요소는 그림을 그리기 위한 <canvas>요소, 사용자로부터

  숫자를 입력받을 수 있는 <input>요소, 버튼 등이 필요하다. 이것을 먼저 생성하고 테스트하자.

<!DOCTYPE html>
<html lang="en" dir="ltr">
    <head>
        <meta charset="utf-8">
        <title>Javascript Game</title>
        <style>
            canvas {
                border: 1px dotted red;
                background-color: #fcff00;
            }
        </style>
    </head>
    <body>
        <canvas id="canvas" width="500" height="300"></canvas>
        <div id="control">
            속도 <input id="velocity" value="30" type="number" min="0" max="100" step="1">
            각도 <input id="angle" value="45" type="number" min="0" max="90" step="1">
            <div id="score">점수 = 0</div>
            <button>발사</button>
        </div>
    </body>
</html>

 배경 만들기

  배경은 두 개의 이미지만을 가지고 만들자. 하나는 잔디밭 이고 한는 그물망 이다. 적절한 이미지를 생성하여 자바스크

  립트에서 이것을 그려준다.

<head>
	<script>
		var image = new Image();
		image.src = "lawn.jpg";
		var backimage = new Image();
		backimage.src = "net.jpg";

		function drawBackground() {
			context.drawImage(image, 0, 270);
			context.drawImage(backimage, 450, 60);
		}
		function draw() {
			context.clearRect(0, 0, 500, 300);
			drawBackground();
 		}
		function init() {
			context = document.getElementById('canvas').getContext('2d');
			draw();
		}
	</script>
</head>
<body onload="init()">
...
</body>

  먼저 init() 함수를 작성한다. 여기서는 여러 초기화를 담당한다. 변수에 값을 대입하고 캔버스 객체로부터 컨텍스트 객

  체를 얻어놓는다. 또 배경을 그려준다.

  init() 함수가 작정되면 어디선가 호출되어야 한다. 어디서 호출하는 것이 좋은가? <body> 태그의 onload 이벤트에

  연결해놓자. 문서가 완전히 로드된 후에 호출되어야 하기 때문이다. 이미지도 완전히 로드가 되어 있어야 한다.

  게임의 화면을 그려줄 때는 먼저 화면을 지워야 한다. 화면을 지우지 않으면 새로운 그림과 이전 그림이 섞이게 된다.

  화면은 다음과 같은 문장으로 지울 수 있다.

context.clearRect(0, 0, 500, 300);

  이미지를 화면에 그릴 때는 다음과 같은 문장을 사용한다.

context.drawImage(image, 0, 270);

 움직이는 공 만들기

  이 게임의 주인공은 움직이는 공이다. 따라서 공에 대한 많은 변수가 필요하다. 다음과 같은 변수를 선언하였다.

  + var ballV; - 공의 속도이다.

  + var ballVx; - 공의 x 방향 속도이다.

  + var ballVy; - 공의 y 방향 속도이다.

  + var ballX; - 공의 현재 x 좌표이다.

  + var ballY; - 공의 현재 y 좌표이다.

  + var ballRadius; - 공의 반지름이다.

  모든 게임에는 물리 엔진이 필요하지만 우리 게임은 너무 단순해서 사용할 필요가 없다.

  날아가는 공에는 현재 속도가 있고 속도는 x방향과 y방향 속도로 나누어진다.

  공의 y방향 속도는 공기의 영향을 받지 않는 것으로 가정한다. 물론 실제 상황에서는 광기의 저항을 받겠지만 이것은

  무시하도록 하자. 공의 y방향 속도는 중력 가속도 때문에 점점 느려질 것이다.

  + ballVx; 초기 속도에서 변하지 않는다.

  + ballVy; 초기 속도에서 중력 가속도만큼 점점 느려진다.

  따라서 시간이 흘려가면 ballVy에서 중력 가속도만큼을 빼주면 된다. 중력 가속도는 원래 9.8m/sec²이지만 게임에서는

  단위 시간이 초가 아니기 때문에 적당한 값을 빼주면서 실험해 보면 된다.

ballVx = ballVx;
ballVy = ballVy + 1.98;

  자바스크립트에서는 y좌표가 위에서 아래로 가면서 증가하게 된다. 따라서 일반적인 수학 좌표와는 반대이다.

  속도를 계산할 때도 중력 가속도를 빼주는 것이 아니고 더해주어야 한다.

  공의 현재 위치는 이전 위치에 속도 x 시간을 더하면 된다. 시간은 단위시간 1이 흘렀다고 가정하면 다음과 같이 단순

  히 현재 위치에 속도를 더하면 된다.

ballX =ballX + ballVx;
ballY =ballY + ballVy;

  그리고 또 아주 중요한 부분이 남아 있다. 단위 시간마다 속도를 다시 계산하고 공을 하면에 다시 그려야 한다.

  즉 주기적으로 어떤 함수를 호출해야 한다. 이것은 setInterval() 함수를 사용하면 된다. setInterval() 함수는 일정한 시간

  이 흐른 뒤에 특정한 함수를 호출할 수 있다.

timer = setInterval(calculate, 100);

  점수 계산은 현재 공의 위치가 목표 안에 있으면 점수를 1만큼 증가하면 된다.

if ((ballX >= 450) && <ballX <= 480) && < (ballY >= 60) && (ballY <= 210) {
	score++;
	document.getElementById("score").innerHTML = "점수" + score;
	clearInterval(timer);
}

  clearInterval()은 주기적인 호출을 중단하는 함수이다. 공이 목표물에 맞았으면 더 이상 게임을 계속할 필요가 없기 때

  문에 주기적인 호출을 중단해야 한다.

 공의 초기 속도

  공의 초기 속도는 사용자가 입력한 속도와 각도에 따라서 설정되어야 한다. 간단한 삼각함수를 사용하면 된다.

//id가 velocity인 요소에서 값을 읽어서 숫자로 변환한다.
velocity = Number(document.getElementById('velocity').value);

//id가 angle인 요소에서 값을 읽어서 숫자로 변환한다.
angle = Number(document.getElementById('angle').value);

//각도 단위를 도에서 라디안으로 바꾼다.
var angleR = angle * Math.PI / 180;

//공의 초기 x방향 속도와 초기 y방향 속도를 계산한다.
ballVx = velocity * Math.cos(angleR);
ballVy = -velocity * Math.sin(angleR);

전체 소스

<!DOCTYPE html>
<html lang="en" dir="ltr">
    <head>
        <meta charset="utf-8">
        <title>Javascript Game</title>
        <style>
            canvas {
                border: 1px dotted red; /*캔버스에 경계선을 그려준다.*/
                background-color: #fcff00; /*캔버스와 배경색을 지정한다.*/
            }
        </style>
        <script>
            var context; /*컨텍스트 객체*/
            var velocity; /*사용자가 입력한 공의 초기 속도*/
            var angle; /*사용자가 입력한 공의 초기 각도*/
            var ballV; /*공의 현재 속도*/
            var ballVx; /*공의 현재 x방향 속도*/
            var ballVy; /*공의 현재 y방향 속도*/
            var ballX = 10; /*공의 현재 x방향 위치*/
            var ballY = 250; /*공의 현재 y방향 위치*/
            var ballRadius = 10; /*공의 반지름*/
            var score = 0; /*점수*/
            var image = new Image(); /*이미지 객체 생성*/
            image.src = "lawn.jpg"; /*이미지 파일 이름 설정*/
            var backimage = new Image();
            backimage.src = "net.jpg";
            var timer; /*타이머 객체 변수*/

            /*공을 화면에 그린다.*/
            function drawBall() {
                context.beginPath();
                context.arc(ballX, ballY, ballRadius, 0, 2.0 * Math.PI, true);
                context.fillStyle = "red";
                context.fill();
            }

            /*배경을 화면에 그린다*/
            function drawBackground() {
                context.drawImage(image, 0, 270);
                context.drawImage(backimage, 450, 60);
            }

            /*전체 화면을 그리는 함수*/
            function draw() {
                context.clearRect(0, 0, 500, 300);
                drawBall();
                drawBackground();
            }

            /*초기화를 담당하는 함수*/
            function init() {
                ballX = 10;
                ballY = 250;
                ballRadius = 10;
                context = document.getElementById('canvas').getContext('2d');
                draw();
            }

            /*사용자가 발사 버튼을 누르면 호출된다.*/
            function start() {
                init();
                velocity = Number(document.getElementById('velocity').value);
                angle = Number(document.getElementById('angle').value);
                var angleR = angle * Math.PI / 180;

                ballVx = velocity * Math.cos(angleR);
                ballVy = -velocity * Math.sin(angleR);

                draw();
                timer = setInterval(calculate, 100);
                return false
            }

            /*공의 현재 속도와 위치를 업데이트한다.*/
            function calculate() {
                ballVy = ballVy + 1.98;

                ballX = ballX + ballVx;
                ballY = ballY + ballVy;

                /*공이 목표물에 맞았으면*/
                if ((ballX >= 450) && (ballX <= 480) && (ballY >= 60) && (ballY <= 210)) {
	                score++;
	                document.getElementById("score").innerHTML = "점수= " + score;
	                clearInterval(timer);
                }
                /*공이 경계를 벗어났으면*/
                if (ballY >= 300 || ballY < 0) {
                    clearInterval(timer);
                }
                draw();
            }
        </script>
    </head>
    <body onload="init();">
        <canvas id="canvas" width="500" height="300"></canvas>
        <div id="control">
            속도 <input id="velocity" value="30" type="number" min="0" max="100" step="1">
            각도 <input id="angle" value="45" type="number" min="0" max="90" step="1">
            <div id="score">점수 = 0</div>
            <button onclick="start()">발사</button>
        </div>
    </body>
</html>