728x90
안녕하세요!
오늘은 자바스크립트를 사용해 클래식한 스네이크 게임을 만드는 방법을 알려드리겠습니다.
1. index.html 작성
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Snake Game</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f0f0f0;
}
canvas {
background-color: #fff;
border: 2px solid #333;
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="400" height="400"></canvas>
<script src="snake.js"></script>
</body>
</html>
- canvas 태그를 사용해 스네이크 게임을 그릴 공간을 마련합니다.
- id를 통해 JavaScript에서 이 캔버스를 쉽게 접근할 수 있도록 설정했습니다.
- style 태그로 배경색과 캔버스 테두리를 설정해 간단한 디자인을 적용했습니다.
2. 스네이크와 음식의 초기 상태 정의
이제 snake.js 파일을 생성하고, 스네이크와 음식의 초기 상태를 정의해보겠습니다.
// 캔버스 설정
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// 게임 설정
const gridSize = 20; // 한 칸의 크기
let snake = [{ x: 100, y: 100 }]; // 스네이크의 초기 위치
let food = { x: 200, y: 200 }; // 음식의 초기 위치
let dx = gridSize; // x축 이동 방향 (오른쪽으로 시작)
let dy = 0; // y축 이동 방향 (세로 이동 없음)
let gameOver = false; // 게임 종료 상태 변수
let growing = false; // 스네이크가 자라는 중인지 상태를 관리
- 스네이크는 배열로 관리하며, 각 요소는 스네이크의 몸 부분을 나타냅니다.
- food는 음식의 위치를 나타내고, dx와 dy는 스네이크의 이동 방향을 관리합니다.
- gameOver 변수는 게임 종료 상태를, growing 변수는 스네이크가 자라는 상태를 관리합니다.
3. 스네이크와 음식 그리기
스네이크와 음식을 캔버스에 그리는 함수를 작성합니다.
// 스네이크와 음식을 그리는 함수
function drawSnake() {
ctx.fillStyle = 'green';
snake.forEach(part => {
ctx.fillRect(part.x, part.y, gridSize, gridSize);
});
}
function drawFood() {
ctx.fillStyle = 'red';
ctx.fillRect(food.x, food.y, gridSize, gridSize);
}
// 초기 화면 그리기
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height); // 화면 지우기
drawSnake();
drawFood();
}
- drawSnake() 함수는 스네이크의 각 부분을 forEach로 순회하며 그립니다.
- drawFood() 함수는 캔버스에 음식의 위치를 그립니다.
- draw() 함수는 화면을 매번 지우고, 스네이크와 음식을 새로 그립니다.
4. 스네이크 움직이기
스네이크가 방향키를 누를 때마다 이동하도록 설정합니다.
// 스네이크 이동 함수
function moveSnake() {
const head = { x: snake[0].x + dx, y: snake[0].y + dy };
snake.unshift(head);
// 스네이크가 자라지 않는다면 꼬리 제거
if (!growing) {
snake.pop();
} else {
growing = false; // 자라기를 완료했으니 다시 false로 설정
}
}
// 방향 변경 함수
function changeDirection(event) {
const keyPressed = event.keyCode;
const LEFT = 37;
const UP = 38;
const RIGHT = 39;
const DOWN = 40;
if (keyPressed === LEFT && dx === 0) {
dx = -gridSize;
dy = 0;
} else if (keyPressed === UP && dy === 0) {
dx = 0;
dy = -gridSize;
} else if (keyPressed === RIGHT && dx === 0) {
dx = gridSize;
dy = 0;
} else if (keyPressed === DOWN && dy === 0) {
dx = 0;
dy = gridSize;
}
}
// 키보드 이벤트 리스너 추가
document.addEventListener('keydown', changeDirection);
- moveSnake() 함수는 스네이크의 새로운 머리 위치를 계산하고, growing에 따라 꼬리를 제거하거나 유지합니다.
- changeDirection() 함수는 방향키 입력에 따라 스네이크의 이동 방향을 변경합니다.
5. 음식 먹기와 길이 증가
스네이크가 음식을 먹었을 때 길이가 증가하도록 설정합니다.
// 음식 먹기 함수
function checkFoodCollision() {
if (snake[0].x === food.x && snake[0].y === food.y) {
// 음식 먹으면 스네이크가 자라도록 설정
growing = true;
placeFood();
}
}
// 랜덤 위치에 음식 배치
function placeFood() {
food.x = Math.floor(Math.random() * canvas.width / gridSize) * gridSize;
food.y = Math.floor(Math.random() * canvas.height / gridSize) * gridSize;
}
- 스네이크의 머리가 음식 위치와 일치할 때 growing을 true로 설정하여 길이를 증가시킵니다.
- placeFood() 함수는 랜덤한 위치에 음식을 새로 생성합니다.
6. 벽 또는 자기자신과 충돌 처리
스네이크가 벽이나 자신의 몸에 부딪히면 게임이 종료되도록 설정합니다.
// 벽 충돌 확인 함수
function checkWallCollision() {
const head = snake[0];
if (
head.x < 0 || head.x >= canvas.width ||
head.y < 0 || head.y >= canvas.height
) {
gameOver = true;
}
}
// 몸 충돌 확인 함수
function checkSelfCollision() {
const head = snake[0];
for (let i = 1; i < snake.length; i++) {
if (head.x === snake[i].x && head.y === snake[i].y) {
gameOver = true;
}
}
}
// 게임 오버 메시지 표시 함수
function displayGameOver() {
ctx.fillStyle = 'black';
ctx.font = '30px Arial';
ctx.fillText('Game Over', canvas.width / 2 - 80, canvas.height / 2);
}
7. 게임 루프 작성하기
게임이 계속 진행되도록 루프를 작성하고, 게임 오버 시 메시지를 표시합니다.
// 게임 루프
function gameLoop() {
if (gameOver) {
displayGameOver();
return;
}
moveSnake();
checkFoodCollision();
checkWallCollision();
draw();
checkSelfCollision();
setTimeout(gameLoop, 100);
}
gameLoop();
- gameLoop() 함수는 0.1초마다 게임 상태를 업데이트하고, 스네이크의 이동 및 충돌 상태를 체크합니다.
- 게임 오버 시 displayGameOver() 함수를 호출하여 게임 종료 메시지를 표시합니다.
'JavaScript' 카테고리의 다른 글
[JavaScript] Leaflet를 활용한 OpenStreetMap 지도 출력하기 (2) | 2024.10.28 |
---|---|
[JavaScript] 스네이크 게임 완성도 올리기 (0) | 2024.10.25 |
[JavaScript] 비행기 슈팅 게임 만들기 - (5) 점수, 목숨, 다시 시작 구현 (2) | 2024.10.10 |
[JavaScript] 비행기 슈팅 게임 만들기 - (4) 충돌 감지와 게임 오버 (2) | 2024.10.04 |
[JavaScript] 비행기 슈팅 게임 만들기 - (3) 총알 발사하기 (2) | 2024.09.28 |