Flash CS4 + ActionScript 3.0로 만든 틈새탄
발사.
주인공기는 마우스를 따라다니게 하다.
타이머로 2초마다 적기에서 틈새탄을 발사하게 하다.
적탄은 화면을 나가면 제거되게 하다.
-----------------------------------------------------------------------------
Flash CS4로 '게임 매니악스 탄막게임 알고리즘' 중 6-4 틈새탄 예제 참고하여 만들기.
n-way탄의 변형.
n-way탄의 발사간격, 총알수, 총알간 각도와 속도를 조절하여 만들었다.
매번 발사할 때 마다 발사각도를 랜덤으로 바꿔 주는 방식으로 구현.
핵심은 매번 발사각도를 랜덤으로 바꿔 주는 것과 n-way탄
설정을 조절하는 것.
발사되는 총알의 각도를 발사 방향으로 바꿔주는 기능 추가.
15/6/18 목
* 한데 탄들의 속도와 간격이 균일하지 않고 미묘하게 들쭉날쭉하다.(특히 탄 간 간격이 아주 밀집되게 발사할
경우는 심하게 드러난다) 이건 액션스크립트의 한계인지, 정수와 소수간 변환시 날아가는 정확성 문제인지, 알고리즘
문제인지 잘 모르겠다.
* 그외 방향탄과 소용돌이탄도 코드상에 회색으로 남겨 두었다.
|
화면에 'playerM', 'enemyM'이란 이름의 주인공과 적 무비클립을
배치해 두고 'eBullet02M'이란 익스포트명의 적 총알 무비클립을 라이브러리에 만들어 두다.
var player = playerM; //화면상 플레이어 무비클립
var enemy = enemyM; //화면상 적 무비클립
var ebSpeed=2; //적탄 이동 속도
var ebTheta = -90;//적탄 발사 각도 초기화
var eBulletArr:Array=new Array();
var eBulletTimer:Timer=new Timer(2000); //적탄 발사 타이머(2초)
function init(){
Mouse.hide(); //마우스 커서 감추기
player.startDrag(true); //주인공 마우스 커서 따라다니게 하기
stage.addEventListener(Event.ENTER_FRAME, loop);
eBulletTimer.addEventListener(TimerEvent.TIMER, eBulletInit);
eBulletTimer.start(); //적탄 발사 타이머 시작
}
function loop(e:Event){ //기본 루프
eBulletMove(); //적탄 움직임 처리 함수 호출
}
function eBulletInit(e:TimerEvent){ //타이머 종료시
//적탄 중심 탄환 속도벡터 구하기
var vx0 = Math.cos(Math.PI/180 * ebTheta)*ebSpeed;
var vy0 = Math.sin(Math.PI/180 * ebTheta)*ebSpeed;
ebTheta=Math.random()*180+180;
eBulletNwayInit(40, 8, vx0, vy0, [],[],[]);
}
//function eBulletInit(e:TimerEvent){ //타이머 종료시
// //ebDirectInit(90);
// ebSpiralInit(0, 0.5, 2);
// ebSpiralInit(90, 0.5, 2.5);
// ebSpiralInit(180, 0.5, 3);
// ebSpiralInit(270, 0.5, 1);
//}
function eBulletNwayInit(bulletNum, bbTheta, vx0, vy0, vxArr, vyArr, radArr){
//적 N-way탄 생성 및 초기화
//(탄환 수, 탄환 간 각도, 중심이되는 탄환속도(vx0,vy0),
// n-way탄의 속도 x,y 배열(vxArr,vyArr),탄방향각도 배열)
//탄환 간 각도를 라디안으로 변환
var radStep = Math.PI/180*bbTheta;
//가장자리 탄환과 중심부분 탄환 간 각도 계산
var rad = (-bulletNum/2+0.5)*radStep;
var cosRad, sinRad;
//bulletNum개의 탄환 속도 계산하기
for(var i=0; i < bulletNum; i++, rad+=radStep){
//(vx[i], vy[i]) 구하기
//속도벡터 (vx0, vy0)를 rad만큼 회전시키기
cosRad = Math.cos(rad);
sinRad = Math.sin(rad);
vxArr[i]=vx0*cosRad - vy0*sinRad;
vyArr[i]=vx0*sinRad + vy0*cosRad;
radArr[i] = Math.atan2(vyArr[i],vxArr[i]); //탄 방향용
}
for(var j=0; j < bulletNum; j++){//적탄 생성,속도부여,배열추가
var eb = new eBullet02M();
eb.x = enemy.x, eb.y = enemy.y; //적탄 위치 초기화
eb.vx = 0, eb.vy = 0; //적탄 속도벡터 초기화
eb.rotation = radArr[j]*180/ Math.PI;//라디안에서 도로
//적탄 속도벡터 배열에서 적용하기
eb.vx = vxArr[j];
eb.vy = vyArr[j];
stage.addChild(eb); //적탄 화면에 붙이기
eBulletArr.push(eb); //적탄 배열에 추가
}
}
//function ebDirectInit(angle=0, speed=2){ //적 방향탄 생성 및 초기화
// //매개변수(각도, 이동속도)
// var eb = new eBullet01M();
// eb.x = enemy.x, eb.y = enemy.y; //적탄 위치 초기화
// eb.vx = 0, eb.vy = 0; //적탄 속도벡터 초기화
//
// angle += Math.PI/180 * angle; //도에서 라디안으로
// //적탄 속도벡터 구하기
// eb.vx = Math.cos(angle)*speed;
// eb.vy = Math.sin(angle)*speed;
//
// stage.addChild(eb); //적탄 화면에 붙이기
// eBulletArr.push(eb); //적탄 배열에 추가
//}
//적 소용돌이탄 생성 및 초기화
//function ebSpiralInit(angle=0, angleRate=0.5, speed=2){
//매개변수(발사각도, 발사 각속도(+:시계방향, -:시계반대방향), 발사 속도)
// var eb = new eBullet01M();
// eb.x = enemy.x, eb.y = enemy.y; //적탄 위치 초기화
// eb.vx = 0, eb.vy = 0; //적탄 속도벡터 초기화
//
// ebTheta += angleRate;
// //적탄 속도벡터 구하기
// eb.vx = Math.cos(ebTheta)*speed;
// eb.vy = Math.sin(ebTheta)*speed;
//
// stage.addChild(eb); //적탄 화면에 붙이기
// eBulletArr.push(eb); //적탄 배열에 추가
//}
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 < stage.stageWidth
&& eb.y > -20 && eb.y < stage.stageHeight){
//적탄이 화면내 존재시
eb.x += eb.vx; //기존 적탄 위치 더하기 속도 벡터
eb.y += eb.vy;
}else{ //적탄이 화면 밖으로 나갔을 경우
try{
stage.removeChild(eb); //적탄 화면에서 제거
}catch(er:Error){ trace("removeChild error"); }
eBulletArr[i] = null; //적탄 배열서 비우기 위해 null 넣기
continue; //다음으로 넘어가기
}
}
}
function eraseNull(element:*,index:uint,array:Array):Boolean{
//배열 내부의 null 제거용 함수
return (element != null);
}
init(); |