첫 번째 프로젝트 - BLACK MAMBA (1)

JooYong Lee·2021년 11월 19일
0

BLACK MAMBA

목록 보기
1/5
post-thumbnail
  • 목표

    • Black Mamba 피하기 게임을 구현하며 JavaScript에 익숙해지기
  • 게임 설명

    • 뱀(Black Mamba)이 랜덤한 방향으로 스스로 돌아다닌다.
    • User는 방향키를 사용해 뱀을 피해 이동한다.
    • 필드에 랜덤하게 등장하는 보석을 7개 모아야한다.
    • 일정 시간이 주어지고 시간 안에 모두 모으면 성공.
  • 구현할 내용

    1. 오프닝
      1. 25*25 필드에 BLACK MAMBA 글씨가 나타남
      2. start 버튼을 누르면 게임에 필요한 것들이 추가로 나타남 (화상 키보드, 타이머)
    2. 게임
      1. 블랙 맘바 3마리가 필드에 돌아다님
      2. 유저는 키보드 방향키 또는 화상 방향키로 이동하며 보석을 모음
      3. 뱀에 닿으면 실패
      4. 보석은 총 7개이고 랜덤한 위치에 차례대로 나타남
      5. 보석을 1개 먹을 때 마다 블랙 맘바가 추가됨
    3. 엔딩
      1. 보석을 모두 모으면 종료
      2. 25*25 필드가 다양한 색깔들로 채워지며 마무리

게임이라고는 하지만 아주 옛날 조그만 게임기에서 봤을 법한 수준의 귀여운 느낌으로 만들 예정이다. (25*25크기의 게임 화면)

우선 가장 중요한 뱀을 구현해보기로 했다.

먼저 내가 생각한 로직은 다음과 같다.
1. 웹 상에 보여지는 테이블이 있고, 뱀과 유저, 보석, 빈 땅이 기록되는 2차원 배열이 있다.
2. 배열에 우선적으로 기록이 되고 이후에 화면에 표시를 해준다.
3. 뱀은 일정 시간 단위로 이동을 하는데 방향은 랜덤으로 한다.

자세한 내용은 코드와 함께 설명하는게 좋을 것 같다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Black Mamba</title>
</head>
<body>
    <table border="1" width="500" height="500" id="game-board"></table>

    <script src="js/blmam.js"></script>
</body>
</html>

index.html 이고 아무 내용없다. 게임 필드를 table로 만들었다.

function makeBoard(){
    const gameboard = document.getElementById("game-board");
    
    for (let i = 0; i<25; i++){
        const tr = document.createElement("tr");
        for (let j = 0; j<25; j++){
            const td = document.createElement("td");
            td.id = `${i},${j}`;
            tr.appendChild(td);
        }
        gameboard.appendChild(tr);
    }
}
makeBoard();

table을 25*25 크기로 만들기 위한 함수다. 먼저 table을 가져온 뒤에 테이블의 행와 열 속성을 만들어 추가해주었다.

board = new Array(25);
for (let i = 0; i<25; i++){
    board[i] = new Array(25);
}
for (let i=0;i<25;i++){
    for (let j=0; j<25; j++){
        board[i][j] = 0;
    }
}

위에서 얘기했던 2차원 배열이다. 0은 빈 땅, 1은 뱀, 2는 유저, 3은 보석으로 기록할 예정이다.

const snake = [ [0, 0], [0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [0, 6], [0, 7], [0, 8] ];
function drawSnake(){
    for (let i = 0; i < snake.length; i++){
        board[snake[i][0]][snake[i][1]] = 1;
        const block = document.getElementById(snake[i]);
        block.style.backgroundColor = "black";
    }
}
drawSnake();

snake 배열을 만들어 뱀이 있는 위치를 모두 담아주었다.
처음 뱀 한 마리를 그려준다. 왼쪽 위에 자리잡고 있고 단순히 검정색으로 칠해주었다.

const dx = [0, 1, 0, -1];
const dy = [1, 0, -1, 0];
function moveSnake(){
    const snakeHead = snake[snake.length - 1]; //뱀의 머리
    while (true){ //전진할 수 있는 방향을 찾을 때 까지 반복한다
        const next_dir = Math.floor(Math.random() * 10) % 4; //0~3 중 랜덤으로 선택
        const nextX = snakeHead[0]+dx[next_dir]; //코드가 길어 변수에 담아주었다.
        const nextY = snakeHead[1]+dy[next_dir];
      //nextX, nextY -> 다음으로 전진할 위치
        if (0<=nextX && nextX<25 && 0<=nextY && nextY<25){
            if (board[nextX][nextY] !== 1){ //다음 전진할 위치가 필드 범위 안에 있으면서 뱀의 몸이 아닌 경우
                snake.push([nextX, nextY]); //전진
                const snakeTail = snake.shift(); //뱀의 꼬리
                document.getElementById(`${snakeTail[0]},${snakeTail[1]}`).style.backgroundColor = "white";
                board[snakeTail[0]][snakeTail[1]] = 0;
              //꼬리 부분을 정리해준다.
                drawSnake(); //뱀을 새로 그려준다
                return;
            }
        }
    }
}
setInterval(moveSnake, 100); //0.1초 단위로 뱀을 이동시킨다

뱀이 이동하도록 해주는 함수이다. bfs를 구현하던 것을 한껏 적용해주었다.
뱀의 머리 부분을 snake배열의 가장 마지막 부분으로 지정해주었다.
뱀의 머리를 기준으로 상하좌우를 살피며 빈 땅인 곳을 찾고 전진한다.
단, 상하좌우는 랜덤으로 결정해주어 뱀이 어느 방향으로 갈지 예측할 수 없게 했다.
필드 범위 안에 있으면서 뱀의 몸이 아닌 경우 (1이 아니라면) snake 배열에 전진할 칸의 좌표를 push 해주고, 꼬리 부분은 pop (shift)해준다.

이 과정에서 몇번의 시행착오가 있었다.
처음에는 뱀이 전진을 하는데 꼬리 부분을 지워주지 않아서 뱀이 계속 길어져버렸다.
그 다음에는 board에 뱀의 위치를 1로 기록해둔 것을 이동하면서 뱀이 있는 곳이 아니면 다시 0으로 바꿔줘야 하는데 이것을 빼먹어서 뱀이 어느정도 가다가 끼어버렸다.

아직 수정해야할 부분이 많다.

우선 해결해야할 내용들.
1. 뱀이 구석이나 스스로의 몸에 갇혀 멈춰버리는 버그가 있다.
2. 코드에서 비효율적인 부분들을 수정해야한다.

해결하고 난 뒤에 진행할 내용.
1. 뱀 여러마리가 돌아다니도록 한다.
2. 유저를 추가하고 키보드로 조종할 수 있도록 한다.
3. 유저와 뱀이 닿으면 게임 종료가 되도록 한다.
4. 타이머를 추가하고 일정 시간동안만 플레이되도록 한다.
5. 보석이 랜덤 위치에서 등장하며 유저가 습득할 수 있도록 한다.
6. 보석을 하나 먹을 때 마다 뱀이 추가가 된다.
7. 시간안에 보석 7개를 모두 모으면 엔딩으로 넘어간다.

게임에 직접적으로 관련된 내용을 먼저 구현한 뒤에 오프닝과 엔딩을 추가할 예정이다.

profile
21.11.01~ 기록

0개의 댓글