Changes
This commit is contained in:
@@ -578,7 +578,7 @@ const AIChat = () => {
|
|||||||
className={`max-w-[90%] sm:max-w-[85%] md:max-w-[80%] p-2 sm:p-3 rounded-lg text-xs sm:text-sm overflow-x-auto ${
|
className={`max-w-[90%] sm:max-w-[85%] md:max-w-[80%] p-2 sm:p-3 rounded-lg text-xs sm:text-sm overflow-x-auto ${
|
||||||
message.role === 'user'
|
message.role === 'user'
|
||||||
? 'bg-primary/20 border border-primary/50'
|
? 'bg-primary/20 border border-primary/50'
|
||||||
: 'bg-secondary/50 border border-primary/30'
|
: 'bg-muted border border-primary/30'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<MessageContent
|
<MessageContent
|
||||||
@@ -607,7 +607,7 @@ const AIChat = () => {
|
|||||||
<div className="w-8 h-8 rounded border border-primary/50 flex items-center justify-center bg-primary/10">
|
<div className="w-8 h-8 rounded border border-primary/50 flex items-center justify-center bg-primary/10">
|
||||||
<Bot className="w-4 h-4 text-primary" />
|
<Bot className="w-4 h-4 text-primary" />
|
||||||
</div>
|
</div>
|
||||||
<div className="p-3 rounded-lg bg-secondary/50 border border-primary/30">
|
<div className="p-3 rounded-lg bg-muted border border-primary/30">
|
||||||
<Loader2 className="w-4 h-4 text-primary animate-spin" />
|
<Loader2 className="w-4 h-4 text-primary animate-spin" />
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|||||||
+20
-4
@@ -106,10 +106,26 @@ const Breakout = () => {
|
|||||||
if (height > maxHeight) { height = maxHeight; width = height * aspectRatio; }
|
if (height > maxHeight) { height = maxHeight; width = height * aspectRatio; }
|
||||||
return { width: Math.floor(width), height: Math.floor(height) };
|
return { width: Math.floor(width), height: Math.floor(height) };
|
||||||
}
|
}
|
||||||
if (isTwoPlayer) {
|
if (isFullscreen) {
|
||||||
return isFullscreen ? { width: 480, height: 580 } : { width: 400, height: 500 };
|
const aspectRatio = 560 / 680;
|
||||||
|
if (isTwoPlayer) {
|
||||||
|
// Two canvases side by side
|
||||||
|
const maxWidth = (window.innerWidth - 100) / 2;
|
||||||
|
const maxHeight = window.innerHeight - 120;
|
||||||
|
let width = maxWidth;
|
||||||
|
let height = width / aspectRatio;
|
||||||
|
if (height > maxHeight) { height = maxHeight; width = height * aspectRatio; }
|
||||||
|
return { width: Math.floor(width), height: Math.floor(height) };
|
||||||
|
}
|
||||||
|
// Single player - fill screen
|
||||||
|
const maxWidth = window.innerWidth - 280;
|
||||||
|
const maxHeight = window.innerHeight - 100;
|
||||||
|
let width = maxWidth;
|
||||||
|
let height = width / aspectRatio;
|
||||||
|
if (height > maxHeight) { height = maxHeight; width = height * aspectRatio; }
|
||||||
|
return { width: Math.floor(width), height: Math.floor(height) };
|
||||||
}
|
}
|
||||||
return isFullscreen ? { width: 700, height: 840 } : { width: 560, height: 680 };
|
return isTwoPlayer ? { width: 400, height: 500 } : { width: 560, height: 680 };
|
||||||
}, [isFullscreen, isTwoPlayer]);
|
}, [isFullscreen, isTwoPlayer]);
|
||||||
|
|
||||||
const [canvasSize, setCanvasSize] = useState(getCanvasSize);
|
const [canvasSize, setCanvasSize] = useState(getCanvasSize);
|
||||||
@@ -304,7 +320,7 @@ const Breakout = () => {
|
|||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
if (!ctx) return;
|
if (!ctx) return;
|
||||||
|
|
||||||
const paddleSpeed = isMobile ? 6 : (isFullscreen ? 10 : 8);
|
const paddleSpeed = isMobile ? 4 : (isFullscreen ? 6 : 5);
|
||||||
if (keysRef.current.has(leftKey)) paddleRefParam.current = Math.max(0, paddleRefParam.current - paddleSpeed);
|
if (keysRef.current.has(leftKey)) paddleRefParam.current = Math.max(0, paddleRefParam.current - paddleSpeed);
|
||||||
if (keysRef.current.has(rightKey)) paddleRefParam.current = Math.min(canvasSize.width - paddleWidth, paddleRefParam.current + paddleSpeed);
|
if (keysRef.current.has(rightKey)) paddleRefParam.current = Math.min(canvasSize.width - paddleWidth, paddleRefParam.current + paddleSpeed);
|
||||||
|
|
||||||
|
|||||||
+13
-7
@@ -122,7 +122,13 @@ const Pacman = () => {
|
|||||||
const maxHeight = window.innerHeight - 420;
|
const maxHeight = window.innerHeight - 420;
|
||||||
return Math.min(Math.floor(maxWidth / GRID_WIDTH), Math.floor(maxHeight / GRID_HEIGHT), 18);
|
return Math.min(Math.floor(maxWidth / GRID_WIDTH), Math.floor(maxHeight / GRID_HEIGHT), 18);
|
||||||
}
|
}
|
||||||
return isFullscreen ? 30 : 24;
|
if (isFullscreen) {
|
||||||
|
// Fill screen more in fullscreen - calculate based on available space
|
||||||
|
const maxWidth = window.innerWidth - 240; // Space for side panel
|
||||||
|
const maxHeight = window.innerHeight - 100; // Space for header
|
||||||
|
return Math.min(Math.floor(maxWidth / GRID_WIDTH), Math.floor(maxHeight / GRID_HEIGHT));
|
||||||
|
}
|
||||||
|
return 24;
|
||||||
}, [isFullscreen]);
|
}, [isFullscreen]);
|
||||||
|
|
||||||
const [cellSize, setCellSize] = useState(getCellSize);
|
const [cellSize, setCellSize] = useState(getCellSize);
|
||||||
@@ -678,7 +684,7 @@ const Pacman = () => {
|
|||||||
|
|
||||||
const renderPacman2 = () => (
|
const renderPacman2 = () => (
|
||||||
<svg viewBox="0 0 100 100" className="w-full h-full transition-transform duration-100 ease-out" style={{ transform: `rotate(${getPacmanRotation2()}deg)` }}>
|
<svg viewBox="0 0 100 100" className="w-full h-full transition-transform duration-100 ease-out" style={{ transform: `rotate(${getPacmanRotation2()}deg)` }}>
|
||||||
<circle cx="50" cy="50" r="45" fill="hsl(120 70% 50%)" className="transition-all duration-100 ease-out" />
|
<circle cx="50" cy="50" r="45" fill="hsl(var(--secondary))" className="transition-all duration-100 ease-out" />
|
||||||
{mouthOpen2 && <path d="M 50 50 L 95 25 L 95 75 Z" fill="hsl(var(--background))" className="transition-all duration-100 ease-out" />}
|
{mouthOpen2 && <path d="M 50 50 L 95 25 L 95 75 Z" fill="hsl(var(--background))" className="transition-all duration-100 ease-out" />}
|
||||||
<circle cx="50" cy="25" r="6" fill="hsl(var(--background))" className="transition-all duration-100 ease-out" />
|
<circle cx="50" cy="25" r="6" fill="hsl(var(--background))" className="transition-all duration-100 ease-out" />
|
||||||
</svg>
|
</svg>
|
||||||
@@ -713,7 +719,7 @@ const Pacman = () => {
|
|||||||
cells.push(
|
cells.push(
|
||||||
<div key={`${x}-${y}`} className={`flex items-center justify-center transition-all duration-200 ease-out ${isWall ? 'bg-primary/20 border border-primary/40' : isTunnel ? 'bg-background/30' : 'bg-background/50 border border-primary/5'}`} style={{ width: cellSize, height: cellSize }}>
|
<div key={`${x}-${y}`} className={`flex items-center justify-center transition-all duration-200 ease-out ${isWall ? 'bg-primary/20 border border-primary/40' : isTunnel ? 'bg-background/30' : 'bg-background/50 border border-primary/5'}`} style={{ width: cellSize, height: cellSize }}>
|
||||||
{isPacmanHere && <div className={`drop-shadow-lg ${p1Invulnerable ? 'animate-pulse' : ''}`} style={{ width: spriteSize, height: spriteSize, transition: 'all 0.2s ease-out', filter: 'drop-shadow(0 0 4px hsl(var(--primary)))', opacity: p1Invulnerable ? 0.5 : 1 }}>{renderPacman()}</div>}
|
{isPacmanHere && <div className={`drop-shadow-lg ${p1Invulnerable ? 'animate-pulse' : ''}`} style={{ width: spriteSize, height: spriteSize, transition: 'all 0.2s ease-out', filter: 'drop-shadow(0 0 4px hsl(var(--primary)))', opacity: p1Invulnerable ? 0.5 : 1 }}>{renderPacman()}</div>}
|
||||||
{isPacman2Here && <div className={`drop-shadow-lg ${p2Invulnerable ? 'animate-pulse' : ''}`} style={{ width: spriteSize, height: spriteSize, transition: 'all 0.2s ease-out', filter: 'drop-shadow(0 0 4px hsl(120 70% 50%))', opacity: p2Invulnerable ? 0.5 : 1 }}>{renderPacman2()}</div>}
|
{isPacman2Here && <div className={`drop-shadow-lg ${p2Invulnerable ? 'animate-pulse' : ''}`} style={{ width: spriteSize, height: spriteSize, transition: 'all 0.2s ease-out', filter: 'drop-shadow(0 0 4px hsl(var(--secondary)))', opacity: p2Invulnerable ? 0.5 : 1 }}>{renderPacman2()}</div>}
|
||||||
{ghostIndex !== -1 && !isPacmanHere && !isPacman2Here && <div style={{ width: spriteSize, height: spriteSize, transition: 'all 0.2s ease-out' }}>{renderGhost(ghostIndex, ghosts[ghostIndex].eaten)}</div>}
|
{ghostIndex !== -1 && !isPacmanHere && !isPacman2Here && <div style={{ width: spriteSize, height: spriteSize, transition: 'all 0.2s ease-out' }}>{renderGhost(ghostIndex, ghosts[ghostIndex].eaten)}</div>}
|
||||||
{isFruitHere && !isPacmanHere && !isPacman2Here && ghostIndex === -1 && (
|
{isFruitHere && !isPacmanHere && !isPacman2Here && ghostIndex === -1 && (
|
||||||
<div className="animate-bounce text-lg" style={{ fontSize: `${Math.max(cellSize * 0.7, 14)}px` }} title={`${fruit.points} points`}>
|
<div className="animate-bounce text-lg" style={{ fontSize: `${Math.max(cellSize * 0.7, 14)}px` }} title={`${fruit.points} points`}>
|
||||||
@@ -764,8 +770,8 @@ const Pacman = () => {
|
|||||||
<p className="font-minecraft text-lg text-primary text-glow">{score.toLocaleString()}</p>
|
<p className="font-minecraft text-lg text-primary text-glow">{score.toLocaleString()}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<p className="font-pixel text-[8px]" style={{ color: 'hsl(120 70% 50%)' }}>P2</p>
|
<p className="font-pixel text-[8px] text-secondary">P2</p>
|
||||||
<p className="font-minecraft text-lg" style={{ color: 'hsl(120 70% 50%)', textShadow: '0 0 10px hsl(120 70% 50%)' }}>{score2.toLocaleString()}</p>
|
<p className="font-minecraft text-lg text-secondary" style={{ textShadow: '0 0 10px hsl(var(--secondary))' }}>{score2.toLocaleString()}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -795,7 +801,7 @@ const Pacman = () => {
|
|||||||
<div className="flex justify-center gap-2 mt-1">
|
<div className="flex justify-center gap-2 mt-1">
|
||||||
<span className="font-minecraft text-sm text-primary">{lives}</span>
|
<span className="font-minecraft text-sm text-primary">{lives}</span>
|
||||||
<span className="text-foreground/30">/</span>
|
<span className="text-foreground/30">/</span>
|
||||||
<span className="font-minecraft text-sm" style={{ color: 'hsl(120 70% 50%)' }}>{lives2}</span>
|
<span className="font-minecraft text-sm text-secondary">{lives2}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -816,7 +822,7 @@ const Pacman = () => {
|
|||||||
<p className="font-pixel text-[9px] text-foreground/60">WASD</p>
|
<p className="font-pixel text-[9px] text-foreground/60">WASD</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className="font-pixel text-[8px]" style={{ color: 'hsl(120 70% 50%)' }}>P2</p>
|
<p className="font-pixel text-[8px] text-secondary">P2</p>
|
||||||
<p className="font-pixel text-[9px] text-foreground/60">IJKL</p>
|
<p className="font-pixel text-[9px] text-foreground/60">IJKL</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+13
-4
@@ -13,7 +13,7 @@ import GameTouchButton from '@/components/GameTouchButton';
|
|||||||
import MatrixCursor from '@/components/MatrixCursor';
|
import MatrixCursor from '@/components/MatrixCursor';
|
||||||
|
|
||||||
const GRID_SIZE = 20;
|
const GRID_SIZE = 20;
|
||||||
const TICK_SPEED = 120;
|
const TICK_SPEED = 150;
|
||||||
const MAX_SCORE = 4294967296;
|
const MAX_SCORE = 4294967296;
|
||||||
const HIGHSCORE_KEY = 'snake-highscore';
|
const HIGHSCORE_KEY = 'snake-highscore';
|
||||||
|
|
||||||
@@ -78,10 +78,19 @@ const Snake = () => {
|
|||||||
const maxHeight = window.innerHeight - 420;
|
const maxHeight = window.innerHeight - 420;
|
||||||
return Math.min(Math.floor(maxWidth / GRID_SIZE), Math.floor(maxHeight / GRID_SIZE), 20);
|
return Math.min(Math.floor(maxWidth / GRID_SIZE), Math.floor(maxHeight / GRID_SIZE), 20);
|
||||||
}
|
}
|
||||||
if (gameMode === '2p') {
|
if (isFullscreen) {
|
||||||
return isFullscreen ? 24 : 20;
|
if (gameMode === '2p') {
|
||||||
|
// Two grids side by side
|
||||||
|
const maxWidth = (window.innerWidth - 100) / 2;
|
||||||
|
const maxHeight = window.innerHeight - 150;
|
||||||
|
return Math.min(Math.floor(maxWidth / GRID_SIZE), Math.floor(maxHeight / GRID_SIZE));
|
||||||
|
}
|
||||||
|
// Single player - fill screen
|
||||||
|
const maxWidth = window.innerWidth - 280;
|
||||||
|
const maxHeight = window.innerHeight - 100;
|
||||||
|
return Math.min(Math.floor(maxWidth / GRID_SIZE), Math.floor(maxHeight / GRID_SIZE));
|
||||||
}
|
}
|
||||||
return isFullscreen ? 32 : 28;
|
return gameMode === '2p' ? 20 : 28;
|
||||||
}, [isFullscreen, gameMode]);
|
}, [isFullscreen, gameMode]);
|
||||||
|
|
||||||
const [cellSize, setCellSize] = useState(getCellSize);
|
const [cellSize, setCellSize] = useState(getCellSize);
|
||||||
|
|||||||
Reference in New Issue
Block a user