Changes
This commit is contained in:
@@ -62,7 +62,12 @@ const Breakout = () => {
|
||||
if (height > maxHeight) { height = maxHeight; width = height * aspectRatio; }
|
||||
return { width: Math.floor(width), height: Math.floor(height) };
|
||||
}
|
||||
return isFullscreen ? { width: 600, height: 720 } : { width: 480, height: 580 };
|
||||
// Desktop: maximize based on available height
|
||||
const availableHeight = window.innerHeight - 100;
|
||||
const aspectRatio = 480 / 580;
|
||||
const height = Math.min(availableHeight, 700);
|
||||
const width = Math.floor(height * aspectRatio);
|
||||
return { width, height };
|
||||
}, [isFullscreen]);
|
||||
|
||||
const [canvasSize, setCanvasSize] = useState(getCanvasSize);
|
||||
@@ -261,7 +266,7 @@ const Breakout = () => {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className={`flex ${isMobile ? 'flex-col items-center' : 'flex-row gap-4'} flex-1 ${isFullscreen ? 'justify-center items-center' : ''}`}>
|
||||
<div className={`flex ${isMobile ? 'flex-col items-center' : 'flex-row gap-4 items-start justify-center'} flex-1`}>
|
||||
<div className="border-2 border-primary box-glow bg-background/80">
|
||||
<canvas ref={canvasRef} width={canvasSize.width} height={canvasSize.height} onTouchMove={handleTouchMove} className="block" />
|
||||
</div>
|
||||
|
||||
@@ -101,7 +101,11 @@ const Pacman = () => {
|
||||
const maxHeight = window.innerHeight - 420;
|
||||
return Math.min(Math.floor(maxWidth / GRID_WIDTH), Math.floor(maxHeight / GRID_HEIGHT), 16);
|
||||
}
|
||||
return isFullscreen ? 26 : 20;
|
||||
// Desktop: calculate based on available height (subtract header ~60px, margins ~40px)
|
||||
const availableHeight = window.innerHeight - 100;
|
||||
const maxCellFromHeight = Math.floor(availableHeight / GRID_HEIGHT);
|
||||
// Clamp to reasonable max
|
||||
return Math.min(maxCellFromHeight, 28);
|
||||
}, [isFullscreen]);
|
||||
|
||||
const [cellSize, setCellSize] = useState(getCellSize);
|
||||
@@ -554,7 +558,7 @@ const Pacman = () => {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className={`flex ${isMobile ? 'flex-col items-center' : 'flex-row gap-4'} flex-1 ${isFullscreen ? 'justify-center items-center' : ''}`}>
|
||||
<div className={`flex ${isMobile ? 'flex-col items-center' : 'flex-row gap-4 items-start justify-center'} flex-1`}>
|
||||
<div className="border-2 border-primary box-glow p-1 bg-background/80 relative overflow-hidden">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-primary/5 via-transparent to-primary/5 animate-pulse" style={{ animationDuration: '4s' }}></div>
|
||||
<div className="grid relative z-10" style={{ gridTemplateColumns: `repeat(${GRID_WIDTH}, ${cellSize}px)` }}>{renderGrid()}</div>
|
||||
|
||||
+6
-5
@@ -75,10 +75,11 @@ const Snake = () => {
|
||||
const maxHeight = window.innerHeight - 420;
|
||||
return Math.min(Math.floor(maxWidth / GRID_SIZE), Math.floor(maxHeight / GRID_SIZE), 18);
|
||||
}
|
||||
if (gameMode === '2p') {
|
||||
return isFullscreen ? 20 : 16;
|
||||
}
|
||||
return isFullscreen ? 28 : 24;
|
||||
// Desktop: calculate based on available height (subtract header ~60px, margins ~40px)
|
||||
const availableHeight = window.innerHeight - 100;
|
||||
const maxCellFromHeight = Math.floor(availableHeight / GRID_SIZE);
|
||||
// Clamp to reasonable max
|
||||
return Math.min(maxCellFromHeight, 30);
|
||||
}, [isFullscreen, gameMode]);
|
||||
|
||||
const [cellSize, setCellSize] = useState(getCellSize);
|
||||
@@ -538,7 +539,7 @@ const Snake = () => {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className={`flex ${isMobile ? 'flex-col items-center' : 'flex-row gap-4'} flex-1 ${isFullscreen ? 'justify-center items-center' : ''}`}>
|
||||
<div className={`flex ${isMobile ? 'flex-col items-center' : 'flex-row gap-4 items-start justify-center'} flex-1`}>
|
||||
<div className="border-2 border-primary box-glow p-1 bg-background/80">
|
||||
<div className="grid" style={{ gridTemplateColumns: `repeat(${GRID_SIZE}, ${cellSize}px)` }}>
|
||||
{gameMode === '1p' ? renderGrid1P() : renderGrid2P()}
|
||||
|
||||
+65
-55
@@ -148,10 +148,17 @@ const Tetris = () => {
|
||||
const maxHeight = window.innerHeight - 440;
|
||||
return Math.min(Math.floor(maxWidth / BOARD_WIDTH), Math.floor(maxHeight / BOARD_HEIGHT), 22);
|
||||
}
|
||||
// Desktop: calculate based on available height (subtract header ~60px, margins ~40px)
|
||||
const availableHeight = window.innerHeight - 100;
|
||||
const maxCellFromHeight = Math.floor(availableHeight / BOARD_HEIGHT);
|
||||
if (gameMode === '2p') {
|
||||
return isFullscreen ? 22 : 18;
|
||||
// 2P needs two boards side by side plus controls (~500px for both boards + gaps)
|
||||
const availableWidth = window.innerWidth - 300; // space for controls
|
||||
const maxCellFromWidth = Math.floor(availableWidth / (BOARD_WIDTH * 2 + 4));
|
||||
return Math.min(maxCellFromHeight, maxCellFromWidth, 28);
|
||||
}
|
||||
return isFullscreen ? 30 : 24;
|
||||
// 1P mode - maximize based on height
|
||||
return Math.min(maxCellFromHeight, 32);
|
||||
}, [isFullscreen, gameMode]);
|
||||
|
||||
const [cellSize, setCellSize] = useState(getCellSize);
|
||||
@@ -598,7 +605,7 @@ const Tetris = () => {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className={`flex ${isMobile ? 'flex-col items-center' : 'flex-row gap-4'} flex-1 ${isFullscreen ? 'justify-center items-center' : ''}`}>
|
||||
<div className={`flex ${isMobile ? 'flex-col items-center' : 'flex-row gap-3 items-start justify-center'} flex-1`}>
|
||||
{gameMode === '1p' ? (
|
||||
<>
|
||||
<div className="border-2 border-primary box-glow p-1 bg-background/80">{renderBoard1P()}</div>
|
||||
@@ -629,42 +636,44 @@ const Tetris = () => {
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
/* 2P Layout: P1 Board with Next | Controls | P2 Board with Next */
|
||||
<>
|
||||
{/* P1 Board */}
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 rounded-sm bg-primary" />
|
||||
<span className="font-pixel text-xs text-primary">P1 (WASD/Q)</span>
|
||||
{/* P1 Section */}
|
||||
<div className="flex gap-2 items-start">
|
||||
<div className="flex flex-col items-center gap-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 rounded-sm bg-primary" />
|
||||
<span className="font-pixel text-xs text-primary">P1 (WASD/Q)</span>
|
||||
</div>
|
||||
<div className="border-2 border-primary box-glow p-1 bg-background/80">{renderBoard2P(player1, 'border-primary/20')}</div>
|
||||
<div className="flex gap-2 text-center">
|
||||
<div><p className="font-pixel text-[8px] text-foreground/60">SCORE</p><p className="font-minecraft text-sm text-primary">{player1.score}</p></div>
|
||||
<div><p className="font-pixel text-[8px] text-foreground/60">LINES</p><p className="font-minecraft text-sm text-primary">{player1.lines}</p></div>
|
||||
</div>
|
||||
{player1.gameOver && <span className="font-pixel text-xs text-destructive">GAME OVER</span>}
|
||||
</div>
|
||||
<div className="border-2 border-primary box-glow p-1 bg-background/80">{renderBoard2P(player1, 'border-primary/20')}</div>
|
||||
<div className="flex gap-2 text-center">
|
||||
<div><p className="font-pixel text-[8px] text-foreground/60">SCORE</p><p className="font-minecraft text-sm text-primary">{player1.score}</p></div>
|
||||
<div><p className="font-pixel text-[8px] text-foreground/60">LINES</p><p className="font-minecraft text-sm text-primary">{player1.lines}</p></div>
|
||||
</div>
|
||||
{player1.gameOver && <span className="font-pixel text-xs text-destructive">GAME OVER</span>}
|
||||
</div>
|
||||
|
||||
{/* P1 Next Piece */}
|
||||
<div className="border-2 border-primary/50 p-2 bg-background/50 flex flex-col items-center justify-center min-h-[60px]">
|
||||
<p className="font-pixel text-[10px] text-foreground/60">P1 NEXT</p>
|
||||
<div className="flex flex-col gap-1">
|
||||
{player1.nextPiece.shape.map((row, y) => (
|
||||
<div key={y} className="flex gap-1">
|
||||
{row.map((val, x) => (
|
||||
<div key={`${y}-${x}`} className={`w-2 h-2 ${val ? 'bg-primary box-glow' : 'bg-transparent'}`} />
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
{/* P1 Next Piece */}
|
||||
<div className="border border-primary/50 p-2 bg-background/50 flex flex-col items-center justify-center">
|
||||
<p className="font-pixel text-[8px] text-foreground/60 mb-1">NEXT</p>
|
||||
<div className="flex flex-col gap-0.5">
|
||||
{player1.nextPiece.shape.map((row, y) => (
|
||||
<div key={y} className="flex gap-0.5">
|
||||
{row.map((val, x) => (
|
||||
<div key={`${y}-${x}`} className={`w-2 h-2 ${val ? 'bg-primary box-glow' : 'bg-transparent'}`} />
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Center controls */}
|
||||
<div className="flex flex-col gap-2 min-w-[100px] items-center">
|
||||
<div className="flex flex-col gap-2 min-w-[90px] items-center justify-center">
|
||||
<div className="border border-primary/50 p-2 bg-background/50 text-center">
|
||||
<p className="font-pixel text-[8px] text-foreground/60 mb-1">CONTROLS</p>
|
||||
<p className="font-pixel text-[8px] text-primary">P1: WASD Q</p>
|
||||
<p className="font-pixel text-[8px] text-purple-400">P2: ↑↓←→ /</p>
|
||||
<p className="font-pixel text-[8px] text-foreground/60 mt-1">P: Pause</p>
|
||||
<p className="font-pixel text-[7px] text-primary">P1: WASD Q</p>
|
||||
<p className="font-pixel text-[7px] text-purple-400">P2: ↑↓←→ /</p>
|
||||
<p className="font-pixel text-[7px] text-foreground/60 mt-1">P: Pause</p>
|
||||
</div>
|
||||
{!gameStarted || gameOver ? (
|
||||
<button onClick={() => startGame('2p')} className="font-minecraft text-xs py-2 px-3 border border-primary bg-primary/20 text-primary hover:bg-primary/40 transition-all box-glow">
|
||||
@@ -677,31 +686,32 @@ const Tetris = () => {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* P2 Board */}
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 rounded-sm" style={{ backgroundColor: 'hsl(280 70% 50%)' }} />
|
||||
<span className="font-pixel text-xs text-purple-400">P2 (↑↓←→/)</span>
|
||||
{/* P2 Section */}
|
||||
<div className="flex gap-2 items-start">
|
||||
{/* P2 Next Piece */}
|
||||
<div className="border border-purple-500/50 p-2 bg-background/50 flex flex-col items-center justify-center">
|
||||
<p className="font-pixel text-[8px] text-purple-400 mb-1">NEXT</p>
|
||||
<div className="flex flex-col gap-0.5">
|
||||
{player2.nextPiece.shape.map((row, y) => (
|
||||
<div key={y} className="flex gap-0.5">
|
||||
{row.map((val, x) => (
|
||||
<div key={`${y}-${x}`} className={`w-2 h-2 ${val ? 'bg-purple-400 box-glow' : 'bg-transparent'}`} />
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="border-2 border-purple-500 p-1 bg-background/80" style={{ boxShadow: '0 0 10px hsl(280 70% 50% / 0.5)' }}>{renderBoard2P(player2, 'border-purple-500/20')}</div>
|
||||
<div className="flex gap-2 text-center">
|
||||
<div><p className="font-pixel text-[8px] text-foreground/60">SCORE</p><p className="font-minecraft text-sm text-purple-400">{player2.score}</p></div>
|
||||
<div><p className="font-pixel text-[8px] text-foreground/60">LINES</p><p className="font-minecraft text-sm text-purple-400">{player2.lines}</p></div>
|
||||
</div>
|
||||
{player2.gameOver && <span className="font-pixel text-xs text-destructive">GAME OVER</span>}
|
||||
</div>
|
||||
|
||||
{/* P2 Next Piece */}
|
||||
<div className="border-2 border-purple-500/50 p-2 bg-background/50 flex flex-col items-center justify-center min-h-[60px]">
|
||||
<p className="font-pixel text-[10px] text-purple-400">P2 NEXT</p>
|
||||
<div className="flex flex-col gap-1">
|
||||
{player2.nextPiece.shape.map((row, y) => (
|
||||
<div key={y} className="flex gap-1">
|
||||
{row.map((val, x) => (
|
||||
<div key={`${y}-${x}`} className={`w-2 h-2 ${val ? 'bg-purple-400 box-glow' : 'bg-transparent'}`} />
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
<div className="flex flex-col items-center gap-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 rounded-sm" style={{ backgroundColor: 'hsl(280 70% 50%)' }} />
|
||||
<span className="font-pixel text-xs text-purple-400">P2 (↑↓←→/)</span>
|
||||
</div>
|
||||
<div className="border-2 border-purple-500 p-1 bg-background/80" style={{ boxShadow: '0 0 10px hsl(280 70% 50% / 0.5)' }}>{renderBoard2P(player2, 'border-purple-500/20')}</div>
|
||||
<div className="flex gap-2 text-center">
|
||||
<div><p className="font-pixel text-[8px] text-foreground/60">SCORE</p><p className="font-minecraft text-sm text-purple-400">{player2.score}</p></div>
|
||||
<div><p className="font-pixel text-[8px] text-foreground/60">LINES</p><p className="font-minecraft text-sm text-purple-400">{player2.lines}</p></div>
|
||||
</div>
|
||||
{player2.gameOver && <span className="font-pixel text-xs text-destructive">GAME OVER</span>}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
{/* P2 Next Piece */}
|
||||
<div className="border-2 border-purple-500/50 p-3 bg-background/50 flex flex-col items-center justify-center min-h-[60px]">
|
||||
<p className="font-pixel text-[10px] text-purple-400">P2 NEXT</p>
|
||||
<div className="flex flex-col gap-1">
|
||||
{player2.nextPiece.shape.map((row, y) => (
|
||||
<div key={y} className="flex gap-1">
|
||||
{row.map((val, x) => (
|
||||
<div key={`${y}-${x}`} className={`w-2 h-2 ${val ? 'bg-purple-400 box-glow' : 'bg-transparent'}`} />
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Center controls */}
|
||||
Reference in New Issue
Block a user