HTML + JS + jQuery로 공튀기기 게임을 만들어 보았습니다.
아래 HTML코드 실행 시 바로 플레이 해볼 수 있습니다.
canvasWidth, canvasHeight, speed 값 등을 변경하여
게임 내부 설정을 변경할 수 있습니다
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>공튀기기기</title>
<script src="jQuery.js"></script>
<script>
$(function () {
// 게임 맵 크기 설정
const canvasWidth = 500;
const canvasHeight = 500;
const paper = document.getElementById("c");
paper.width = canvasWidth;
paper.height = canvasHeight;
const pen = paper.getContext("2d");
// 공 이미지 객체 생성, 이미지 경로 설정
const ballImg = new Image();
ballImg.src = "img/ball.png";
// 공 크기
const ballSize = 30;
// 점수 저장 변수
let score = 0;
// 점수 여러번 획득되는 버그 방지
let isScored = false;
// 플레이어 박스 x좌표
let xPlayer = 0;
// 박스 가로, 세로 크기
const paddleWidth = 160
const paddleHeight = 20;
// 공 처음 스폰 위치
let ballX = 100, ballY = 5;
// 이동 방향
let xMove = 1, yMove = 1;
// 이동 속도
let speed = 7;
const resetSpeed = speed;
// 이동 방향, 속도 정규화
function normalizeVector() {
const normVec = Math.sqrt(xMove * xMove + yMove * yMove);
xMove /= normVec;
yMove /= normVec;
}
// 점수 업데이트 및 표시
function updateScore(isGet) {
score = isGet ? score + 1 : 0;
// 1점씩 오르면 감질맛 나니까 10점씩 상승.
$("h2").text("점수 : " + score * 10);
}
$("canvas").mousemove(function (e) {
xPlayer = Math.min(e.pageX, canvasWidth - paddleWidth); // 오른쪽 끝 이동 제한
$("h3").text("Mouse: " + xPlayer); // 좌표 확인용
});
// 시작할때 정규화 한번
normalizeVector();
// 이미지 로딩되면,
ballImg.onload = function () {
function gameLoop() {
pen.save();
pen.fillStyle = "#00000011";
pen.fillRect(0, 0, canvasWidth, canvasHeight);
pen.shadowOffsetX = 0;
pen.shadowOffsetY = 0;
pen.shadowBlur = 10;
pen.shadowColor = "red";
// 공 이동
ballX += xMove * speed;
ballY += yMove * speed;
pen.drawImage(ballImg, ballX, ballY, ballSize, ballSize);
// 플레이어 박스 그리기
pen.shadowColor = "white";
pen.fillStyle = "green";
pen.fillRect(xPlayer, canvasHeight - 50, paddleWidth, paddleHeight);
pen.restore();
// 벽 충돌
if (ballX <= 0 || ballX >= canvasWidth - ballSize) {
xMove *= -1;
isScored = false;
}
// 천장 충돌
if (ballY <= 0) {
yMove *= -1;
isScored = false;
}
// 기본 플레이어 박스 충돌 확인
if (ballY + ballSize >= canvasHeight - 50 &&
ballX + (ballSize/2) >= xPlayer &&
ballX + (ballSize/2) <= xPlayer + paddleWidth) {
if (Math.abs((ballX+ballSize/2) - (xPlayer+paddleWidth/2)) <
Math.abs(ballY+ballSize-canvasHeight-50)) { // 박스 왼쪽 벽면으로 부딫히면,
// 공을 강제로 패들 위로 위치 조정
// 충돌 반복 현상 완화
ballY = canvasHeight - 50 - ballSize;
// 이동 반전
yMove *= -1;
// 점수 획득
if (!isScored) updateScore(true);
// 공을 받을수록 속도가 상승.
if (speed < resetSpeed * 2) { // 기존 속도 2배까지 상승
speed += 0.2;
}
isScored = true; // 점수 얻음 (추가로 얻지 않음)
}else{
xMove *= -1
}
}
// 바닥 충돌 (실패)
if (ballY >= canvasHeight) {
ballX = Math.random() * (canvasWidth - ballSize);
ballY = 50;
speed = resetSpeed;
updateScore(false);
isScored = false;
}
// 정규화
normalizeVector();
// 재귀 호출
requestAnimationFrame(gameLoop);
}
requestAnimationFrame(gameLoop);
};
});
</script>
<style>
canvas {
border: solid black 3px;
background-color: #eee;
}
</style>
</head>
<body>
<canvas id="c" width="500" height="500"></canvas>
<h2>점수 : 0</h2>
<h3>마우스</h3>
</body>
</html>