화면에 'tM'이란 이름의 주인공 탱크(무비클립 내에는 'top'이란 이름의
탱크위 터렛 무비클립, 'pointM'이란 이름의 충돌체크용 사각형 무비클립을 만들어 두었다)를 배치해 두고 'eTankM'이란
익스포트명의 적 탱크 무비클립(무비클립 내에는 'boom'이란 name 뒤에 간단한 폭파 애니를 만들어 두었다),
'tBulletM', 'eBulletM'이란 이름의 주인공 포탄, 적 포탄 무비클립, 'screenM'이란 이름의
설명용 화면 무비클립(내부에 'restartBtn'이란 이름의 재시작 버튼 무비클립을 담고 있다)을 라이브러리에
만들어 두다.
var screen:MovieClip = new screenM(); //설명화면 무비클립
var player:MovieClip = tM; //주인공 탱크
var pSpeed = 2; //탱크 속도
var pEnergy; //탱크 목숨
var shootInterval = 500; //주인공 발사 간격 0.5초
var startTime = 0;
var elapsedTime = 0;
var enemyNum = 0; //화면상 적 탱크의 수
var allObjM:MovieClip = new MovieClip(); //화면내 모든 무비 담기용
var pBulletArr:Array = new Array(); //주인공 탄 저장 배열
var pBulletBoomArr:Array = new Array(); //주인공 탄 폭파효과 저장 배열
var enemyArr:Array = new Array(); //적 탱크 저장 배열
var eBulletArr:Array = new Array(); //적탄 저장 배열
var enemyBoomArr:Array = new Array(); //적 폭파효과 저장 배열
var eSpawnTimer:Timer = new Timer(3000); // 적탱크 생성 타이머 3초
var left, right, up, down, jump; //주인공 조종 관련 방향변수
var left0,right0,up0,down0,released=true; //주인공 이전 방향변수
var sx0=0, sx1=stage.stageWidth; //화면 상하좌우 변수
var sy0=0, sy1=stage.stageHeight;
function init(){
gameInit();
}
//************************************************************
// 게임 초기화, 종료, 재시작 처리 등.
//************************************************************
function gameInit(){
player.gotoAndStop(1);
left = false, right = false, up = false, right = false;
pEnergy = 4;
enemyNum = 0;
pEnergyM.gotoAndStop(pEnergy);
stage.addChild(allObjM);
stage.addEventListener(Event.ENTER_FRAME,loop);
stage.addEventListener(MouseEvent.CLICK,mouseClick);
stage.addEventListener(KeyboardEvent.KEY_UP,keyUps);
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDowns);
eSpawnTimer.addEventListener(TimerEvent.TIMER,esTimeOn);
eSpawnTimer.reset();
eSpawnTimer.start();
}
function gameOver(){ //게임 오버 처리
//배열들 비우기
pBulletArr = [];
pBulletBoomArr = [];
enemyArr = [];
eBulletArr = [];
enemyBoomArr = [];
//이벤트 핸들러들 지우기
stage.removeEventListener(Event.ENTER_FRAME,loop);
stage.removeEventListener(MouseEvent.CLICK,mouseClick);
stage.removeEventListener(KeyboardEvent.KEY_UP,keyUps);
stage.removeEventListener(KeyboardEvent.KEY_DOWN,keyDowns);
eSpawnTimer.removeEventListener(TimerEvent.TIMER,esTimeOn);
stage.addChild(screen);
screen.gotoAndStop("gameOver");
screen.restartBtn.addEventListener(MouseEvent.CLICK,gameRestartH);
}
function gameRestartH(e:MouseEvent){ gameRestart(); }
function gameRestart(){
//화면내 무비클립들 지우기
while(allObjM.numChildren) allObjM.removeChildAt(0);
stage.removeChild(allObjM);
screen.restartBtn.removeEventListener(MouseEvent.CLICK,gameRestartH);
stage.removeChild(screen);
gameInit();
}
//************************************************************
//************************************************************
// 메인 루프**************************************************
//************************************************************
//************************************************************
function loop(e:Event){ //매 프레임 실행
keyProcessing(); //키보드 처리
pBulletMove(); //주인공 총알 움직임 처리
pBulletBoomProcess(); //주인공 총알 폭발효과 처리
enemyMove(); //적 이동 처리
eBulletMove(); //적탄 이동 처리
enemyBoomProcess(); //적 폭발효과 처리
collisionCheck(); //충돌처리
}
//************************************************************
// 충돌 처리 관련
//************************************************************
function collisionCheck(){ //충돌처리
eBulletArr = eBulletArr.filter(eraseNull);//eBulletArr내 null 제거
for(var i=0; i < eBulletArr.length; ++i){ //적탄과 주인공 충돌 체크
var eb = eBulletArr[i];
if(eb.hitTestObject(player.pointM)){ //적탄과 주인공 충돌시
playerDamage(); //주인공 충돌처리
eBulletDestroy(eb, i); //적탄 제거 함수 호출
continue; //다음으로 넘어가기
}
}
enemyArr = enemyArr.filter(eraseNull);//enemyArr내 null 제거
for(var j=0; j < enemyArr.length; ++j){
var enemy = enemyArr[j];
pBulletArr = pBulletArr.filter(eraseNull);//pBulletArr내 null 제거
for(var k=0; k < pBulletArr.length; ++k){ //주인공 총알과 적 충돌 체크
var pb = pBulletArr[k];
if(pb.hitTestObject(enemy)){ //총알과 적 충돌시
//trace("enemy Hit!!!!!!!!");
enemyBoom(enemy.x, enemy.y, enemy.rotation);//폭발효과 붙이기
enemyDestroy(enemy, j); //적 제거 함수 호출
pBulletDestroy(pb, k); //총알 제거 함수 호출
continue; //다음으로 넘어가기
}
}
}
}
//************************************************************
// 타이머 처리 관련
//************************************************************
function esTimeOn(e:TimerEvent){ //타이머 작동
if(enemyNum < 3){ //화면상에 적 탱크가 3대 이하일 경우
enemyInit(); //적 생성, 초기화 함수 호출
enemyNum++;
}
}
//************************************************************
// 적 관련
//************************************************************
function enemyInit(angle=90, speed=2){ //적 탱크 생성, 초기화
//매개변수(각도(도), 이동속도)
var em = new eTankM();
em.x = Math.random()*(sx1-em.width)+em.width; //적 위치 초기화
em.y = 100; //-em.height;
em.vx = 0, em.vy = 0; //탄 속도벡터 초기화
em.rotation = angle; //탄 각도 발사방향으로 회전
em.sTimer = 60; //총알 발사 타이머
//em.life = 130;
angle = Math.PI/180 * angle; //도에서 라디안으로
//탄 속도벡터 구하기
em.vx = Math.cos(angle)*speed;
em.vy = Math.sin(angle)*speed;
allObjM.addChild(em); //적 화면에 붙이기
enemyArr.push(em); //적 배열에 추가
}
function eBulletInit(enemy, angle=90, speed=2){ //적탄 생성, 초기화
//매개변수(적 무비클립,)
var eb = new eBulletM();
eb.x = enemy.x; //적탄 위치 초기화
eb.y = enemy.y;
eb.vx = 0, eb.vy = 0; //탄 속도벡터 초기화
eb.rotation = angle; //탄 각도 발사방향으로 회전
//eb.life = 130;
angle = Math.PI/180 * angle; //도에서 라디안으로
//탄 속도벡터 구하기
eb.vx = Math.cos(angle)*speed;
eb.vy = Math.sin(angle)*speed;
allObjM.addChild(eb); //적탄 화면에 붙이기
eBulletArr.push(eb); //적 배열에 추가
}
function enemyMove(){ //적 이동 처리
//enemyArr내 null값 요소 제거
enemyArr = enemyArr.filter(eraseNull);
for(var i=0; i < enemyArr.length; ++i){
var em = enemyArr[i];
if(em.x > -20 && em.x-em.width < stage.stageWidth
&& em.y > -20 && em.y-em.height < stage.stageHeight){
//적이 화면내 존재시
em.x += em.vx; //기존 탄 위치 더하기 속도 벡터
em.y += em.vy;
if(em.sTimer <= 0){ //총알 발사 간격이 지났으면
var ebAngle = Math.random()*160+10; //총알 발사각도
em.top.rotation = ebAngle - em.rotation;
eBulletInit(em, ebAngle); //적 총알 발사
em.sTimer = 60; // 타이머 시간 복원
}
em.sTimer--; //타이머 시간 줄이기
}else{ //적이 화면 밖으로 나갔을 경우
enemyDestroy(em, i); //적 제거
continue; //다음으로 넘어가기
}
}
}
function eBulletMove(){ //적탄 이동 처리
//eBulletArr내 null값 요소 제거
eBulletArr = eBulletArr.filter(eraseNull);
for(var i=0; i < eBulletArr.length; ++i){
var eb = eBulletArr[i];
if(eb.x > -20 && eb.x-eb.width < stage.stageWidth
&& eb.y > -20 && eb.y-eb.height < stage.stageHeight){
//적이 화면내 존재시
eb.x += eb.vx; //기존 탄 위치 더하기 속도 벡터
eb.y += eb.vy;
}else{ //적이 화면 밖으로 나갔을 경우
eBulletDestroy(eb, i); //적 제거
continue; //다음으로 넘어가기
}
}
}
function enemyDestroy(em, id){ //적 제거 처리
arrDestroy(em, id, enemyArr);
enemyNum--;
}
function eBulletDestroy(eb, id){ //적탄 제거 처리
arrDestroy(eb, id, eBulletArr);
}
function enemyBoom(bx, by, angle=0){ //적 폭발효과 붙이기
//매개변수(x위치, y위치)
var emb = new eTankM();
emb.gotoAndPlay("boom");
emb.x = bx, emb.y = by; //위치 초기화
emb.rotation = angle; //탄 각도 발사방향으로 회전
emb.life = 30;
allObjM.addChild(emb); //화면에 붙이기
enemyBoomArr.push(emb); //배열에 추가
}
function enemyBoomProcess(){ //적 탱크 폭발효과 처리
//Arr내 null값 요소 제거
enemyBoomArr = enemyBoomArr.filter(eraseNull);
for(var i=0; i < enemyBoomArr.length; ++i){
var emb = enemyBoomArr[i];
if(emb.life){ //life 요소를 갖고 있으면
emb.life--; //매 프레임 life 줄이기
if(emb.life <= 1){ //life가 1이하가 되면
enemyBoomDestroy(emb, i); //폭발효과 제거
continue; //다음으로 넘어가기
}
}
}
}
function enemyBoomDestroy(emb, id){ arrDestroy(emb, id, enemyBoomArr); }
//************************************************************
// 마우스 처리 관련
//************************************************************
function mouseClick(e:MouseEvent){ //마우스 클릭시
elapsedTime = getTimer() - startTime;
if(elapsedTime >= shootInterval){
//이전 샷 이후 경과시간이 총알 발사제한 인터벌 통과시
elapsedTime = 0; //경과시간 초기화
rayCastTest(mouseX, mouseY);
}
startTime = getTimer(); //마지막 클릭한 시간 기억
}
function rayCastTest(mx, my){
graphics.clear();
lineDraw01(player.x, player.y, mx,my, 1, 0xFFFFFF); //마우스 클릭한 곳까지 선긋기
var dx = mx - player.x;
var dy = my - player.y;
var tangle = Math.atan2(dy, dx); //탱크 중앙과 마우스 클릭한 곳 각 구하기
player.top.rotation = tangle * 180/Math.PI; //탱크 위 터렛 회전
pbDirectInit(tangle); //총알 생성, 초기화
}
//************************************************************
// 주인공 관련
//************************************************************
function pbDirectInit(angle=0, speed=3){ //주인공 방향탄 생성 및 초기화
//매개변수(각도, 이동속도)
var pb = new tBulletM();
pb.x = player.x, pb.y = player.y; //탄 위치 초기화
pb.vx = 0, pb.vy = 0; //탄 속도벡터 초기화
pb.rotation = angle * 180/Math.PI; //탄 각도 발사방향으로 회전
pb.life = 130;
//angle += angle * Math.PI/180; //도에서 라디안으로
//탄 속도벡터 구하기
pb.vx = Math.cos(angle)*speed;
pb.vy = Math.sin(angle)*speed;
allObjM.addChild(pb); //탄 화면에 붙이기
pBulletArr.push(pb); //탄 배열에 추가
}
function pBulletMove(){ //주인공 총탄 이동 처리
//pBulletArr내 null값 요소 제거
pBulletArr = pBulletArr.filter(eraseNull);
for(var i=0; i < pBulletArr.length; ++i){
var pb = pBulletArr[i];
if(pb.x > -20 && pb.x+pb.width < stage.stageWidth
&& pb.y > -20 && pb.y+pb.height < stage.stageHeight){
//탄이 화면내 존재시
pb.x += pb.vx; //기존 탄 위치 더하기 속도 벡터
pb.y += pb.vy;
if(pb.life){ //life 요소를 갖고 있으면
pb.life--; //매 프레임 life 줄이기
if(pb.life <= 1){ //life가 1이하가 되면
pBulletDestroy(pb, i); //탄 제거
pBulletBoom(pb.x, pb.y, pb.rotation);//폭발효과 붙이기
}
}
}else{ //탄이 화면 밖으로 나갔을 경우
pBulletDestroy(pb, i); //탄 제거
continue; //다음으로 넘어가기
}
}
}
function pBulletDestroy(pb, id){ //주인공 총탄 제거 처리
arrDestroy(pb, id, pBulletArr);
}
function pBulletBoom(bx, by, angle=0){ //총탄 폭발효과 붙이기
//매개변수(x위치, y위치)
var pbb = new tBulletM();
pbb.gotoAndPlay("boom");
pbb.x = bx, pbb.y = by; //위치 초기화
pbb.rotation = angle; //탄 각도 발사방향으로 회전
pbb.life = 30;
allObjM.addChild(pbb); //화면에 붙이기
pBulletBoomArr.push(pbb); //배열에 추가
}
function pBulletBoomProcess(){ //주인공 총탄 폭발효과 처리
//pBulletArr내 null값 요소 제거
pBulletBoomArr = pBulletBoomArr.filter(eraseNull);
for(var i=0; i < pBulletBoomArr.length; ++i){
var pbb = pBulletBoomArr[i];
if(pbb.life){ //life 요소를 갖고 있으면
pbb.life--; //매 프레임 life 줄이기
if(pbb.life <= 1){ //life가 1이하가 되면
pBulletBoomDestroy(pbb, i); //폭발효과 제거
continue; //다음으로 넘어가기
}
}
}
}
function pBulletBoomDestroy(pbb, id){ arrDestroy(pbb, id, pBulletBoomArr); }
function playerDamage(){ //주인공 충돌 처리
trace("Player Hit!!!!!!!!!!");
player.gotoAndPlay("hit"); //주인공 충격 그래픽
if(pEnergy > 1){
pEnergy--; //주인공 목숨 수 줄이기
pEnergyM.gotoAndStop(pEnergy); //에너지 게이지 줄이기
}else{
trace("player Dead!!!!!!!!!");
player.gotoAndStop("hit");
gameOver(); //게임 오버 처리.
}
}
//************************************************************
// 키보드 처리 관련
//************************************************************
function keyProcessing(){ //키보드 처리
if(left && sx0 <= player.x-player.width/2){ player.x -= pSpeed; }
if(right && player.x+player.width/2 <= sx1){ player.x += pSpeed; }
if(up && sy0 <= player.y-player.height/2){ player.y -= pSpeed; }
if(down && player.y+player.height/2 <= sy1){ player.y += pSpeed; }
}
function keyDowns(e:KeyboardEvent){ //키보드 눌릴때
switch(e.keyCode){
case(37): case(65): left = true; break; //left, a
case(39): case(68): right = true; break; //right, d
case(38): case(87): up = true; break; //up, w
case(40): case(83): down = true; break; //down, s
case(17): jump = true; break; //left ctrl 점프
case(90): break; //z
case(88): break; //x
default: break;
}
}
function keyUps(e:KeyboardEvent){ //키보드 뗄 때
switch(e.keyCode){
case(37): case(65): left = false; break; //left, a
case(39): case(68): right = false; break; //right, d
case(38): case(87): up = false; break; //up, w
case(40): case(83): down = false; break; //down, s
case(107): break; //Numpad +
//case(109): break; //Numpad -
case(96): break; //Numpad 0
case(32): break; //space
case(90): break; //z
case(88): break; //x
case(67): break; //c
default: break;
}
}
//************************************************************
// 기타 도우미 함수들
//************************************************************
function arrDestroy(item, id, arr:Array){ //배열내 해당요소 제거 처리
try{
allObjM.removeChild(item); //해당 요소 화면에서 제거
}catch(er:Error){ trace("pBullet removeChild error"); }
arr[id] = null; //해당요소 배열에서 비우기 위해 null 넣어두기
}
function lineDraw01(mX,mY,tX,tY,style1=1,style2=0){ //선그리기 함수
//(mX,mY)위치로 이동, (tX,tY)까지 style(굵기,색)대로 선그리기
graphics.lineStyle(style1, style2);
graphics.moveTo(mX, mY);
graphics.lineTo(tX, tY);
}
function eraseNull(element:*,index:uint,array:Array):Boolean{
//배열 내부의 null 제거용 함수
return (element != null);
}
init();
|