mirror of
https://github.com/cmclark00/tetris-3d.git
synced 2025-05-17 23:25:21 +01:00
Fix blocks not appearing by reconstructing core game functions
This commit is contained in:
parent
a6ceb3c9be
commit
da65fcf1e1
1 changed files with 186 additions and 8 deletions
194
script.js
194
script.js
|
@ -325,9 +325,26 @@ for (let i = 0; i < PIECES.length; i++) {
|
||||||
PIECE_3D_ORIENTATIONS[i].push(verticalRotation);
|
PIECE_3D_ORIENTATIONS[i].push(verticalRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add this to the loadOptions function
|
// Load options from localStorage
|
||||||
function loadOptions() {
|
function loadOptions() {
|
||||||
// ... existing code ...
|
const savedOptions = localStorage.getItem('tetris3DOptions');
|
||||||
|
if (savedOptions) {
|
||||||
|
const options = JSON.parse(savedOptions);
|
||||||
|
|
||||||
|
enable3DEffects = options.enable3DEffects !== undefined ? options.enable3DEffects : true;
|
||||||
|
enableSpinAnimations = options.enableSpinAnimations !== undefined ? options.enableSpinAnimations : true;
|
||||||
|
animationSpeed = options.animationSpeed !== undefined ? options.animationSpeed : 0.05;
|
||||||
|
forceMobileControls = options.forceMobileControls !== undefined ? options.forceMobileControls : false;
|
||||||
|
|
||||||
|
// Update UI controls
|
||||||
|
if (toggle3DEffects) toggle3DEffects.checked = enable3DEffects;
|
||||||
|
if (toggleSpinAnimations) toggleSpinAnimations.checked = enableSpinAnimations;
|
||||||
|
if (animationSpeedSlider) animationSpeedSlider.value = animationSpeed;
|
||||||
|
|
||||||
|
if (toggleMobileControls) {
|
||||||
|
toggleMobileControls.checked = forceMobileControls;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Detect if we're on mobile and reduce effects automatically
|
// Detect if we're on mobile and reduce effects automatically
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
|
@ -337,6 +354,16 @@ function loadOptions() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save options to localStorage
|
||||||
|
function saveOptions() {
|
||||||
|
localStorage.setItem('tetris3DOptions', JSON.stringify({
|
||||||
|
enable3DEffects,
|
||||||
|
enableSpinAnimations,
|
||||||
|
animationSpeed,
|
||||||
|
forceMobileControls
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
// Modify the Firework constructor to use the max particles limit
|
// Modify the Firework constructor to use the max particles limit
|
||||||
class Firework {
|
class Firework {
|
||||||
constructor(x, y) {
|
constructor(x, y) {
|
||||||
|
@ -1654,16 +1681,18 @@ function draw() {
|
||||||
|
|
||||||
lastTimestamp = now - (elapsed % FRAME_MIN_TIME);
|
lastTimestamp = now - (elapsed % FRAME_MIN_TIME);
|
||||||
|
|
||||||
// Clear canvas
|
// Clear the canvas completely to make sure nothing is left over
|
||||||
ctx.fillStyle = EMPTY;
|
ctx.fillStyle = EMPTY;
|
||||||
ctx.fillRect(0, 0, COLS * BLOCK_SIZE, ROWS * BLOCK_SIZE);
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
// Draw the board - this shows only locked pieces
|
// Draw the board - this shows locked pieces
|
||||||
drawBoard();
|
drawBoard();
|
||||||
|
|
||||||
// Always draw the active piece
|
// Always draw the active piece if it exists
|
||||||
if (p) {
|
if (p) {
|
||||||
p.draw();
|
p.draw();
|
||||||
|
} else {
|
||||||
|
console.warn("No active piece to draw!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fireworks - limit on mobile
|
// Fireworks - limit on mobile
|
||||||
|
@ -2029,8 +2058,8 @@ function optimizeForMobile() {
|
||||||
maxFireworks = 5;
|
maxFireworks = 5;
|
||||||
maxParticlesPerFirework = 10;
|
maxParticlesPerFirework = 10;
|
||||||
|
|
||||||
// Use lower frame rate for mobile
|
// Use lower frame rate for mobile - update global variable
|
||||||
const FRAME_MIN_TIME = (1000 / MOBILE_FPS_LIMIT);
|
FRAME_MIN_TIME = (1000 / MOBILE_FPS_LIMIT);
|
||||||
|
|
||||||
// Reduce shadow complexity
|
// Reduce shadow complexity
|
||||||
showShadow = false; // Start with shadow off on mobile for performance
|
showShadow = false; // Start with shadow off on mobile for performance
|
||||||
|
@ -2053,4 +2082,153 @@ function cleanup() {
|
||||||
// Call cleanup periodically on mobile devices
|
// Call cleanup periodically on mobile devices
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
setInterval(cleanup, 60000); // Cleanup every minute
|
setInterval(cleanup, 60000); // Cleanup every minute
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize game
|
||||||
|
function init() {
|
||||||
|
// Reset game variables
|
||||||
|
score = 0;
|
||||||
|
level = 1;
|
||||||
|
lines = 0;
|
||||||
|
gameOver = false;
|
||||||
|
paused = false;
|
||||||
|
|
||||||
|
// Clear the board
|
||||||
|
for (let r = 0; r < ROWS; r++) {
|
||||||
|
for (let c = 0; c < COLS; c++) {
|
||||||
|
board[r][c] = EMPTY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update UI
|
||||||
|
scoreElement.textContent = score;
|
||||||
|
levelElement.textContent = level;
|
||||||
|
linesElement.textContent = lines;
|
||||||
|
|
||||||
|
// Reset canvas to ensure clean state
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
nextPieceCtx.clearRect(0, 0, nextPieceCanvas.width, nextPieceCanvas.height);
|
||||||
|
|
||||||
|
// Load saved options
|
||||||
|
loadOptions();
|
||||||
|
|
||||||
|
// Draw the board
|
||||||
|
drawBoard();
|
||||||
|
|
||||||
|
// Generate initial pieces
|
||||||
|
p = randomPiece();
|
||||||
|
nextPiece = randomPiece();
|
||||||
|
|
||||||
|
// Draw initial next piece
|
||||||
|
nextPiece.drawNextPiece();
|
||||||
|
|
||||||
|
// Set up game interval
|
||||||
|
dropStart = Date.now();
|
||||||
|
gameInterval = setInterval(dropPiece, 1000);
|
||||||
|
|
||||||
|
// Listen for keyboard events
|
||||||
|
document.addEventListener('keydown', control);
|
||||||
|
|
||||||
|
// Force immediate draw to show pieces
|
||||||
|
draw();
|
||||||
|
|
||||||
|
console.log("Game initialized with new pieces");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drop the piece - called by interval
|
||||||
|
function dropPiece() {
|
||||||
|
if (gameOver || paused) return;
|
||||||
|
|
||||||
|
let now = Date.now();
|
||||||
|
let delta = now - dropStart;
|
||||||
|
|
||||||
|
// Drop speed depends on level
|
||||||
|
let speed = 1000 * (1 - (level - 1) * 0.1);
|
||||||
|
speed = Math.max(speed, 100); // Don't allow too fast drops (minimum 100ms)
|
||||||
|
|
||||||
|
if (delta > speed) {
|
||||||
|
p.moveDown();
|
||||||
|
dropStart = now;
|
||||||
|
|
||||||
|
// If we can't move down and we're still at the top, game over
|
||||||
|
if (p.collision(0, 1) && p.y < 1) {
|
||||||
|
gameOver = true;
|
||||||
|
showGameOver();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show game over modal
|
||||||
|
function showGameOver() {
|
||||||
|
clearInterval(gameInterval);
|
||||||
|
finalScoreElement.textContent = score;
|
||||||
|
gameOverModal.classList.add('active');
|
||||||
|
console.log("Game over!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// The control function
|
||||||
|
function control(event) {
|
||||||
|
if (gameOver) return;
|
||||||
|
if (paused && event.keyCode !== 80) return; // Allow only P key if paused
|
||||||
|
|
||||||
|
switch(event.keyCode) {
|
||||||
|
case 37: // Left arrow
|
||||||
|
case 65: // A key
|
||||||
|
p.moveLeft();
|
||||||
|
break;
|
||||||
|
case 38: // Up arrow - no function
|
||||||
|
break;
|
||||||
|
case 39: // Right arrow
|
||||||
|
case 68: // D key
|
||||||
|
p.moveRight();
|
||||||
|
break;
|
||||||
|
case 40: // Down arrow
|
||||||
|
case 83: // S key
|
||||||
|
p.moveDown();
|
||||||
|
break;
|
||||||
|
case 81: // Q key - rotate left
|
||||||
|
p.rotate('left');
|
||||||
|
break;
|
||||||
|
case 69: // E key - rotate right
|
||||||
|
p.rotate('right');
|
||||||
|
break;
|
||||||
|
case 87: // W key - 3D vertical rotation
|
||||||
|
p.rotate3DX();
|
||||||
|
break;
|
||||||
|
case 88: // X key - 3D horizontal rotation
|
||||||
|
p.rotate3DY();
|
||||||
|
break;
|
||||||
|
case 32: // Space bar - hard drop
|
||||||
|
p.hardDrop();
|
||||||
|
break;
|
||||||
|
case 80: // P key - pause
|
||||||
|
togglePause();
|
||||||
|
break;
|
||||||
|
case 72: // H key - toggle shadow
|
||||||
|
toggleShadow();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle pause
|
||||||
|
function togglePause() {
|
||||||
|
paused = !paused;
|
||||||
|
|
||||||
|
if (paused) {
|
||||||
|
clearInterval(gameInterval);
|
||||||
|
pauseBtn.textContent = "Resume";
|
||||||
|
} else {
|
||||||
|
gameInterval = setInterval(dropPiece, Math.max(100, 1000 - (level * 100)));
|
||||||
|
pauseBtn.textContent = "Pause";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle shadow display
|
||||||
|
function toggleShadow() {
|
||||||
|
showShadow = !showShadow;
|
||||||
|
if (!gameOver && !paused) {
|
||||||
|
// Redraw current piece to show/hide shadow
|
||||||
|
p.undraw();
|
||||||
|
p.draw();
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue