안녕하세요. 온라인 Snake 게임 개발 교육과정의 네 번째 시간입니다. 오늘은 프론트엔드를 배워 볼 시감입니다. Canvas를 이용한 게임 렌더링과 사용자 인터페이스 디자인에 대해 알아보겠습니다.
1. HTML 구조 설정
먼저 기본적인 HTML 구조를 만들어 봅시다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Multiplayer Snake Game</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="gameContainer">
<div id="menu">
<button id="createRoom">Create Room</button>
<input type="text" id="roomCodeInput" placeholder="Enter Room Code">
<button id="joinRoom">Join Room</button>
</div>
<canvas id="gameCanvas"></canvas>
<div id="playerInfo"></div>
</div>
<script src="/socket.io/socket.io.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
<script src="game.js"></script>
</body>
</html>
2. CSS 스타일링
게임의 외관을 개선하기 위해 CSS를 적용합니다.
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f0f0f0;
}
#gameContainer {
text-align: center;
}
#menu {
margin-bottom: 20px;
}
button {
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
}
input {
padding: 10px;
font-size: 16px;
}
#gameCanvas {
border: 2px solid #333;
}
#playerInfo {
margin-top: 20px;
font-size: 18px;
}
3. Canvas 설정 및 게임 렌더링
p5.js 라이브러리를 사용하여 게임을 렌더링합니다.
let canvas;
const canvasSize = 400;
const gridSize = 20;
function setup() {
canvas = createCanvas(canvasSize, canvasSize);
canvas.parent('gameCanvas');
frameRate(10);
}
function draw() {
background(51);
if (gameState) {
drawFood();
drawPlayers();
}
}
function drawFood() {
fill(255, 0, 0);
for (let food of gameState.foods) {
rect(food.x * gridSize, food.y * gridSize, gridSize, gridSize);
}
}
function drawPlayers() {
for (let player of gameState.players) {
if (player.alive) {
fill(player.color);
for (let segment of player.segments) {
rect(segment.x * gridSize, segment.y * gridSize, gridSize, gridSize);
}
}
}
}
4. 사용자 인터페이스 및 게임 상태 표시
게임 상태와 플레이어 정보를 표시하는 기능을 추가합니다.
function updatePlayerInfo() {
const playerInfoDiv = document.getElementById('playerInfo');
playerInfoDiv.innerHTML = '';
if (gameState) {
gameState.players.forEach((player, index) => {
const playerDiv = document.createElement('div');
playerDiv.textContent = `Player ${index + 1}: ${player.score}`;
playerDiv.style.color = player.color;
playerInfoDiv.appendChild(playerDiv);
});
}
}
socket.on('gameState', (newGameState) => {
gameState = newGameState;
updatePlayerInfo();
});
5. 반응형 디자인 적용
다양한 화면 크기에 대응할 수 있도록 반응형 디자인을 적용합니다.
@media (max-width: 600px) {
#gameContainer {
width: 100%;
}
#gameCanvas {
width: 100%;
height: auto;
}
button, input {
width: 100%;
margin-bottom: 10px;
}
}
6. 터치 컨트롤 추가
모바일 기기에서도 게임을 즐길 수 있도록 터치 컨트롤을 추가합니다.
let touchStartX = 0;
let touchStartY = 0;
function touchStarted() {
touchStartX = mouseX;
touchStartY = mouseY;
return false;
}
function touchEnded() {
const diffX = mouseX - touchStartX;
const diffY = mouseY - touchStartY;
if (Math.abs(diffX) > Math.abs(diffY)) {
if (diffX > 0) {
changeDirection('RIGHT');
} else {
changeDirection('LEFT');
}
} else {
if (diffY > 0) {
changeDirection('DOWN');
} else {
changeDirection('UP');
}
}
return false;
}
function changeDirection(direction) {
socket.emit('changeDirection', { roomCode, direction });
}
7. 게임 오버 화면 구현
게임이 종료되었을 때 결과를 표시하는 화면을 추가합니다.
function showGameOver(winners) {
const gameOverDiv = document.createElement('div');
gameOverDiv.id = 'gameOver';
gameOverDiv.innerHTML = `
<h2>Game Over</h2>
<p>Winner: Player ${winners[0].number}</p>
<button onclick="restartGame()">Play Again</button>
`;
document.body.appendChild(gameOverDiv);
}
function restartGame() {
document.getElementById('gameOver').remove();
socket.emit('restartGame', roomCode);
}
socket.on('gameOver', (winners) => {
showGameOver(winners);
});
결론
이번 포스팅에서는 프론트엔드 개발에 초점을 맞추어 Canvas를 이용한 게임 렌더링, 사용자 인터페이스 디자인, 반응형 웹 디자인, 그리고 터치 컨트롤 구현 등을 다뤘습니다. 이러한 요소들은 사용자 경험을 크게 향상시키고, 다양한 디바이스에서 게임을 즐길 수 있게 해줍니다.
다음 포스팅에서는 백엔드 서버 구축에 대해 더 자세히 알아보겠습니다. Express.js를 이용한 서버 설정과 RESTful API 구현에 대해 다루겠습니다. 감사합니다!