Notice
Recent Posts
Recent Comments
Link
250x250
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- form
- 프레임 워크
- Context API
- useState
- CSS
- Fe
- 협업
- 오블완
- 브라우저 동작
- Study
- react-query
- github
- polling
- 코딩 테스트
- Pr
- 개발자
- 회고록
- tailwind css
- 개발
- js
- prettier
- next.js
- PullRequest
- frontend
- 사과게임
- eslint
- 티스토리챌린지
- zustand
- 비제어
- react
Archives
- Today
- Total
ougi FE
javascript로 사과게임을 만들어보자! 본문
728x90
안녕하세요 오늘은 제가 최근에 제가 좋아하는 게임인 사과게임을 따라서 만들어보았는데
이 게임을 만드는 과정에 대해서 글을 써보고 싶어 이렇게 글을 써보게 되었습니다
저는 토마토 버전으로 만들어보았습니다 ㅎㅎ
사과 게임 소개
사과게임이란 주어진 시간 안에 랜덤한 숫자 값이 들어있는 사과들을 없애는 것이 목표인 게임인데
사과를 없앨 수 있는 조건은 드래그 해서 생긴 네모 칸 안에 숫자 값들이 합해서 10이 되는게 조건입니다
사과 한개 당 1점을 받습니다
만드는 과정
과정을 나누어 보자면 크게 이렇게 나누어 구현 했던 것 같습니다
- 시간 타이머 바 구현하기
- 토마토들에 1-9까지 랜덤한 값을 주어 canvas에 그리기
- 드래그하면 네모 칸 만들어지게 하기
- 네모 칸 안에 숫자들이 10 되는지 확인하고 되면 사과를 없애고 점수 올라가게 구현하기
시간 타이머 바 구현하기
const maxGage = document.querySelector(".max"); // 최대 게이지
const currentGage = document.querySelector(".cur"); // 현재 게이지
let time = 100; // 남은 시간
function countDown() {
setInterval(() => {
currentGage.style.height = `${time}%`; // 현재 게이지의 높이 시간%로 업데이트
time--;
if (time === 0) { // 시간이 다 지나면 점수 알려주고 다시 초기화
alert("Game Over! " + curScore + "점을 획득하셨습니다.");
location.reload();
}
}, 1000);
}
document.addEventListener("DOMContentLoaded", () => { // load 되면 바로 count
countDown();
});
토마토들에 1-9까지 랜덤한 값을 주어 canvas에 그리기
function drawTomatoes() {
tomatoes.forEach(({ x, y, number }) => { // 구조 분해 할당
const tomatoSize = 52; // 토마토 크기
ctx.drawImage(tomato, x, y, tomatoSize, tomatoSize); // 토마토 그리기
ctx.font = "20px"; // 글씨 크기
ctx.fillStyle = "white"; // 글씨 색
ctx.textAlign = "center"; // 수평 가운데 정렬
ctx.textBaseline = "middle"; // 수직 가운데 정렬
const numberX = x + tomatoSize / 2; // 숫자 x 위치
const numberY = y + tomatoSize / 2; // 숫자 y 위치
ctx.fillText(number, numberX, numberY); // 글자 그리기
});
}
function drawCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawTomatoes();
}
// 토마토 초기화
tomato.onload = () => {
const canvasWidth = 800;
const canvasHeight = 500;
const margin = 8;
canvas.width = canvasWidth * (window.devicePixelRatio || 1);
canvas.height = canvasHeight * (window.devicePixelRatio || 1);
canvas.style.width = `${canvasWidth}px`;
canvas.style.height = `${canvasHeight}px`;
ctx.scale(window.devicePixelRatio || 1, window.devicePixelRatio || 1);
const tomatoSize = 52;
const rows = Math.floor((canvasHeight - margin) / (tomatoSize + margin));
const cols = Math.floor((canvasWidth - margin) / (tomatoSize + margin));
for (let row = 0; row < rows; row++) {
for (let col = 0; col < cols; col++) {
const x = col * (tomatoSize + margin) + margin;
const y = row * (tomatoSize + margin) + margin;
const randomNumber = Math.floor(Math.random() * 9) + 1; // 1~9
tomatoes.push({ x, y, number: randomNumber });
}
}
drawCanvas();
};
드래그 이벤트 감지해서 네모 칸 만들고 점수 계산하기
// 드래그 시작
canvas.addEventListener("mousedown", (e) => {
drag = true;
const rect = canvas.getBoundingClientRect();
startX = e.clientX - rect.left;
startY = e.clientY - rect.top;
});
// 드래그 중
canvas.addEventListener("mousemove", (e) => {
if (drag) {
const rect = canvas.getBoundingClientRect();
curX = e.clientX - rect.left;
curY = e.clientY - rect.top;
drawCanvas();
ctx.strokeStyle = "red";
ctx.lineWidth = 2;
ctx.strokeRect(
Math.min(startX, curX),
Math.min(startY, curY),
Math.abs(curX - startX),
Math.abs(curY - startY)
);
}
});
// 드래그 완료
canvas.addEventListener("mouseup", () => {
drag = false;
// Calculate the rectangle bounds
const rectX = Math.min(startX, curX);
const rectY = Math.min(startY, curY);
const rectWidth = Math.abs(curX - startX);
const rectHeight = Math.abs(curY - startY);
// 안에 있는 토마토만 거르기
const insideTomatoes = tomatoes.filter(({ x, y }) => {
const tomatoSize = 52;
return (
x >= rectX &&
x + tomatoSize <= rectX + rectWidth &&
y >= rectY &&
y + tomatoSize <= rectY + rectHeight
);
});
// 더하기
const sum = insideTomatoes.reduce((acc, cur) => acc + cur, 0);
// sum이 10인지 확인
if (sum === 10) {
// 지우기
const remainingTomatoes = tomatoes.filter(
(tomato) => !insideTomatoes.includes(tomato)
);
// 점수 업데이트
curScore += insideTomatoes.length;
score.textContent = curScore;
tomatoes.length = 0;
tomatoes.push(...remainingTomatoes); // 남은 토마토 다시 넣기
drawCanvas();
}
drawCanvas();
});
글을 마치며
제가 만든 토마토 게임의 링크는 https://tomato-game-kappa.vercel.app
진짜 사과게임의 링크는 https://www.gamesaien.com/game/fruit_box_a/
참고한 글 https://github.com/Yejin-Han/peach_game
JS로 게임은 처음 만들어본 것인데 만드는 동안 꽤 재미를 많이 느꼈던 것 같습니다
글을 읽어주셔서 감사합니다
728x90
'JavaScript' 카테고리의 다른 글
[JavaScript] Shadow DOM이란 뭘까? (1) | 2024.11.26 |
---|---|
Closure(클로저)가 뭘까? (4) | 2024.11.15 |
package.json? package-lock.json? 무슨 차이일까? (1) | 2024.11.10 |
[코딩 테스트] (제일 작은 수 제거하기) 나의 첫 코딩 테스트 트러블 슈팅!! ⚽(+ shift, sort, pop, splice, Math.min) (1) | 2024.09.28 |
[JavaScript] Cropper.js가 뭘까? ✂️ (2) | 2024.09.11 |