3. 포트리스 게임을 위한 키보드 입력방법 알아본다.
가. 키보드를 통한 상호작용
포트리스 게임(대포게임)을 제대로 만들기 위해 대포의 각도를 바꾸는 방법에 대해서 생각해 보자. 대포의 각도를 바꾸기 위해서 키보드의 방향키를 이용할 것이다. 상하 방향키를 이용하여 각도 변화를 만들어 보자. 우선 대포 무비 클립을 하나 만들어 인스턴스 네임을 ‘po’ 라고 하고, 키보드를 이용하여 회전시켜 보도록 하자. 메인프레임에 다음과 같이 적어 보자.
//기초값 gak = 0; // 초기각도 onEnterFrame = function () { po._rotation = gak; if (Key.isDown(Key.UP)) { gak = gak-1; } if (Key.isDown(Key.DOWN)) { gak = gak+1; } } |
키보드의 방향키 위,아래를 누르면 대포의 각도가 변하는 것을 볼 수 있다. 그런데 자세히 살펴보면 회전하는 대포에서 이상한 점을 발견할 수 있다. 회전중심이 우리가 원하는 곳이 아니라는 것이다. 첫 번째 그림 처럼 무비클립을 만들면 회전중심은 기본적으로 그 무비클립의 정 가운데가 된다. 이 상태에서 명령을 주어 무비클립을 회전시키면 정가운데 중심을 기준으로 회전하게 되는 것이다. 따라서 두 번째 그림처럼 회전 중심을 무비클립 편집모드로 들어가 바꾸어 주어야 한다.
또 무비클립의 회전각도가 0 이 되는 경우는 오른쪽을 방향으로 잡고 있는 경우이다. 따라서 회전을 목적으로 어떤 무비클립을 만든다면, 초기 무비클립의 모양을 위 그림처럼 오른쪽으로 향하게 만드는 것이 좋다.
나. 무비클립회전과 각도 변화 방법
무비클립의 회전에서 또한가지 알아 두어야 할 것이 있다. 바로 회전 각도이다. 우리가 일반적으로 수학에서 사용하는 회전각도와는 달리 플래시에서는 회전각도가 아래쪽이 기준이 된다.
<수학에서 사용하는 각도방향> <컴퓨터에서 사용하는 각도 방향>
따라서 대포를 위쪽으로 회전시키려면, po._rotation 의 각도를 0보다 작아지게 해야 할 것이다. 대포의 각도를 제한시켜 보자. 대포가 뒤쪽으로 돌아가지 못하도록 -90보다 크고 0보다 작은 범위에서만 회전할 수 있도록 만들어보자.
<토의> 조건문을 사용하여 회전 범위를 제한해 보자.
//기초값 gak = 0; // 초기각도 onEnterFrame = function () { po._rotation = gak; if (Key.isDown(Key.UP)) { if (gak>-90) { gak = gak-1; } } if (Key.isDown(Key.DOWN)) { if (gak<0) { gak = gak+1; } } } |
다. 발사 방법 연구
대포의 발사는 스페이스 바를 눌렀을 때 발사 되게 하려고 한다. 스페이스바를 눌렀을 때 작동하게 하려면 어떤 액션스크립트를 주어야 할까? 중간에 아래와 같은 스크립트를 추가하면 된다.
if (Key.isDown(Key.SPACE)) { trace("대포발사“); } |
4. 초기속도와 각도를 변화해 가며 포물선 운동을 시킬 수 있다.
가. 각도에 따른 공의 운동 표현(삼각함수)
포트리스 게임을 만들기 위한 기본적인 액션스크립트는 다 알아 보았다. 이번에는 발사 각도에 따른 x축과 y축의 속력을 구하는 방법에 대해 알아 보고자 한다. 포물선 운동은 x축으로는 등속운동이고, y축으로는 등가속도 운동이라고 이미 알고 있다. 그런데 중요한 것은 각도에 따라서 x축과 y축의 초기 속도 값이 달라진다는 것이다. 각도를 변하게 하면서 x축과 y축의 초기 속도값이 변하는 것을 어떻게 알아 내수 있을까? 이럴때 필요한 것이 삼각함수이다.
vx 와 vy 값을 삼각함수를 이용해서 구해낼 수 있는 것이다. 따라서 우리는 초기속도 v의 값과 각도 θ만 주어지면 vx 와 vy 값을 구해낼 수 있다. 한가지 주의할 점은 플래시에서는 sin과 cos에 값을 넣을때 라디안으로 넣어주어야 정상적으로 동작한다는 것이다.
라디안이란 호도법에 의한 각도의 단위로 반지름 r인 원에서 원주상에 길이 r인 원호(圓弧)를 잡았을 때의 중심각의 크기를 1라디안 또는 1호도라 한다. 우리는 우리가 알고 있는 각도를 호도법으로 바꾸어 주어야 한다. 너무 어렵게 생각하지 말자. 다음 방법을 따르면 된다. 이것도 마찬가지로 어렵다면 우선 무조건 외워두도록 하자. 예를 들어 30도의 각도를 호도법으로 바꾸면
30 * Math.PI/180 |
이라고 써주면 된다. 우리가 사용하는 각도에 Math.PI/180을 곱하기만 하면 바로 라디안 값으로 변한다. 그렇다면 이제 각도를 조절함에 따라 공의 초기속도가 함께 변하게 만들어 보자.
각도에 따른 공의 vx속력과 vy 속력을 구해 보면 아래와 같다.
vx = v*Math.cos(gak*Math.PI/180); vy = v*Math.sin(gak*Math.PI/180); |
이제 우리는 대포를 발사 시키기 위해서 대포의 각도값만을 바꾸어 줌으로써 대포의 vx 속력과 vy 속력을 구해 낼 수 있는 것이다. gak 이 0부터 -90 사이에 있으므로 계산해 보면 vx 값은 + 값이, vy 값은 - 값이 나온다는 것을 알아두자.
<토의> 위 vx와 vy의 값 계산을 어느 부분에 넣는 것이 가장 바람직할까?
나. 초기속도에 따른 공의 운동 표현
이번에는 같은 방법으로 대포의 초기 발사 속도를 바꾸어 보자. 키보드의 좌,우방향키를 이용하여 v 의 값을 변화 시켜 보자. v 의 값이 0보다 작아지지 않게 해야 할 것이고, 또한 v의 값이 너무 커지지 않도록 해야 할 것이다. 여기에서는 최대 40을 넘지 못하도록 해보자.
if (Key.isDown(Key.LEFT)) { if (v>1) { v = v-1;} } if (Key.isDown(Key.RIGHT)) { if(v<40){ v = v+1;} } |
<키보드를 이용하여 대포 각도를 조절하고 스페이스바를 눌러 대포를 발사해 보자>
다. 포트리스 게임 제작
대포를 발사하기 위한 기본적인 내용은 모두 만들어 졌다. 위 내용들을 모두 합
쳐서 대포를 발사할 수 있는 포트리스 게임을 제작해 보자.
1)고려해야 할 사항에 대해 토의해 보고 변수명을 정해보자.
대포의 인스턴스명 (po) 대포알(포탄)의 인스턴스명 (ball) 적탱크의 인스턴스명 (tank) 대포의 각도값 : gak 대포의 각도 표시값 :gak1 대포알(포탄)의 속도값 : v 대포알(포탄)의 x축 속도값 : vx 대포알(포탄)의 y축 속도값 : vy 대포알(포탄)의 발사 여부 체크값 : check1 |
2) 화면구성
3) 액션스크립트 작성
아래 액션스크립트에서 주의해 볼 것은 대포알의 발사 체크 여부이다.
check1 이라는 변수를 도입하여, 평상시에는 대포알이 발사되지 않도록 하다가 space 가 눌렸을때 cehck1을 1로 바꾸어 주면서 대포알이 발사되도록 하였다.
또 한번 발사하고 나면 발사 버튼이 연속해서 눌리지 않도록, check1 변수를 이용하여 space가 눌리지 않도록 하였다. tank 목표물에 ball 이 맞는 순간 hitTest 문을 이용하여 적의 tank가 폭발하도록 하였다.
물론 적의 tank 무비클립안에는 2번 프레임부터 tank가 폭파되는 에니메이션을 미리 삽입해 놓아야 할 것이다.
//기초값 g = 1; //중력가속도 값 v = 10; // 던져올려진 초기 속도 gak = 0; //처음각도 //대포알의 초음 초기 위치 ball._x = po._x; ball._y = po._y; check1 = 0; //대포발사여부 체크 onEnterFrame = function () { if (check1 == 1) { //발사가 허용된 경우 vy = vy+g; // vy 속도에 중력가속도 값 더해서 속도 변화 ball._y = ball._y+vy; // y축으로 운동 ball._x = ball._x+vx; // x축으로 등속운동 // 포탄이 화면을 벗어나는 경우 if (ball._y>400 || ball._x>550) { ball._x = po._x; ball._y = po._y; check1 = 0; } // 목표물에 맞는 경우 if (ball.hitTest(tank)) { tank.play(); } } po._rotation = gak;// 포 회전 gak1 = -gak; // 각도 표시 하기 위한 값 if (Key.isDown(Key.SPACE)) { if (check1 == 0) { // 속도 분해 vx = v*Math.cos(gak*Math.PI/180); vy = v*Math.sin(gak*Math.PI/180); check1 = 1; } } |
// 각도 조절과 속도 조절 if (Key.isDown(Key.UP)) { if (gak>-90) { gak = gak-1; } } if (Key.isDown(Key.DOWN)) { if (gak<0) { gak = gak+1; } } if (Key.isDown(Key.LEFT)) { if (v>1) { v = v-1; } } if (Key.isDown(Key.RIGHT)) { if (v<40) { v = v+1; } } } |
간단한 포트리스 게임을 제작해 보았다. 간단하지만 물리적 현상을 고려한 게임이라고 할 수 있다. 조금만 더 응용한다면 좋은 게임이 될 것이다. 이밖에도 고려해야할 사항은 바람의 여부, 공기저항여부, 또 지면과의 충돌여부 등도 체크해야할 것이다. 그리고 기회가 된다면 적의 탱크에서도 아군의 대포를 향해 포탄을 발사할 수 있도록 하는 것도 가능할 것이다.
5. 응용
가. 키보드를 이용하여 포의 위치를 이동시켜 본다.
지금까지와는 다른 방법으로 포를 이동시켜 보자. 키보드를 이용해서 조작하는 방법에는 위에서 사용한 Key.isDown 방법도 있지만, 메인프레임에서
Key.addListener()를 사용하는 방법이 있다. 이 방법의 장점은 모든 키의 누름을 체크할 수 있으며, onEnterframe이 계속해서 키가 눌렸는지를 체크하는 반면,
Key.addListener()는 키가 눌려지는 순간만 감지하므로 메모리를 절약할 수도 있다. trace(Key.getAscii());를 통해 내가 누른 키의 코드를 알아내어, 아래처럼 x키와 z키의 코드번호를 알아내어 명령을 줄 수도 있다.
아래 명령을 메인프레임에 추가하면 포를 좌우로 움직이게 할 수 있다.
var keyListener:Object = new Object(); keyListener.onKeyDown = function() { trace(Key.getAscii());// 눌려진 키의 번호를 알아내기 위한 값 if (Key.getAscii() == 120) { //x키 po._x = po._x+1; } if (Key.getAscii() == 122) { //z키 po._x = po._x-1; } }; Key.addListener(keyListener); |
나. 바람에 따라 바뀌는 포탄의 운동을 구현해 본다.
날아가는 포탄이 바람의 영향을 받아 날아가게 만들어 보자. 바람은 왼쪽이나 오른쪽으로 불게 만들것이며, 그 바람 때문에 영향을 받는 것은 x축으로 이동하는 포탄의 속력이 될 것이다. 따라서 포탄의 속력은 오른쪽으로 부는바람에 의해서는 점점 빨라질 것이고 왼쪽으로 부는바람에 의해서는 점점 느려질 것이다.
메인 프레임에 아래와 같은 바람과 관련된 변수를 추가해 보자.
wind=-0.2; |
그리고 onEnterFrame 문 안에 아래처럼 vx를 바꾸어 보자.
vx=vx+wind; ball._x =ball._x+ vx; |
그럼 바람에 영향을 받는 포탄이 만들어 질 것이다.
이왕이면 바람이 불때 마다 바뀔 수 있도록 random 문을 사용하고 바람의 세기를 알 수 있도록 dynamicText 문을 이용하여 화면에 바람의 방향을 표시해 주면 더 좋을 것이다.
wind=Math.random(); |
다. 중력변화에 의한 포탄의 운동 구현
만약 달에 가서 대포를 쏜다면 어떻게 될까, 아니면 우주공간에서 대포를 쏜다면 어떻게 될까. 바뀌는 것은 없다. 단지 중력값만이 바뀔 뿐이다. 중력이 바뀐다면 포탄의 운동도 달라질 것이다. 중력을 바꾸어 가며 포탄의 운동을 확인해 보자. 메인프레임에 g 값만 바꾸어 주면 된다.
라. 지면과의 충돌 여부
san 이라는 무비클립을 만들고 ball 의 위치와 충돌여부를 체크하면 될 것이다.
san 의 모양을 다양하게 바꾸어 가며 충돌여부를 체크해 보아라.
onEnterFrame = function () 문 안에 아래 스크립트를 추가하면 된다.
if (san.hitTest(ball._x,ball._y, true)) { ball._x = po._x; ball._y = po._y; check1 = 0; } |
여러 가지 사항들을 고려하여 자신만의 포트리스게임을 만들어 보자.
<키보드와 스페이스바를 이용하여 게임을 해보자>
더 응용 한다면 사용자가 한번 쏘고 나면 적 탱크가 우리 편을 공격하도록 만들어 보아라.