Signed-off-by: ale <ale@manalejandro.com>
Este commit está contenido en:
ale
2025-12-05 23:40:41 +01:00
padre 8234530ed7
commit 98b4bf92c6
Se han modificado 7 ficheros con 49 adiciones y 35 borrados

Ver fichero

@@ -57,12 +57,14 @@ function startGame(roomId: string): GameState {
}
export async function GET(req: NextRequest) {
// @ts-ignore
// @ts-expect-error - NextRequest extended with socket server
const res = req.res || req.nextUrl;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if (!(res as any).socket?.server?.io) {
console.log('Initializing Socket.IO server...');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const httpServer: HTTPServer = (res as any).socket.server;
const io = new SocketIOServer(httpServer, {
path: '/api/socket',
@@ -167,7 +169,7 @@ export async function GET(req: NextRequest) {
gameRooms.set(roomId, newGameState);
io.to(roomId).emit('game-state-updated', newGameState);
} catch (error) {
} catch {
socket.emit('invalid-move', 'Invalid move');
}
});
@@ -220,6 +222,7 @@ export async function GET(req: NextRequest) {
});
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(res as any).socket.server.io = io;
}

Ver fichero

@@ -1,6 +1,6 @@
'use client';
import React, { useRef, useEffect, useState } from 'react';
import React, { useRef, useEffect, useState, useMemo } from 'react';
import { PlacedTile, Position } from '@/lib/types';
interface GameBoardProps {
@@ -17,7 +17,7 @@ export function GameBoard({ placedTiles, width = 1200, height = 700, className =
const [isDragging, setIsDragging] = useState(false);
const [dragStart, setDragStart] = useState<Position>({ x: 0, y: 0 });
const [canvasSize, setCanvasSize] = useState({ width, height });
const [zoom, setZoom] = useState(1);
const initialZoom = 1;
// Handle responsive canvas sizing
useEffect(() => {
@@ -37,8 +37,8 @@ export function GameBoard({ placedTiles, width = 1200, height = 700, className =
}, [width, height]);
// Auto-zoom and auto-center to fit all tiles
useEffect(() => {
if (placedTiles.length === 0) return;
const autoFitValues = useMemo(() => {
if (placedTiles.length === 0) return null;
// Calculate bounding box of all tiles
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
@@ -65,7 +65,7 @@ export function GameBoard({ placedTiles, width = 1200, height = 700, className =
const contentHeight = maxY - minY;
// Calculate zoom to fit all tiles in viewport
const isMobile = window.innerWidth < 640;
const isMobile = typeof window !== 'undefined' && window.innerWidth < 640;
const zoomX = canvasSize.width / contentWidth;
const zoomY = canvasSize.height / contentHeight;
@@ -83,10 +83,13 @@ export function GameBoard({ placedTiles, width = 1200, height = 700, className =
const newOffsetX = canvasSize.width / 2 - centerX * newZoom;
const newOffsetY = canvasSize.height / 2 - centerY * newZoom;
setZoom(newZoom);
setOffset({ x: newOffsetX, y: newOffsetY });
return { zoom: newZoom, offset: { x: newOffsetX, y: newOffsetY } };
}, [placedTiles, canvasSize.width, canvasSize.height]);
// Derive effective zoom and offset values
const effectiveZoom = autoFitValues?.zoom ?? initialZoom;
const effectiveOffset = autoFitValues?.offset ?? offset;
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
@@ -118,27 +121,27 @@ export function GameBoard({ placedTiles, width = 1200, height = 700, className =
}
// Draw placed tiles
placedTiles.forEach((placedTile, index) => {
placedTiles.forEach((placedTile) => {
const { tile, position, orientation } = placedTile;
const tileWidth = orientation === 'horizontal' ? 60 : 30;
const tileHeight = orientation === 'horizontal' ? 30 : 60;
const x = position.x * zoom + offset.x;
const y = position.y * zoom + offset.y;
const scaledWidth = tileWidth * zoom;
const scaledHeight = tileHeight * zoom;
const x = position.x * effectiveZoom + effectiveOffset.x;
const y = position.y * effectiveZoom + effectiveOffset.y;
const scaledWidth = tileWidth * effectiveZoom;
const scaledHeight = tileHeight * effectiveZoom;
// Draw tile background with shadow
ctx.shadowColor = 'rgba(0, 0, 0, 0.2)';
ctx.shadowBlur = 5 * zoom;
ctx.shadowOffsetX = 2 * zoom;
ctx.shadowOffsetY = 2 * zoom;
ctx.shadowBlur = 5 * effectiveZoom;
ctx.shadowOffsetX = 2 * effectiveZoom;
ctx.shadowOffsetY = 2 * effectiveZoom;
ctx.fillStyle = '#ffffff';
ctx.strokeStyle = '#1f2937';
ctx.lineWidth = 2 * zoom;
ctx.lineWidth = 2 * effectiveZoom;
const radius = 4 * zoom;
const radius = 4 * effectiveZoom;
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + scaledWidth - radius, y);
@@ -158,7 +161,7 @@ export function GameBoard({ placedTiles, width = 1200, height = 700, className =
// Draw center divider
ctx.strokeStyle = '#6b7280';
ctx.lineWidth = 1 * zoom;
ctx.lineWidth = 1 * effectiveZoom;
ctx.beginPath();
if (orientation === 'horizontal') {
ctx.moveTo(x + scaledWidth / 2, y);
@@ -170,7 +173,7 @@ export function GameBoard({ placedTiles, width = 1200, height = 700, className =
ctx.stroke();
// Draw dots
const dotRadius = Math.max(2, 2.5 * zoom);
const dotRadius = Math.max(2, 2.5 * effectiveZoom);
ctx.fillStyle = '#1f2937';
const drawDots = (value: number, dotX: number, dotY: number, size: number) => {
@@ -186,7 +189,7 @@ export function GameBoard({ placedTiles, width = 1200, height = 700, className =
const leftX = x + scaledWidth / 4;
const rightX = x + (scaledWidth * 3) / 4;
const centerY = y + scaledHeight / 2;
const dotAreaSize = (scaledWidth / 2 - 6 * zoom);
const dotAreaSize = (scaledWidth / 2 - 6 * effectiveZoom);
drawDots(tile.left, leftX, centerY, dotAreaSize);
drawDots(tile.right, rightX, centerY, dotAreaSize);
@@ -194,14 +197,14 @@ export function GameBoard({ placedTiles, width = 1200, height = 700, className =
const topY = y + scaledHeight / 4;
const bottomY = y + (scaledHeight * 3) / 4;
const centerX = x + scaledWidth / 2;
const dotAreaSize = (scaledHeight / 2 - 6 * zoom);
const dotAreaSize = (scaledHeight / 2 - 6 * effectiveZoom);
drawDots(tile.left, centerX, topY, dotAreaSize);
drawDots(tile.right, centerX, bottomY, dotAreaSize);
}
});
}, [placedTiles, offset, zoom, canvasSize.width, canvasSize.height]);
}, [placedTiles, effectiveOffset, effectiveZoom, canvasSize.width, canvasSize.height]);
const handleMouseDown = (e: React.MouseEvent<HTMLCanvasElement>) => {
setIsDragging(true);

Ver fichero

@@ -7,10 +7,10 @@ interface LobbyProps {
onCreateRoom: (playerName: string) => void;
onJoinRoom: (roomId: string, playerName: string) => void;
onStartAI: (playerName: string) => void;
roomId: string | null;
roomId?: string | null;
}
export function Lobby({ onCreateRoom, onJoinRoom, onStartAI, roomId }: LobbyProps) {
export function Lobby({ onCreateRoom, onJoinRoom, onStartAI }: LobbyProps) {
const [playerName, setPlayerName] = useState('');
const [joinRoomId, setJoinRoomId] = useState('');
const [mode, setMode] = useState<'menu' | 'create' | 'join' | 'ai'>('menu');

Ver fichero

@@ -151,7 +151,7 @@ export function calculateTilePosition(
const lastTile = side === 'right' ? board[board.length - 1] : board[0];
let position: Position;
let orientation: 'horizontal' | 'vertical' = 'horizontal';
let rotation = 0;
const rotation = 0;
if (side === 'right') {
const offset = lastTile.orientation === 'horizontal' ? tileWidth : tileHeight;

Ver fichero

@@ -163,7 +163,7 @@ io.on('connection', (socket) => {
gameRooms.set(roomId, newGameState);
io.to(roomId).emit('game-state-updated', newGameState);
} catch (error) {
} catch {
socket.emit('invalid-move', 'Invalid move');
}
});

Ver fichero

@@ -11,9 +11,9 @@
},
"dependencies": {
"framer-motion": "^12.23.24",
"next": "16.0.1",
"react": "19.2.0",
"react-dom": "19.2.0",
"next": "15.4.8",
"react": "19.1.2",
"react-dom": "19.1.2",
"socket.io": "^4.8.1",
"socket.io-client": "^4.8.1",
"zustand": "^5.0.8"

Ver fichero

@@ -1,7 +1,11 @@
{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
@@ -11,7 +15,7 @@
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"jsx": "preserve",
"incremental": true,
"plugins": [
{
@@ -19,7 +23,9 @@
}
],
"paths": {
"@/*": ["./*"]
"@/*": [
"./*"
]
}
},
"include": [
@@ -30,5 +36,7 @@
".next/dev/types/**/*.ts",
"**/*.mts"
],
"exclude": ["node_modules"]
"exclude": [
"node_modules"
]
}