하드드랍 안전장치
- space를 눌러서 블록을 내릴때 가끔 발생하는 에러 해결
- 현재 블록이 하드드롭인 상태일때는 x축 y축을 변경 못하는 코드를 추가하자
class Piece {
hardDropped;
spawn() {
// ... 기존 코드
this.hardDropped = false;
}
move(p) {
if(!this.hardDropped){
this.x = p.x;
this.y = p.y;
}
this.shape = p.shape;
}
hardDrop(){
this.hardDropped = true;
}
}
//*** main.js
// 스페이스 누를 경우 하드 드롭
if (event.keyCode === KEY.SPACE) {
while (board.valid(p)) {
account.score += POINTS.HARD_DROP; // 하드 드롭시 점수 증가
board.piece.move(p);
p = moves[KEY.DOWN](board.piece);
}
board.piece.hardDrop();
} else if (board.valid(p)) {
board.piece.move(p);
if (event.keyCode === KEY.DOWN) {
account.score += POINTS.SOFT_DROP; // 아래 방향키 눌러서 빨리 내리면 점수 증가
}
}
// 아래 로직 삭제 -> animate()로 이전한 로직
// if(board.valid(p)) {
// // 이동 가능한 조각을 이동
// board.piece.move(p);
// // 그리기 전에 이전 좌표를 삭제
// ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
// // 테트로미노 그림
// board.piece.draw();
// }
난이도
- 게임 루프에서 인터벌 속도를 줄이면 난이도가 상승함
//*** constants.js
// 상단에 변수 선언
const LINES_PER_LEVEL = 10;
// ... 기존 코드
// 난이도
const LEVEL = {
0: 800,
1: 720,
2: 630,
3: 550,
4: 470,
5: 380,
6: 300,
7: 220,
8: 130,
9: 100,
10: 80,
11: 80,
12: 80,
13: 70,
14: 70,
15: 70,
16: 50,
17: 50,
18: 50,
19: 30,
20: 30,
}
Object.freeze(LEVEL);
- main에 level을 추가하고 모든 게임 요소(점수, 라인, 레벨, 보드판)를 초기화하는 리셋게임 함수 추가해서 호출
// 기존 time 삭제
// time = { start: 0, elapsed: 0, level: 1000 };
//*** main.js
function play() {
resetGame();
time.start = performance.now();
if (requestId) {
cancelAnimationFrame(requestId);
}
animate();
}
// ... 기존 코드
// 점수 계산
let accountValues = {
score: 0,
lines: 0,
level: 0,
}
// ... 기존 코드
function resetGame() {
account.score = 0;
account.lines = 0;
account.level = 0;
board.reset(); // 보드판 초기화
time = { start: 0, elapsed: 0, level: LEVEL[account.level] };
}
- 점수가 레벨에 따라 다르게 적용되게 점수 로직 수정
//*** board.js
class Board {
requestId;
time;
clearLines() {
// ... 기존 코드
if (lines > 0) {
// 지워진 라인들이 있다면 점수를 추가
account.score += this.getLineClearPoints(lines);
account.lines += lines;
// 다음 레벨을 위한 라인 수에 달성했다면
if (account.lines >= LINES_PER_LEVEL) {
account.level++;
// 다음 레벨을 작동하기 위해 라인을 지운다.
account.lines -= LINES_PER_LEVEL;
// 게임 속도를 높인다.
time.level = LEVEL[account.level];
}
}
}
// 지운 라인 갯수당 점수 제공
getLineClearPoints(lines) {
let score =
lines === 1 ? POINTS.SINGLE :
lines === 2 ? POINTS.DOUBLE :
lines === 3 ? POINTS.TRIPLE :
lines === 4 ? POINTS.TETRIS :
0;
// 레벨에 따라 점수 차등 적용
return (account.level + 1) * score;
}
}
게임 종료
- 더이상 내릴수 없으면 게임 루프 함수를 종료
//*** main.js
function animate(now=0){
time.elapsed = now - time.start;
// 1초마다 아래로 한칸씩 움직이는 drop()메서드를 호출
if(time.elapsed > time.level) {
time.start = now;
if (!board.drop()) {
gameOver();
return;
}
}
// ... 기존 코드
}
function gameOver() {
cancelAnimationFrame(requestId);
ctx.fillStyle = 'black';
ctx.fillRect(1, 3, 8, 1.2);
ctx.font = '1px Arial';
ctx.fillStyle = 'red';
ctx.fillText('GAME OVER', 1.8, 4);
}
게임중지
- p 키누르면 현재 움직임이 중지되고 다시 누르면 재개되도록 작업
//*** main.js
document.addEventListener('keydown', event => {
if (event.keyCode === KEY.P) {
pause();
}
// ... 기존 코드
})
// ... 기존 코드
function pause() {
if (!requestId) {
animate();
return;
}
cancelAnimationFrame(requestId);
requestId = null;
ctx.fillStyle = 'black';
ctx.fillRect(1, 3, 8, 1.2);
ctx.font = '1px Arial';
ctx.fillStyle = 'yellow';
ctx.fillText('PAUSED', 3, 4);
}
'Ecmascript > Canvas' 카테고리의 다른 글
[테트리스 만들기] 테트리스 기능 구현(다음 블록 생성, 한줄 채우면 사라지고 점수 증가) (0) | 2020.01.19 |
---|---|
[테트리스 만들기] 레이아웃부터 모션까지 제작 (0) | 2020.01.12 |
캔버스와 비디오 (0) | 2019.12.18 |
캔버스 #01 애니메이션 중지, 이미지 (0) | 2019.12.15 |
캔버스 #01 그리기와 애니메이션 원리 (0) | 2019.12.15 |