본문 바로가기
개발 공부/canvas

Canvas을 사용하여 벽돌깨기 게임 만들기8 (점수 추가와 승패 판정 방법)

by 억만장작 2021. 7. 18.

점수 계산하기

시작시 점수를 0으로 세팅

let score = 0

 

점수 화면을 만들고 업데이트를 하기 위해서 drawScore()을 추가한다.

function drawScore() {
	ctx.font = "16px Arilal"
	ctx.fillStyle = "#0095DD"
	ctx.fillText("Score: " + score, 8, 20)
}

fillText()를 통해 문자를 출력할 수 있다. 8, 20은 문자가 배치될 좌표이다.

 

벽돌이 깨질 때 마다 score++을 해준다.

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 && x > b.x && x < b.x + brickWidth && y > b.y && y < b.y + brickHeight) {
				dy = -dy
				b.status = 0
				score++ // 추가
			}
		}
	}
}

 

drawScore()을 drawPaddle()아래에서 호출한다.

drawScore()

 

모든 벽돌이 파괴되었을 때 승리 메시지 표시

 

모든 벽돌의 수 === brickRowCount & brickColumnCount이다.

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 && x > b.x && x < b.x + brickWidth && y > b.y && y < b.y + brickHeight) {
				dy = -dy
				b.status = 0
				score++
                // 추가
				if (score === brickRowCount * brickColumnCount) {
					clearInterval(tmp)
					alert("YOU WIN, CONGRATURATIONS!")
					document.location.reload()
				}
			}
		}
	}
}

모든 벽돌을 부수면 게임이 끝나고 재시작한다.

 

개인적으로 벽돌이 깨질 수록 공의 속도가 빨라졌으면 싶어서 공의 속도를 조절하는 변수를 넣어줬다.

let ballSpeed = 1.5

중간 부터 들어간 코든데 지금에서야 이야기한다...

 

이 공 속도와 score가 오르면 오를수록 빠르게 움직이게 하기 위하여 다음 코드를 추가한다.

function draw() {
	ctx.clearRect(0, 0, canvas.width, canvas.height)
	drawBricks()
	drawBall()
	drawPaddle()
    drawScore()
	collisionDetection()
	// 공 체크
	if (y + dy < ballRadius) {
		dy = -dy
	} else if (y + dy > canvas.height - ballRadius) {
		alert("GAME OVER")
		document.location.reload()
		clearInterval(tmp)
	} else if (y + dy > canvas.height - ballRadius - paddleHeight &&
				x + dx > paddleX && x + dx < paddleX + paddleWidth) {
		dy = -dy
	}
	if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
		dx = -dx
	}
	
	// 키 체크
	if (rightPressed && paddleX < canvas.width - paddleWidth) {
		paddleX += 7
	}
	if (leftPressed && paddleX > 0) {
		paddleX -= 7
	}
	// 공의 속도를 조절하는 곳.
	x += dx * (ballSpeed + 0.15 * score) // 수정
	y += dy * (ballSpeed + 0.15 * score) // 수정
}

이 부분도 원래 ballSpeed가 곱해져 있는 상황이었다.

 

최종코드

const canvas = document.querySelector("#canvas")
const ctx = canvas.getContext("2d")

let ballRadius = 10
let x = canvas.width / 2
let y = canvas.height - 20
let dx = 1
let dy = -1
let ballSpeed = 1.5
// paddle
const paddleHeight = 10
const paddleWidth = 75
let paddleX = (canvas.width - paddleWidth) / 2
// event
let rightPressed = false
let leftPressed = false
// 벽돌
const brickRowCount = 3
const brickColumnCount = 5
const brickWidth = 75
const brickHeight = 20
const brickPadding = 10
const brickOffsetTop = 30
const brickOffsetLeft = 30

let score = 0

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}
	}
}

function drawScore() {
	ctx.font = "16px Arilal"
	ctx.fillStyle = "#0095DD"
	ctx.fillText("Score: " + score, 8, 20)
}

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 && x > b.x && x < b.x + brickWidth && y > b.y && y < b.y + brickHeight) {
				dy = -dy
				b.status = 0
				score++
				if (score === brickRowCount * brickColumnCount) {
					clearInterval(tmp)
					alert("YOU WIN, CONGRATURATIONS!")
					document.location.reload()
				}
			}
		}
	}
}

function drawBricks() {
	for (let c = 0; c < brickColumnCount; c++) {
		for(let r = 0; r < brickRowCount; r++) {
			if (bricks[c][r].status === 0)
				continue
			let brickX = (c * (brickWidth + brickPadding)) + brickOffsetLeft
			let brickY = (r * (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 keyDownHandler(event) {
	if (event.keyCode === 39) {
		rightPressed = true
	}
	else if (event.keyCode === 37) {
		leftPressed = true
	}
}

function keyUpHandler(event) {
	if (event.keyCode === 39) {
		rightPressed = false
	}
	else if (event.keyCode === 37) {
		leftPressed = false
	}
}

function drawPaddle() {
	ctx.beginPath()
	ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight)
	ctx.fillStyle = "rgba(50, 20, 20, 1)"
	ctx.fill()
	ctx.closePath()
}

function drawBall() {
	ctx.beginPath()
	ctx.arc(x, y, ballRadius, 0, Math.PI * 2, false)
	ctx.fillStyle = "white"
	ctx.fill()
	ctx.strokeStyle = "gray"
	ctx.stroke()
	ctx.closePath()
}

function draw() {
	ctx.clearRect(0, 0, canvas.width, canvas.height)
	drawBricks()
	drawBall()
	drawPaddle()
    drawScore()
	collisionDetection()
	// 공 체크
	if (y + dy < ballRadius) {
		dy = -dy
	} else if (y + dy > canvas.height - ballRadius) {
		alert("GAME OVER")
		document.location.reload()
		clearInterval(tmp)
	} else if (y + dy > canvas.height - ballRadius - paddleHeight &&
				x + dx > paddleX && x + dx < paddleX + paddleWidth) {
		dy = -dy
	}
	if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
		dx = -dx
	}
	
	// 키 체크
	if (rightPressed && paddleX < canvas.width - paddleWidth) {
		paddleX += 7
	}
	if (leftPressed && paddleX > 0) {
		paddleX -= 7
	}
	// 공의 속도를 조절하는 곳.
	x += dx * (ballSpeed + 0.15 * score)
	y += dy * (ballSpeed + 0.15 * score)
}
document.addEventListener("keydown", keyDownHandler, false)
document.addEventListener("keyup", keyUpHandler, false)

let tmp = setInterval(draw, 10)

 

결과물

댓글