요새 자바스크립트 공부중
재밌다 ㅋ.ㅋ
전엔 자바스크립트 너무 싫었는데ㅠ 요샌 재밌넹
가볍게 만들 수 있고 프로젝트도 빨리 끝나다보니 완성된 결과물을 빨리 볼 수있어서 간결하다는 느낌을 받는다
요건 소스 먼저 만들고 하나씩 뜯어보는 중
참고링크가 공부에 많은 도움이 된다
참고링크 :
설명이 아주 잘 되어있다
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Gamedev Canvas Workshop</title>
<style>
* {
padding: 0;
margin: 0;
}
canvas {
background: #eee;
display: block;
margin: 0 auto;
}
button {
display: block;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="480" height="320"></canvas>
<button id="runButton">Start game</button>
<script>
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
const ballRadius = 10;
let x = canvas.width / 2;
let y = canvas.height - 30;
let dx = 2;
let dy = -2;
const paddleHeight = 10;
const paddleWidth = 75;
let paddleX = (canvas.width - paddleWidth) / 2;
let rightPressed = false;
let leftPressed = false;
const brickRowCount = 5;
const brickColumnCount = 3;
const brickWidth = 75;
const brickHeight = 20;
const brickPadding = 10;
const brickOffsetTop = 30;
const brickOffsetLeft = 30;
let score = 0;
let lives = 3;
let bricks = [];
for (let c = 0; c < brickColumnCount; c++) {
bricks[c] = [];
for (let r = 0; r < brickRowCount; r++) {
bricks[c][r] = { x: 0, y: 0, status: 1 };
}
}
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
document.addEventListener("mousemove", mouseMoveHandler, false);
function keyDownHandler(e) {
if (e.key == "Right" || e.key == "ArrowRight") {
rightPressed = true;
} else if (e.key == "Left" || e.key == "ArrowLeft") {
leftPressed = true;
}
}
function keyUpHandler(e) {
if (e.key == "Right" || e.key == "ArrowRight") {
rightPressed = false;
} else if (e.key == "Left" || e.key == "ArrowLeft") {
leftPressed = false;
}
}
function mouseMoveHandler(e) {
let relativeX = e.clientX - canvas.offsetLeft;
if (relativeX > 0 && relativeX < canvas.width) {
paddleX = relativeX - paddleWidth / 2;
}
}
function collisionDetection() {
for (let c = 0; c < brickColumnCount; c++) {
for (let r = 0; r < brickRowCount; r++) {
let b = bricks[c][r];
if (b.status == 1) {
if (
x > b.x &&
x < b.x + brickWidth &&
y > b.y &&
y < b.y + brickHeight
) {
dy = -dy;
b.status = 0;
score++;
if (score == brickRowCount * brickColumnCount) {
alert("YOU WIN, CONGRATS!");
document.location.reload();
}
}
}
}
}
}
function drawBall() {
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function drawPaddle() {
ctx.beginPath();
ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function drawBricks() {
for (let c = 0; c < brickColumnCount; c++) {
for (let r = 0; r < brickRowCount; r++) {
if (bricks[c][r].status == 1) {
const brickX = r * (brickWidth + brickPadding) + brickOffsetLeft;
const brickY = c * (brickHeight + brickPadding) + brickOffsetTop;
bricks[c][r].x = brickX;
bricks[c][r].y = brickY;
ctx.beginPath();
ctx.rect(brickX, brickY, brickWidth, brickHeight);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
}
}
}
function drawScore() {
ctx.font = "16px Arial";
ctx.fillStyle = "#0095DD";
ctx.fillText("Score: " + score, 8, 20);
}
function drawLives() {
ctx.font = "16px Arial";
ctx.fillStyle = "#0095DD";
ctx.fillText("Lives: " + lives, canvas.width - 65, 20);
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBricks();
drawBall();
drawPaddle();
drawScore();
drawLives();
collisionDetection();
if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
dx = -dx;
}
if (y + dy < ballRadius) {
dy = -dy;
} else if (y + dy > canvas.height - ballRadius) {
if (x > paddleX && x < paddleX + paddleWidth) {
dy = -dy;
} else {
lives--;
if (!lives) {
alert("GAME OVER");
document.location.reload();
} else {
x = canvas.width / 2;
y = canvas.height - 30;
dx = 3;
dy = -3;
paddleX = (canvas.width - paddleWidth) / 2;
}
}
}
if (rightPressed && paddleX < canvas.width - paddleWidth) {
paddleX += 7;
} else if (leftPressed && paddleX > 0) {
paddleX -= 7;
}
x += dx;
y += dy;
requestAnimationFrame(draw);
}
document.getElementById("runButton").addEventListener("click", function () {
draw();
this.disabled = true;
});
</script>
</body>
</html>
개인 주석 단 내용 (나혼자 알아보기위함)
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Gamedev Canvas Workshop</title>
<style>
* {
padding: 0;
margin: 0;
}
canvas {
background: #eee;
display: block;
margin: 0 auto;
}
button {
display: block;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="480" height="320"></canvas>
<button id="runButton">Start game</button>
<script>
/* 그림을 그릴 캔버스 생성*/
const canvas = document.getElementById("myCanvas");
/* 캔버스 안에 실질적으로 조종할 객체 생성
이걸 2D rendering context 라고 하나봄;; ㅋㅋ 잘은 모르겠다 일단 그렇다고함 ㅇㅇ*/
const ctx = canvas.getContext("2d");
/* 만들어질 게임 공의 반지름 설정 */
const ballRadius = 10;
/* 만들어질 게임 공의 x와 y좌표(공의 중심) */
let x = canvas.width / 2;
let y = canvas.height - 30;
/* 공 움직임 표현을 위해서 프레임마다 더해줄 값 생성 */
let dx = 2;
let dy = -2;
const paddleHeight = 10;
const paddleWidth = 75;
let paddleX = (canvas.width - paddleWidth) / 2;
let rightPressed = false;
let leftPressed = false;
const brickRowCount = 5;
const brickColumnCount = 3;
const brickWidth = 75;
const brickHeight = 20;
const brickPadding = 10;
const brickOffsetTop = 30;
const brickOffsetLeft = 30;
let score = 0;
let lives = 3;
let bricks = [];
/* bricks[] 배열을 이차원 배열로 만들기 */
for (let c = 0; c < brickColumnCount; c++) {
bricks[c] = [];
for (let r = 0; r < brickRowCount; r++) {
/* 배열안 요소에 x,y status 값 선언*/
bricks[c][r] = { x: 0, y: 0, status: 1 };
}
}
/* 키보드 이벤트
keydown : 키보드 누를 때
keyup : 키보드 뗄 때
mousemove : 마우스 움직일 때
*/
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
document.addEventListener("mousemove", mouseMoveHandler, false);
/* 키보드 누를 때 움직이기 true */
function keyDownHandler(e) {
if (e.key == "Right" || e.key == "ArrowRight") {
rightPressed = true;
} else if (e.key == "Left" || e.key == "ArrowLeft") {
leftPressed = true;
}
}
/* 키보드 뗄 때 움직이기 false */
function keyUpHandler(e) {
if (e.key == "Right" || e.key == "ArrowRight") {
rightPressed = false;
} else if (e.key == "Left" || e.key == "ArrowLeft") {
leftPressed = false;
}
}
/* 마우스 움직일 때 기능 */
function mouseMoveHandler(e) {
/* e.clientX 는 브라우저에서 보여지는 영역을 기준의 좌표
마우스 움직임에 따라 패들 위치 움직이기 */
let relativeX = e.clientX - canvas.offsetLeft;
if (relativeX > 0 && relativeX < canvas.width) {
paddleX = relativeX - paddleWidth / 2;
}
}
/* 벽돌과 부딪혔을때 기능*/
function collisionDetection() {
for (let c = 0; c < brickColumnCount; c++) {
for (let r = 0; r < brickRowCount; r++) {
let b = bricks[c][r];
if (b.status == 1) {
/* 공위치가 벽돌좌표가 겹치면 */
if (
x > b.x &&
x < b.x + brickWidth &&
y > b.y &&
y < b.y + brickHeight
) {
/* 공의 방향틀어주기 , 벽돌 지우기, 총점수 +1 추가하기 */
dy = -dy;
b.status = 0;
score++;
/* 총점수: 만점 이면 경고창띄우고 리로드 */
if (score == brickRowCount * brickColumnCount) {
alert("YOU WIN, CONGRATS!");
document.location.reload();
}
}
}
}
}
}
/* 공 그리기 기능 */
function drawBall() {
/* 그림 그린다는 선언 */
ctx.beginPath();
/* (동그라미도형) 공의 x,y 좌표, 공의 지름, 공 그릴때 시작과 끝각도 ,(생략된 옵션 param: 그리는방향 false true 도 있음)*/
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
/* 채울 색깔 */
ctx.fillStyle = "#0095DD";
ctx.fill();
/* 그림 끝낸다는 선언*/
ctx.closePath();
}
/* 공 받아치는 패들 그리기 기능 */
function drawPaddle() {
ctx.beginPath();
/*사각형 그리기 사각형 좌표, 높이 , 너비) */
ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
/* 벽돌 그리기 기능 */
function drawBricks() {
/* 열:5 행:3 벽돌그리기 반복문 */
for (let c = 0; c < brickColumnCount; c++) {
for (let r = 0; r < brickRowCount; r++) {
if (bricks[c][r].status == 1) {
/* 벽돌 한개씩 for문 돌리면서 좌표 설정*/
const brickX = r * (brickWidth + brickPadding) + brickOffsetLeft;
const brickY = c * (brickHeight + brickPadding) + brickOffsetTop;
bricks[c][r].x = brickX;
bricks[c][r].y = brickY;
ctx.beginPath();
ctx.rect(brickX, brickY, brickWidth, brickHeight);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
}
}
}
function drawScore() {
ctx.font = "16px Arial";
ctx.fillStyle = "#0095DD";
ctx.fillText("Score: " + score, 8, 20);
}
function drawLives() {
ctx.font = "16px Arial";
ctx.fillStyle = "#0095DD";
ctx.fillText("Lives: " + lives, canvas.width - 65, 20);
}
/*공 움직이기 기능: 게임 start 기능과 같음
start할때부터 움직여야하므로,
그래서 이게 시작기능이라고 보고 여기에 모든 기능 떄려넣기 */
function draw() {
/*공 움직임 흔적 지우기*/
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBricks();
drawBall();
drawPaddle();
drawScore();
drawLives();
collisionDetection();
/* 튕겨내기 위한 코드
캔버스에는 총 4개의 벽이 존재함
공을 그리는 매 프레임마다 벽에 닿았는지 확인해야함
벽에 닿았다면 방향을 반대로 틀어줘야함
틀어주면서 또 공을 그려야함 */
/* x값을 +값 (오른쪽) 오른쪽벽에 닿았다? 그럼 x값을 -값(왼쪽)으로 */
if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
dx = -dx;
}
/* y값을 +값 (윗쪽) 상단벽에 닿았다? 그럼 y값을 -값(아래쪽)으로 */
if (y + dy < ballRadius) {
dy = -dy;
} else if (y + dy > canvas.height - ballRadius) {
if (x > paddleX && x < paddleX + paddleWidth) {
dy = -dy;
} else {
lives--;
if (!lives) {
alert("GAME OVER");
document.location.reload();
} else {
x = canvas.width / 2;
y = canvas.height - 30;
dx = 3;
dy = -3;
paddleX = (canvas.width - paddleWidth) / 2;
}
}
}
/* 오른쪽 키보드 누를때 패들 7픽셀씩 이동 */
if (rightPressed && paddleX < canvas.width - paddleWidth) {
paddleX += 7;
/* 왼쪽 키보드 누를때 */
} else if (leftPressed && paddleX > 0) {
paddleX -= 7;
}
x += dx;
y += dy;
requestAnimationFrame(draw);
}
document.getElementById("runButton").addEventListener("click", function () {
draw();
this.disabled = true;
});
</script>
</body>
</html>
'JAVASCRIPT' 카테고리의 다른 글
[JavaScript]카드 짝 맞추기 게임 (0) | 2024.03.24 |
---|---|
고인물 테스트 사이트 (0) | 2024.03.17 |