trail, tailLength 변수 만들기

뱀의 몸은 여러 개의 블럭으로 이루어져 있습니다. 뱀이 상하좌우로 움직일 때 이전의 위치들을 추적하는 것이 중요합니다. trail이라는 배열을 만들어 저장하도록 하겠습니다.

현재 꼬리의 길이를 저장하는 tailLength라는 변수도 생성하도록 하겠습니다. 초기값으로 5를 지정하면 게임을 시작할 때 뱀의 블럭 수는 5개가 됩니다.

let positionX = 10, positionY = 10
const gridSize = 20, tileCount = 20

let velocityX = 0, velocityY = 0

let appleX = 15, appleY = 15

const trail = []
let tailLength = 5

 

trail 배열 갱신하기

trail 배열에 positionX, positionY의 위치를 객체 형태로 저장하는 원소들을 채워넣도록 하겠습니다. 단, tailLength 만큼의 원소를 저장하며, trail 배열의 길이가 tailLength를 초과하면 shift()를 통해 배열의 맨 앞 원소를 제거하는 작업을 해야 합니다.

function game() {
    
    // ...
    
    ctx.fillStyle = "black"
    ctx.fillRect(0, 0, canvas.width, canvas.height)

    ctx.fillStyle = "lime"
    ctx.fillRect(positionX * gridSize, positionY * gridSize, gridSize - 2, gridSize - 2)
    
    trail.push({
        x: positionX, 
        y: positionY
    })
    while(trail.length > tailLength) {
        trail.shift()
    }
    
    if(appleX === positionX && appleY === positionY) {
        appleX = Math.floor(Math.random() * tileCount)
        appleY = Math.floor(Math.random() * tileCount)
    }
    
    // ...
}

여기까지 작성해도 표면적인 변화는 없습니다. 뱀의 몸을 그리는 렌더링 부분이 제대로 작성되지 않았기 때문입니다.

 

뱀 렌더링 부분 구현

game 함수에서 뱀을 그리는 부분을 아래와 같이 변경합니다.

ctx.fillStyle = "lime"
// 삭제: ctx.fillRect(positionX * gridSize, positionY * gridSize, gridSize - 2, gridSize - 2)

for(let i = 0; i < trail.length; i++) {
    ctx.fillRect(trail[i].x * gridSize, trail[i].y * gridSize, gridSize - 2, gridSize - 2)
}

기존의 단일 position을 렌더링하던 것이 for문으로 변경되어 trail의 배열을 순회하도록 바뀌었습니다. 사이즈 부분은 변함이 없고, 프레임 당 trail의 배열을 따라 블럭을 여러 개 그립니다. 이렇게 하면 드디어 뱀 모양으로 이동하는 효과가 나타나게 됩니다.

그리고 뱀의 머리와 꼬리가 부딪혔을 때 게임오버가 되도록 합니다. 게임오버가 되면 tailLength 가 5인 처음 상황으로 돌아가도록 만듭니다.

for(let i = 0; i < trail.length; i++) {
    ctx.fillRect(trail[i].x * gridSize, trail[i].y * gridSize, gridSize - 2, gridSize - 2)
    
    if(trail[i].x === positionX && trail[i].y === positionY) {
        tail = 5
    }
}

 

 

최종 완성 코드

 


문의 | 코멘트 또는 ayaysir0@naver.com  donaricano-btn

카테고리: WEB: Frontend

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다