하드드랍 안전장치
- 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;
}
}
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;
}
}
난이도
- 게임 루프에서 인터벌 속도를 줄이면 난이도가 상승함
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을 추가하고 모든 게임 요소(점수, 라인, 레벨, 보드판)를 초기화하는 리셋게임 함수 추가해서 호출
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] };
}
- 점수가 레벨에 따라 다르게 적용되게 점수 로직 수정
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;
}
}
게임 종료
function animate(now=0){
time.elapsed = now - time.start;
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 키누르면 현재 움직임이 중지되고 다시 누르면 재개되도록 작업
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);
}