Spaces:
Running
Running
Create index.html
Browse files- index.html +159 -0
index.html
ADDED
@@ -0,0 +1,159 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React, { useState, useEffect } from 'react';
|
2 |
+
import { AlertCircle, Axe, Box, Building, Cpu, Factory, Zap } from 'lucide-react';
|
3 |
+
|
4 |
+
const Game = () => {
|
5 |
+
const [selectedTool, setSelectedTool] = useState(null);
|
6 |
+
const [grid, setGrid] = useState(() =>
|
7 |
+
Array(8).fill().map(() => Array(8).fill({ type: null, color: 'white' }))
|
8 |
+
);
|
9 |
+
const [resources, setResources] = useState({ energy: 50, minerals: 50, circuits: 0 });
|
10 |
+
const [tick, setTick] = useState(0);
|
11 |
+
const [researchProgress, setResearchProgress] = useState({ automation: 0, speed: 0 });
|
12 |
+
const [message, setMessage] = useState('');
|
13 |
+
|
14 |
+
const tools = {
|
15 |
+
solarPanel: {
|
16 |
+
cost: { minerals: 10 },
|
17 |
+
color: 'bg-yellow-200',
|
18 |
+
produces: 'energy',
|
19 |
+
icon: <Zap className="w-6 h-6" />
|
20 |
+
},
|
21 |
+
mineralExtractor: {
|
22 |
+
cost: { energy: 10 },
|
23 |
+
color: 'bg-gray-300',
|
24 |
+
produces: 'minerals',
|
25 |
+
icon: <Box className="w-6 h-6" />
|
26 |
+
},
|
27 |
+
circuitFactory: {
|
28 |
+
cost: { energy: 15, minerals: 15 },
|
29 |
+
color: 'bg-green-200',
|
30 |
+
produces: 'circuits',
|
31 |
+
icon: <Cpu className="w-6 h-6" />
|
32 |
+
}
|
33 |
+
};
|
34 |
+
|
35 |
+
// Game tick for resource production
|
36 |
+
useEffect(() => {
|
37 |
+
const timer = setInterval(() => {
|
38 |
+
setTick(t => t + 1);
|
39 |
+
setResources(prev => {
|
40 |
+
const newResources = { ...prev };
|
41 |
+
grid.forEach(row => {
|
42 |
+
row.forEach(cell => {
|
43 |
+
if (cell.type && tools[cell.type]) {
|
44 |
+
const produces = tools[cell.type].produces;
|
45 |
+
newResources[produces] = (newResources[produces] || 0) + 1;
|
46 |
+
}
|
47 |
+
});
|
48 |
+
});
|
49 |
+
return newResources;
|
50 |
+
});
|
51 |
+
}, 1000);
|
52 |
+
|
53 |
+
return () => clearInterval(timer);
|
54 |
+
}, [grid]);
|
55 |
+
|
56 |
+
const handleCellClick = (rowIndex, colIndex) => {
|
57 |
+
if (!selectedTool) {
|
58 |
+
setMessage('Select a building first!');
|
59 |
+
return;
|
60 |
+
}
|
61 |
+
|
62 |
+
const tool = tools[selectedTool];
|
63 |
+
const canAfford = Object.entries(tool.cost).every(
|
64 |
+
([resource, cost]) => resources[resource] >= cost
|
65 |
+
);
|
66 |
+
|
67 |
+
if (!canAfford) {
|
68 |
+
setMessage('Not enough resources!');
|
69 |
+
return;
|
70 |
+
}
|
71 |
+
|
72 |
+
// Deduct costs
|
73 |
+
setResources(prev => {
|
74 |
+
const newResources = { ...prev };
|
75 |
+
Object.entries(tool.cost).forEach(([resource, cost]) => {
|
76 |
+
newResources[resource] -= cost;
|
77 |
+
});
|
78 |
+
return newResources;
|
79 |
+
});
|
80 |
+
|
81 |
+
// Place building
|
82 |
+
setGrid(prev => {
|
83 |
+
const newGrid = [...prev];
|
84 |
+
newGrid[rowIndex] = [...prev[rowIndex]];
|
85 |
+
newGrid[rowIndex][colIndex] = {
|
86 |
+
type: selectedTool,
|
87 |
+
color: tool.color
|
88 |
+
};
|
89 |
+
return newGrid;
|
90 |
+
});
|
91 |
+
|
92 |
+
// Show success message
|
93 |
+
setMessage(`Built ${selectedTool}!`);
|
94 |
+
setTimeout(() => setMessage(''), 2000);
|
95 |
+
};
|
96 |
+
|
97 |
+
return (
|
98 |
+
<div className="p-4 max-w-4xl mx-auto">
|
99 |
+
{/* Resources */}
|
100 |
+
<div className="grid grid-cols-3 gap-4 mb-6">
|
101 |
+
<div className="p-3 bg-yellow-100 rounded-lg flex items-center gap-2">
|
102 |
+
<Zap className="w-4 h-4" />
|
103 |
+
<span>Energy: {resources.energy}</span>
|
104 |
+
</div>
|
105 |
+
<div className="p-3 bg-gray-100 rounded-lg flex items-center gap-2">
|
106 |
+
<Box className="w-4 h-4" />
|
107 |
+
<span>Minerals: {resources.minerals}</span>
|
108 |
+
</div>
|
109 |
+
<div className="p-3 bg-green-100 rounded-lg flex items-center gap-2">
|
110 |
+
<Cpu className="w-4 h-4" />
|
111 |
+
<span>Circuits: {resources.circuits}</span>
|
112 |
+
</div>
|
113 |
+
</div>
|
114 |
+
|
115 |
+
{/* Tool Selection */}
|
116 |
+
<div className="mb-6">
|
117 |
+
<div className="flex gap-4 mb-4">
|
118 |
+
{Object.entries(tools).map(([name, data]) => (
|
119 |
+
<button
|
120 |
+
key={name}
|
121 |
+
onClick={() => setSelectedTool(name)}
|
122 |
+
className={`p-4 rounded-lg flex flex-col items-center ${data.color}
|
123 |
+
${selectedTool === name ? 'ring-2 ring-blue-500' : ''}`}
|
124 |
+
>
|
125 |
+
{data.icon}
|
126 |
+
<span className="text-sm mt-2">{name.replace(/([A-Z])/g, ' $1').trim()}</span>
|
127 |
+
<span className="text-xs mt-1">
|
128 |
+
Cost: {Object.entries(data.cost).map(([r, c]) => `${c} ${r}`).join(', ')}
|
129 |
+
</span>
|
130 |
+
</button>
|
131 |
+
))}
|
132 |
+
</div>
|
133 |
+
{message && (
|
134 |
+
<div className="text-center text-sm font-medium text-blue-600 mb-2">
|
135 |
+
{message}
|
136 |
+
</div>
|
137 |
+
)}
|
138 |
+
</div>
|
139 |
+
|
140 |
+
{/* Game Grid */}
|
141 |
+
<div className="grid grid-cols-8 gap-1 bg-gray-100 p-2 rounded-lg">
|
142 |
+
{grid.map((row, rowIndex) => (
|
143 |
+
row.map((cell, colIndex) => (
|
144 |
+
<button
|
145 |
+
key={`${rowIndex}-${colIndex}`}
|
146 |
+
onClick={() => handleCellClick(rowIndex, colIndex)}
|
147 |
+
className={`w-16 h-16 rounded-lg ${cell.type ? tools[cell.type].color : 'bg-white'}
|
148 |
+
hover:bg-opacity-80 transition-colors flex items-center justify-center`}
|
149 |
+
>
|
150 |
+
{cell.type && tools[cell.type].icon}
|
151 |
+
</button>
|
152 |
+
))
|
153 |
+
))}
|
154 |
+
</div>
|
155 |
+
</div>
|
156 |
+
);
|
157 |
+
};
|
158 |
+
|
159 |
+
export default Game;
|