70 lines
2.3 KiB
TypeScript
70 lines
2.3 KiB
TypeScript
import React from 'react';
|
|
import { GridCell } from '../types';
|
|
import { Zap, Footprints, Flag, BrickWall } from 'lucide-react';
|
|
|
|
interface CellProps {
|
|
cell: GridCell;
|
|
isPlayerHere: boolean;
|
|
}
|
|
|
|
export const Cell: React.FC<CellProps> = React.memo(({ cell, isPlayerHere }) => {
|
|
// Base style
|
|
let bgColor = 'bg-gray-700'; // Default hidden color
|
|
let borderColor = 'border-gray-800';
|
|
let icon = null;
|
|
|
|
if (cell.revealed) {
|
|
switch (cell.type) {
|
|
case 'wall':
|
|
bgColor = 'bg-slate-800 shadow-inner';
|
|
borderColor = 'border-slate-900';
|
|
icon = <div className="w-full h-full flex items-center justify-center"><BrickWall size={12} className="text-stone-500 opacity-50" /></div>;
|
|
break;
|
|
case 'trap':
|
|
bgColor = 'bg-red-900/80';
|
|
borderColor = 'border-red-950';
|
|
icon = <Zap size={14} className="text-red-500" />;
|
|
break;
|
|
case 'start':
|
|
bgColor = 'bg-emerald-900/50';
|
|
borderColor = 'border-emerald-800';
|
|
break;
|
|
case 'end':
|
|
bgColor = 'bg-yellow-900/50';
|
|
borderColor = 'border-yellow-800';
|
|
icon = <Flag size={14} className="text-yellow-500" />;
|
|
break;
|
|
case 'safe':
|
|
bgColor = 'bg-gray-600';
|
|
borderColor = 'border-gray-500';
|
|
if (cell.steppedOn && !isPlayerHere) {
|
|
bgColor = 'bg-gray-600/80';
|
|
icon = <Footprints size={10} className="text-gray-500/30" />;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Visual highlight for the player
|
|
const playerOverlay = isPlayerHere ? (
|
|
<div className="absolute inset-0 flex items-center justify-center z-10 pointer-events-none">
|
|
<div className="w-3/4 h-3/4 bg-blue-500 rounded-full shadow-[0_0_10px_rgba(59,130,246,0.8)] animate-pulse border-2 border-white">
|
|
<div className="absolute top-1 left-1 w-1.5 h-1.5 bg-white rounded-full opacity-60"></div>
|
|
</div>
|
|
</div>
|
|
) : null;
|
|
|
|
return (
|
|
<div
|
|
className={`relative w-full h-full min-w-0 min-h-0 border ${borderColor} ${bgColor} flex items-center justify-center transition-colors duration-300 overflow-hidden box-border`}
|
|
>
|
|
{/* Icon Wrapper to ensure it doesn't shift layout */}
|
|
<div className="absolute inset-0 flex items-center justify-center pointer-events-none">
|
|
{icon}
|
|
</div>
|
|
{playerOverlay}
|
|
</div>
|
|
);
|
|
});
|
|
|
|
Cell.displayName = 'Cell'; |