0. 구상
게임에서 기본적으로 등장하는 요소는 캐릭터와 장애물이다. 캐릭터는 처음 지정된 좌표 위치에 고정되어 점프할 때 y좌표만 변경된다. 장애물은 x좌표를 변경해 캐릭터쪽으로 이동시켜 마치 캐릭터가 장애물에게 가는 듯한 효과를 준다.
0) 캔버스 크기
캔버스 크기는 가로 800, 세로 260으로 설정했다.
canvas.width = 800;
canvas.height = 260;
1) 기본 배치(캐릭터, 장애물)
const character = {
x:16,
y:165,
width:45,
height:85,
draw(){
ctx.fillStyle = 'green';
ctx.fillRect(this.x,this.y,this.width,this.height);
}
}
class Flower{
constructor(){
this.name="flower";
this.x =600;
this.y = 200;
this.width =45;
this.height =50;
}
draw(){
ctx.fillStyle = 'red';
ctx.fillRect(this.x,this.y,this.width,this.height);
}
}
class Branch{
constructor(){
this.name="branch";
this.x =600;
this.y = 65 ;
this.width =45;
this.height =50;
}
draw(){
ctx.fillStyle = 'blue';
ctx.fillRect(this.x,this.y,this.width,this.height);
}
}
네모박스의 형태로 캐릭터와 장애물의 위치를 잡아준다. 이는 히트박스를 나타낸다.
장애물의 경우 충돌확인 때 상단, 하단을 구분하기 위해 this.name에 각자의 이름을 변수로 설정했다.
❔ 히트박스(hitbox / hit mark) 게임에서 위치, 공격,피탄 등을 판별하기 위해 오브젝트나 캐릭터를 둘러싸도록 만든 투명한 박스를 말한다. 히트박스가 겹치는지 매 순간 검사하는 알고리즘을 충돌 감지(Collistion Detection)라 한다. -출처: 히트박스 - 나무위키 |
1. 애니메이션 만들기
requestAnimationFrame()을 사용해서 애니메이션을 만든다. 이를 위해 frameRepeatd()라는 함수를 만들어 사용했다.
function frameRepeatd(){
requestAnimationFrame(frameRepeatd);
}
frameRepeatd()
1) 장애물 생성하기
장애물을 두 종류로 하단장애물, 상단장애물이다.
배열을 생성에 이에 장애물을 담는다. 이때 상단 또는 하단 장애물이 배열에 하나씩 담기도록 한다.
⚠ 해당 파트는 장애물이 생성되는 것이지 그리거나 이동하지 않는다.
장애물배열=[하단, 하단, 상단]
let timer =0;
let animation;
function frameRepeatd(){
animation=requestAnimationFrame(frameRepeatd);
timer++;
ctx.clearRect(0,0,canvas.width,canvas.height);
if(timer %230===0){
if(timer%920===0){
nowCollisionNum=makeRandomNum()
if(nowCollisionNum===1){ // 1이면 상단 출력
const branch = new Branch();
collisionArr.push(branch);
}else{ // 0이면 하단 출력
const flower = new Flower();
collisionArr.push(flower);
}
}else{ //기본적으로 하단 장애물 출력
const flower = new Flower();
collisionArr.push(flower);
}
}
character.draw(); //캐릭터 그리기
}
frameRepeatd();
// 0또는 1 반환
function makeRandomNum(){
const num = Math.round((Math.random()));
return num;
}
timer 설정 및 ctx.clearRect
animation변수를 만들고 이에 requestAnimationFrame(frameRepeatd);를 담는다.
시간 흐름에 따라 장애물을 담기위해 변수 timer을 만들고 프레임마다 1씩 증가되도록 한다.
ctx.clearRect(0,0,canvas.width,canvas.height)를 사용해 네모 모양으로 출력되도록 한다. 이를 사용하지 않으면 그래프가 증가하는 것처럼 이미지가 쭉 이어서 출력된다.
-ctx.clearRect(0,0,canvas.width,canvas.height) 사용 ❌
-ctx.clearRect(0,0,canvas.width,canvas.height); 사용 ⭕
장애물 생성 - 상단 or 하단
① 기본적인 장애물은 하단 장애물로 한다. timer를 230으로 나누어 떨어질 때 마다 장애물을 하나 생성한다.
② 그리고 가끔씩 상단 장애물이 나오도록 설정하기 위해 timer가 920으로 나누어 떨어질 때 상단 장애물을 나타낼지 말지 결정한다. 이는 nowCllisionNum의 값이 0이냐 1이냐에 따라 결정된다.
이를 위해 makeRandomNum()를 만들고 random()을 사용해 0또는 1을 반환한다. 이를 nowCllisionNum변수에 담는다.
timer가 920로 나누어 떨어질때 nowCllisionNum의 값이 1이면 상단 장애물을 출력하고, 0이면 하단 장애물을 출력한다.
이를 통해 가끔씩 하단 장애물 사이에 상단 장애물이 출력되게 된다.
기본적으로 하단에 장애물이 나오고 4번째에 상단에 나오는 것을 볼 수 있다. 위의 이미지는 4번째에 나오지만 실제로는 4번째에 안 나올 수 있다.
2) 장애물 이동, 삭제 및 그리기
let timer =0;
function frameRepeatd(){
/*앞 내용, 장애물 생성부분 생략*/
collisionArr.forEach((collision, i, o)=>{
collision.x--; //장애물 캐릭터 방향으로 이동
if(collision.x < 0){ //장애물 x좌표가 0미만이면 제거 (==화면을 벗어나면)
o.splice(i,1)
}
collision.draw(); //장애물 그리기
})
character.draw(); //캐릭터 그리기
}
collisionArr[]를 foreach()를 사용해 하나씩 검사한다.
collision는 장애물을 나타낸다.
① collision.x--를 통해 장애물이 캐릭터 쪽으로 이동하도록 한다.
② collision.x < 0를 통해 장애물이 화면을 벗어나면 배열에서 삭제한다.
③ collision.draw()를 통해 장애물을 그린다.
3) 장애물 충돌확인
장애물은 하단 또는 상단임으로 각각의 경우를 계산해야한다.
//충돌확인
function checkCollision(character, collision){
let checkX = collision.x - (character.x+character.width); //하단 장애물 윗면
let checkY = collision.y - (character.y+character.height); //장애물 앞면
let checkTopY = (collision.y+collision.height) - (character.y); // 상단 장애물 아랫면
if(collision.name=="flower"){
if((checkX < 0 && checkY <0)){ // 하단 장애물 확인
ctx.clearRect(0,0,canvas.width,canvas.height); //캔버스 그림 지우기
cancelAnimationFrame(animation); // requestAnimationFrame 중지
}
}else if(collision.name=="branch"){ // 상단 장애물 확인
if((checkX < 0 && checkTopY >0)){
ctx.clearRect(0,0,canvas.width,canvas.height); //캔버스 그림 지우기
cancelAnimationFrame(animation); // requestAnimationFrame 중지
}
}
}
⑴ 공통
상단, 하단 장애물 둘다 공통적으로 계산되는 부분은 x축의 충돌이다.
x축의 경우 캐릭터의 오른쪽면과 장애물의 왼쪽면이 만나면 충돌한 것으로 계산한다.
☝ 그림의 보라색 선
⑵ 하단 장애물
하단 장애물 충돌은 앞서 언급한 x축이 충돌하고, 장애물의 윗면과 캐릭터의 아랫면이 만나면 충돌한 것으로 계산한다.
☝ 그림의 하늘색 선
⑶ 상단 장애물
상단 장애물 충돌은 앞서 언급한 x축이 충돌하고, 장애물의 아랫면과 캐릭터의 윗면이 만나면 충돌한 것으로 계산한다.
☝ 그림의 주황색 선
Reference
'PROGAMMING > Project' 카테고리의 다른 글
[Javascript / Canvas] 크롬 공룡게임 따라서 게임 만들기 #4 - 게임 속도 증가 (0) | 2023.09.03 |
---|---|
[Javascript / Canvas] 크롬 공룡게임 따라서 게임 만들기 #3 - 타이머, 점수, 게임오버 및 재시작 표시 (0) | 2023.08.29 |
[Javascript / Cavas] 크롬 공룡게임 따라서 게임 만들기 #2 - 조작, 캐릭터 디자인, 움직이는 배경 (0) | 2023.08.11 |
[Javascript / Cavas] 크롬 공룡게임 따라서 게임 만들기 #0 (0) | 2023.06.23 |