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:
@@ -289,6 +289,19 @@ button:active {
|
||||
border: 1px solid #333;
|
||||
}
|
||||
|
||||
/* Hold and Next piece previews side by side */
|
||||
.board-info:has(canvas) {
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
padding: 8px 5px;
|
||||
}
|
||||
|
||||
.board-info canvas {
|
||||
border: 1px solid #333;
|
||||
background: #000;
|
||||
}
|
||||
}
|
||||
|
||||
#game-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -399,3 +412,111 @@ button:active {
|
||||
.player-board.flash {
|
||||
animation: flash 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
/* Touch Controls */
|
||||
#touch-controls {
|
||||
display: none;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
margin-top: 20px;
|
||||
gap: 20px;
|
||||
justify-content: center;
|
||||
align-items: flex-end;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
#touch-dpad {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 70px);
|
||||
grid-template-rows: repeat(2, 70px);
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
#btn-left {
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
}
|
||||
|
||||
#btn-down {
|
||||
grid-column: 2;
|
||||
grid-row: 2;
|
||||
}
|
||||
|
||||
#btn-right {
|
||||
grid-column: 3;
|
||||
grid-row: 2;
|
||||
}
|
||||
|
||||
#touch-actions {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 70px);
|
||||
grid-template-rows: repeat(2, 70px);
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
#btn-rotate {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
}
|
||||
|
||||
#btn-drop {
|
||||
grid-column: 2;
|
||||
grid-row: 1;
|
||||
}
|
||||
|
||||
#btn-hold {
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
}
|
||||
|
||||
.touch-btn {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
font-size: 1.5rem;
|
||||
background: #333;
|
||||
border: 3px solid #555;
|
||||
border-radius: 10px;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
.touch-btn:active {
|
||||
background: #0ff;
|
||||
color: #000;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.touch-btn.action-btn {
|
||||
background: #444;
|
||||
}
|
||||
|
||||
.touch-btn.drop-btn {
|
||||
background: #ff00ff;
|
||||
border-color: #ff00ff;
|
||||
}
|
||||
|
||||
.touch-btn.hold-btn {
|
||||
background: #ff8800;
|
||||
border-color: #ff8800;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
/* Show touch controls on mobile only */
|
||||
@media (max-width: 768px) and (hover: none) {
|
||||
#touch-controls {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#battle-grid {
|
||||
height: 60vh;
|
||||
}
|
||||
|
||||
.player-board.spectator {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user