const canvas = document.getElementById('myCanvas');
const context = canvas.getContext('2d');
//벽돌 관련
const brickWidth = 50; // 간격 10
const brickHeight = 25; // 간격 5
const brickColumn = 5; // 열
const brickRow = 4; // 행
let bricks = []; // 갯수가 정해져있다면. new Array(5)
//볼 관련
const arcRadius = 10;
let arcPosX = canvas.width / 2 ; // 다른언어는 멤버변수가 들어있어서 오타시 잡아줌
let arcPosY = canvas.height - 30;
let arcMoveDirX = -1; // 원이 이동하는 방향 X축
let arcMoveDirY = -1; // 원이 이동하는 방향 Y축
let arcMoveSpd = 3 ; // 이동속도
let ball = {
left : 0,
right : 0,
top : 0,
bottom : 0,
};
let brick = {
left : 0,
right : 0,
top : 0,
bottom : 0,
column : 0,
row : 0,
}
//패들관련
const barWidth = 100;
const barHight = 20;
let barPosX = canvas.width / 2 - barWidth / 2;
// let arcPosX = barPosX + 50;
let barPosY = canvas.height - barHight;
let barMoveSpd = 50;
let paddle = {
left : barPosX,
right : barPosX + barWidth,
top : 380,
bottom : 400,
}
// 키처리 함수 추가
document.addEventListener('keydown', keyDownEventHandler);
document.addEventListener('keyup', keyUpEventHandler);
//함수 모음
let setStart = false;
function keyDownEventHandler(e)
{
if(e.key == ' ')
{
// setInterval(() => {
// }, update);
setStart = true
}
if(e.key == 'ArrowRight')
{
// updateRec();
// 바를 오른쪽으로 이동
if(barPosX + barWidth < canvas.width && setStart == false)
{
barPosX += barMoveSpd;
arcPosX = barPosX + 50;
//1번씩(2-1)
}
else if(barPosX + barWidth < canvas.width){
barPosX += barMoveSpd;
}
}
else if(e.key == 'ArrowLeft')
{
// updateRec();
// 바를 왼쪽으로 이동
if(barPosX > 0 && setStart == false)
{
barPosX -= barMoveSpd;
arcPosX = barPosX + 50;
//1번씩(2-2)
}
else if(barPosX > 0 ){
barPosX -= barMoveSpd;
}
}
//2에 1번(1) 연산량이 많을수도 있다.
paddle.left = barPosX;
paddle.right = barPosX + barWidth;
paddle.top = barPosY;
paddle.bottom = barPosY + barHight;
}
function keyUpEventHandler(e)
{
}
function update()
{
if( arcPosY + 10 > 400)
{
window.location.reload();
//console.log('gg')
alert("겜오버!!")
}
//데이터 수정 도형의 위치 이동
if(arcPosX - arcRadius < 0)
{
arcMoveDirX = 1;
}
else if(arcPosX + arcRadius > canvas.width)
{
arcMoveDirX = -1;
}
if(arcPosY - arcRadius < 0)
{
arcMoveDirY = 1;
}
else if(arcPosY + arcRadius > canvas.height)
{
arcMoveDirY = -1;
}
arcPosX += arcMoveDirX * arcMoveSpd;
arcPosY += arcMoveDirY * arcMoveSpd;
ball.left = arcPosX - arcRadius;
ball.right = arcPosX + arcRadius;
ball.top = arcPosY - arcRadius;
ball.bottom = arcPosY + arcRadius;
// 충돌확인 어떤경우에도 안부딪히는 상황
if(isCollisionRectToArc(ball, paddle))
{
arcMoveDirY = -1;
arcPosY = paddle.top - arcRadius;
}
for(let i = 0; i < brickRow; i++)
{
for(let j = 0; j < brickColumn; j++)
{
if (isCollisionRectToArc(ball, bricks[i][j]))
{
// 벽돌을 안보이게.. 위치를 바꾸던지.. 볼의 방향을 바꾸던지..
// console.log('i : ', i, ', j : ', j);
if(bricks[i][j].collisionCount > 0) {
bricks[i][j].collisionCount--;
arcMoveDirY *= -1;
break
}
}
else{
}
}
}
}
function isCollisionRectToArc(arcA, rectB)
{
// a의 완쪽과 b의 오른쪽
// a의 오른쪽과 b의 왼쪽
// a의 아래쪽과 b의 위쪽
// a의 위쪽과 b의 아래쪽
if (arcA.left > rectB.right || // a의 왼쪽이 더 클때
arcA.right < rectB.left || // b의 왼쪽이 더 클때
arcA.top > rectB.bottom || // a의 탑이 더 클때
arcA.bottom < rectB.top ) // b의 탑이 더 클때
{
return false;
}
return true;
}
function draw()
{
// 화면 클리어
context.clearRect(0, 0, canvas.width, canvas.height);
drawCanavs();
// 다른 도형 그리기
drawRect();
drawArc();
drawBricks();
}
function drawCanavs()
{
context.beginPath();
context.rect(0, 0, canvas.width, canvas.height);
context.fillStyle = "rgba(10, 10, 10, 0.1)";
context.fill();
context.closePath();
}
function drawArc() // 컴파일시 실행준비 함수는 한번씩만 작동하는게 좋다 - 기능하나만 구현하는게 최고다
{
context.beginPath();
context.arc(arcPosX, arcPosY, arcRadius, 0, 2 * Math.PI);
context.fillStyle = 'gold'
context.fill();
context.closePath();
}
function drawRect()
{
context.beginPath();
// context.rect(canvas.width / 2 , canvas.heigh / 2, 100, 100);
context.rect(barPosX , barPosY, barWidth, barHight);
context.fillStyle = 'red';
context.fill();
context.closePath();
}
function setBricks()
{
for(let i = 0; i < brickRow; i++) // 위에서아래라 4줄
{
bricks[i] = [];
for(let j = 0; j < brickColumn; j++) // 좌우로 5개씩
{
// TODO : right : lefi + 50 해보기
bricks[i][j] = {
left : 55 + j * (brickWidth + 10),
right : 55 + j * (brickWidth + 10) + 50,
top : 30 + i * (brickHeight + 5),
bottom : 30 + i * (brickHeight + 5) + 25,
column : i,
row : j,
collisionCount : 2
};
}
}
}
const bricksColor = [ "red", "orange", "yellow", "green", "blue" ]
function drawBricks()
{
let gamimg = false;
// context.beginPath();
for(let i = 0; i < brickRow; i++) // 위에서아래로 4줄 {
{
for(let j = 0; j < brickColumn; j++) // 좌우로 5개씩
{
// TODO : right : lefi + 50 해보기
if(bricks[i][j].collisionCount == 2)
{
context.beginPath();
context.rect(bricks[i][j].left, bricks[i][j].top, brickWidth, brickHeight);
context.fillStyle = bricksColor[i];
context.fill();
context.closePath();
gamimg = true;
}
else if(bricks[i][j].collisionCount == 1)
{
context.beginPath();
context.rect(bricks[i][j].left, bricks[i][j].top, brickWidth, brickHeight);
context.fillStyle = "purple";
context.fill();
context.closePath();
gamimg = true;
}
else
{
}
}
}
if(!gamimg) {
clear();
}
// context.closePath();
}
function clear()
{
window.location.reload();
alert("클리어!!")
}
function gameover()
{
if( arcPosY + 10 > 400)
{
console.log('gg')
alert("겜오버!!")
}
}
setBricks();
setInterval(() => {if(setStart) {update()}}, 10);
setInterval(draw, 10); // 런타임시 컴피알된 함수 실행
// 실습1. 동그라미가 오른쪽으로 움직이다가 캔버스 끝에 닿으면 왼쪽으로 이동 반대까지
// 실습2. 동그라마가 빠르게 움직이기
// 실습3. 방향키로 방향을 입력하면 네모칸의 방향이 움직인다. // 화면밖으로 이동하는걸 막는다.
// 부딪힌 벽돌이 사라지는 함수 추가 // arc가 브릭스에 닿을때 브릭스가 사라진다. 색이 변한다.
// 공과 브릭이 하나하나씩 충돌하는지 확인 // 충돌체크
// 벽돌이 2번에 걸쳐서 사라지게 하기(색변경으로 상태나타내기) // 안그리면 된다.
블록깨기 게임 작성
1. 공 움직임 (자동)
2. 패들 움직임 (수동 : 키 입력 처리)
3. 벽돌 생성
4. 공 - 패들 , 공 - 벽돌 충돌처리
5. 게임 클리어 , 게임 오버 처리
6. 벽돌 배치 후 스페이스바 누르면 공 발사 방향 결정
게임 외부 입력 요소 (react 활용)
// 처리한거
// 처리못한거