Add hold piece feature
- Added holdPiece and canHold state to TetrisGame class - Implemented hold() method to swap current piece with held piece - Added player-hold socket event on server - Added HOLD preview canvas showing held piece (grayed when unavailable) - Added C key keyboard shortcut and touch button for hold - Fixed canHold reset on piece spawn for proper swap functionality Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,8 @@ class TetrisGame {
|
||||
this.board = this.createEmptyBoard();
|
||||
this.currentPiece = null;
|
||||
this.nextPiece = null;
|
||||
this.holdPiece = null;
|
||||
this.canHold = true;
|
||||
this.score = 0;
|
||||
this.lines = 0;
|
||||
this.level = 1;
|
||||
@@ -51,6 +53,8 @@ class TetrisGame {
|
||||
this.gameOver = false;
|
||||
this.eliminated = false;
|
||||
this.dropInterval = 1000;
|
||||
this.holdPiece = null;
|
||||
this.canHold = true;
|
||||
this.currentPiece = this.spawnPiece();
|
||||
this.nextPiece = this.getRandomPiece();
|
||||
|
||||
@@ -172,6 +176,38 @@ class TetrisGame {
|
||||
return dropped;
|
||||
}
|
||||
|
||||
hold() {
|
||||
if (this.gameOver || this.inputLocked || !this.canHold) return false;
|
||||
|
||||
if (this.holdPiece === null) {
|
||||
// First hold - store current piece and spawn next
|
||||
this.holdPiece = {
|
||||
type: this.currentPiece.type,
|
||||
shape: JSON.parse(JSON.stringify(this.currentPiece.shape)),
|
||||
color: this.currentPiece.color
|
||||
};
|
||||
this.currentPiece = this.nextPiece;
|
||||
this.nextPiece = this.getRandomPiece();
|
||||
} else {
|
||||
// Swap with held piece
|
||||
const temp = {
|
||||
type: this.currentPiece.type,
|
||||
shape: JSON.parse(JSON.stringify(this.currentPiece.shape)),
|
||||
color: this.currentPiece.color
|
||||
};
|
||||
this.currentPiece = {
|
||||
...this.holdPiece,
|
||||
shape: JSON.parse(JSON.stringify(this.holdPiece.shape)),
|
||||
x: Math.floor(BOARD_WIDTH / 2) - Math.floor(this.holdPiece.shape[0].length / 2),
|
||||
y: 0
|
||||
};
|
||||
this.holdPiece = temp;
|
||||
}
|
||||
|
||||
this.canHold = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
lockPiece() {
|
||||
if (!this.currentPiece) return false;
|
||||
|
||||
@@ -205,6 +241,9 @@ class TetrisGame {
|
||||
this.eliminated = true;
|
||||
}
|
||||
|
||||
// Reset canHold for the new piece
|
||||
this.canHold = true;
|
||||
|
||||
return cleared;
|
||||
}
|
||||
|
||||
@@ -294,6 +333,8 @@ class TetrisGame {
|
||||
board: JSON.parse(JSON.stringify(this.board)),
|
||||
currentPiece: this.currentPiece ? JSON.parse(JSON.stringify(this.currentPiece)) : null,
|
||||
nextPiece: this.nextPiece ? JSON.parse(JSON.stringify(this.nextPiece)) : null,
|
||||
holdPiece: this.holdPiece ? JSON.parse(JSON.stringify(this.holdPiece)) : null,
|
||||
canHold: this.canHold,
|
||||
score: this.score,
|
||||
lines: this.lines,
|
||||
level: this.level,
|
||||
@@ -306,6 +347,8 @@ class TetrisGame {
|
||||
this.board = JSON.parse(JSON.stringify(state.board));
|
||||
this.currentPiece = state.currentPiece ? JSON.parse(JSON.stringify(state.currentPiece)) : null;
|
||||
this.nextPiece = state.nextPiece ? JSON.parse(JSON.stringify(state.nextPiece)) : null;
|
||||
this.holdPiece = state.holdPiece ? JSON.parse(JSON.stringify(state.holdPiece)) : null;
|
||||
this.canHold = state.canHold !== undefined ? state.canHold : true;
|
||||
this.score = state.score;
|
||||
this.lines = state.lines;
|
||||
this.level = state.level;
|
||||
|
||||
Reference in New Issue
Block a user