awacke1 commited on
Commit
42db519
·
verified ·
1 Parent(s): a482ed9

Create index.html

Browse files
Files changed (1) hide show
  1. index.html +272 -0
index.html ADDED
@@ -0,0 +1,272 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Hexagon Ecosystem Game</title>
7
+ <style>
8
+ body { text-align: center; background-color: #282c34; color: white; font-family: Arial; }
9
+ #gameContainer { display: flex; justify-content: space-between; }
10
+ #sidebar { width: 300px; text-align: left; padding: 10px; }
11
+ canvas { background-color: #1e1e1e; cursor: pointer; }
12
+ #timer, #counts, #selection { font-size: 18px; margin-top: 10px; }
13
+ button { margin: 3px; padding: 8px; font-size: 14px; cursor: pointer; }
14
+ .category { margin-top: 15px; }
15
+ </style>
16
+ </head>
17
+ <body>
18
+ <h1>🌱 Hexagon Ecosystem Game 🐝</h1>
19
+ <div id="gameContainer">
20
+ <div id="sidebar">
21
+ <div id="timer">Time Left: 5:00</div>
22
+ <div id="counts">Counts: Loading...</div>
23
+ <div id="selection">
24
+ <div class="category"><strong>Plants</strong></div>
25
+ <div id="plantSelection"></div>
26
+ <div class="category"><strong>Insects</strong></div>
27
+ <div id="insectSelection"></div>
28
+ <div class="category"><strong>Animals</strong></div>
29
+ <div id="animalSelection"></div>
30
+ </div>
31
+ </div>
32
+ <canvas id="gameCanvas" width="800" height="600"></canvas>
33
+ </div>
34
+ <script>
35
+ const canvas = document.getElementById("gameCanvas");
36
+ const ctx = canvas.getContext("2d");
37
+
38
+ const hexSize = 40;
39
+ const hexWidth = Math.sqrt(3) * hexSize;
40
+ const hexHeight = 2 * hexSize;
41
+ const offsetX = hexWidth;
42
+ const offsetY = hexHeight * 0.75;
43
+ const rows = 10;
44
+ const cols = 10;
45
+ let hexGrid = [];
46
+ let timer = 300;
47
+ let selectedEntity = null;
48
+
49
+ const entities = {
50
+ plants: ["🌱", "🌿", "🍁", "🌺", "🌸", "🌼", "🌻", "🌾", "🌳", "🌴", "🍂", "🍃", "🍇", "🍊", "🍎", "🍑", "🍒", "🍓", "🍍", "🥕"],
51
+ insects: ["🐝", "🦋", "🐞"],
52
+ animals: ["🐇", "🦊", "🦌", "🐦", "🐿️"]
53
+ };
54
+ let resources = {};
55
+ let counts = {};
56
+
57
+ function initializeEntities() {
58
+ Object.keys(entities).forEach(category => {
59
+ entities[category].forEach(entity => {
60
+ resources[entity] = 5;
61
+ counts[entity] = 0;
62
+ });
63
+ });
64
+ }
65
+
66
+ function generateHexGrid() {
67
+ for (let row = 0; row < rows; row++) {
68
+ for (let col = 0; col < cols; col++) {
69
+ let x = col * offsetX + 150;
70
+ let y = row * hexHeight + (col % 2 ? offsetY : 0) + 50;
71
+ hexGrid.push({ x, y, type: "empty", entities: [], pollinated: false });
72
+ }
73
+ }
74
+ }
75
+
76
+ function selectEntity(entity) {
77
+ selectedEntity = entity;
78
+ }
79
+
80
+ function drawHex(hex) {
81
+ const { x, y, type, entities } = hex;
82
+ ctx.beginPath();
83
+ for (let i = 0; i < 6; i++) {
84
+ let angle = (Math.PI / 3) * i;
85
+ let px = x + hexSize * Math.cos(angle);
86
+ let py = y + hexSize * Math.sin(angle);
87
+ ctx.lineTo(px, py);
88
+ }
89
+ ctx.closePath();
90
+ ctx.fillStyle = type === "empty" ? "#C2B280" : "#90EE90";
91
+ ctx.fill();
92
+ ctx.stroke();
93
+ ctx.fillStyle = "white";
94
+ ctx.font = "20px Arial";
95
+ entities.forEach((entity, index) => {
96
+ let randX = x - 10 + (Math.random() * 20 - 10);
97
+ let randY = y + 5 + (Math.random() * 20 - 10);
98
+ ctx.fillText(entity, randX, randY);
99
+ });
100
+ }
101
+
102
+ function getNeighbors(hexIndex) {
103
+ const neighbors = [];
104
+ const row = Math.floor(hexIndex / cols);
105
+ const col = hexIndex % cols;
106
+ const directions = [
107
+ [-1, 0], [1, 0], [0, -1], [0, 1],
108
+ col % 2 ? [-1, -1] : [-1, 1],
109
+ col % 2 ? [1, -1] : [1, 1]
110
+ ];
111
+ directions.forEach(([dr, dc]) => {
112
+ const newRow = row + dr;
113
+ const newCol = col + dc;
114
+ if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols) {
115
+ neighbors.push(newRow * cols + newCol);
116
+ }
117
+ });
118
+ return neighbors;
119
+ }
120
+
121
+ function pollinate() {
122
+ hexGrid.forEach((hex, index) => {
123
+ if (hex.entities.some(e => entities.insects.includes(e))) {
124
+ hex.entities.forEach(entity => {
125
+ if (entities.plants.includes(entity)) {
126
+ getNeighbors(index).forEach(n => {
127
+ if (hexGrid[n].type === "empty" && Math.random() < 0.1) {
128
+ hexGrid[n].entities.push(entity);
129
+ hexGrid[n].type = "occupied";
130
+ counts[entity]++;
131
+ }
132
+ });
133
+ }
134
+ });
135
+ }
136
+ });
137
+ }
138
+
139
+ function aStar(startIdx, goalIdx) {
140
+ const openSet = new Set([startIdx]);
141
+ const cameFrom = {};
142
+ const gScore = { [startIdx]: 0 };
143
+ const fScore = { [startIdx]: heuristic(startIdx, goalIdx) };
144
+
145
+ while (openSet.size > 0) {
146
+ let current = Array.from(openSet).reduce((a, b) => fScore[a] < fScore[b] ? a : b);
147
+ if (current === goalIdx) return reconstructPath(cameFrom, current);
148
+
149
+ openSet.delete(current);
150
+ getNeighbors(current).forEach(neighbor => {
151
+ const tentativeGScore = gScore[current] + 1;
152
+ if (!gScore[neighbor] || tentativeGScore < gScore[neighbor]) {
153
+ cameFrom[neighbor] = current;
154
+ gScore[neighbor] = tentativeGScore;
155
+ fScore[neighbor] = gScore[neighbor] + heuristic(neighbor, goalIdx);
156
+ openSet.add(neighbor);
157
+ }
158
+ });
159
+ }
160
+ return [];
161
+ }
162
+
163
+ function heuristic(a, b) {
164
+ const rowA = Math.floor(a / cols), colA = a % cols;
165
+ const rowB = Math.floor(b / cols), colB = b % cols;
166
+ return Math.abs(rowA - rowB) + Math.abs(colA - colB);
167
+ }
168
+
169
+ function reconstructPath(cameFrom, current) {
170
+ const path = [current];
171
+ while (cameFrom[current] !== undefined) {
172
+ current = cameFrom[current];
173
+ path.unshift(current);
174
+ }
175
+ return path;
176
+ }
177
+
178
+ function moveAnimals() {
179
+ hexGrid.forEach((hex, index) => {
180
+ hex.entities.forEach((entity, i) => {
181
+ if (entities.animals.includes(entity)) {
182
+ const neighbors = getNeighbors(index);
183
+ const mateIdx = neighbors.find(n => hexGrid[n].entities.includes(entity));
184
+ if (mateIdx && Math.random() < 0.05) {
185
+ const emptyNeighbor = neighbors.find(n => hexGrid[n].type === "empty");
186
+ if (emptyNeighbor) {
187
+ hexGrid[emptyNeighbor].entities.push(entity);
188
+ hexGrid[emptyNeighbor].type = "occupied";
189
+ counts[entity]++;
190
+ }
191
+ } else if (Math.random() < 0.2) {
192
+ const path = aStar(index, mateIdx || neighbors[Math.floor(Math.random() * neighbors.length)]);
193
+ if (path.length > 1) {
194
+ hexGrid[path[1]].entities.push(entity);
195
+ hex.entities.splice(i, 1);
196
+ if (hex.entities.length === 0) hex.type = "empty";
197
+ hexGrid[path[1]].type = "occupied";
198
+ }
199
+ }
200
+ }
201
+ });
202
+ });
203
+ }
204
+
205
+ function renderMap() {
206
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
207
+ hexGrid.forEach(hex => drawHex(hex));
208
+ }
209
+
210
+ function updateTimer() {
211
+ timer--;
212
+ document.getElementById("timer").innerText = `Time Left: ${Math.floor(timer / 60)}:${(timer % 60).toString().padStart(2, '0')}`;
213
+ if (timer % 5 === 0) {
214
+ pollinate();
215
+ moveAnimals();
216
+ updateCounts();
217
+ }
218
+ renderMap();
219
+ if (timer <= 0) {
220
+ clearInterval(gameLoop);
221
+ alert("Game Over!");
222
+ }
223
+ }
224
+
225
+ function updateCounts() {
226
+ let countText = "Counts: ";
227
+ Object.keys(counts).forEach(entity => {
228
+ countText += `${entity}: ${counts[entity]} `;
229
+ });
230
+ document.getElementById("counts").innerText = countText;
231
+ }
232
+
233
+ function populateSidebar() {
234
+ ["plantSelection", "insectSelection", "animalSelection"].forEach((id, idx) => {
235
+ const category = ["plants", "insects", "animals"][idx];
236
+ const div = document.getElementById(id);
237
+ entities[category].forEach(entity => {
238
+ const btn = document.createElement("button");
239
+ btn.innerText = entity;
240
+ btn.onclick = () => selectEntity(entity);
241
+ div.appendChild(btn);
242
+ });
243
+ });
244
+ }
245
+
246
+ canvas.addEventListener("click", (event) => {
247
+ const rect = canvas.getBoundingClientRect();
248
+ const mouseX = event.clientX - rect.left;
249
+ const mouseY = event.clientY - rect.top;
250
+
251
+ hexGrid.forEach(hex => {
252
+ if (Math.hypot(hex.x - mouseX, hex.y - mouseY) < hexSize) {
253
+ if (selectedEntity && resources[selectedEntity] > 0 && hex.type === "empty") {
254
+ hex.type = "occupied";
255
+ hex.entities.push(selectedEntity);
256
+ resources[selectedEntity]--;
257
+ counts[selectedEntity]++;
258
+ updateCounts();
259
+ }
260
+ }
261
+ });
262
+ renderMap();
263
+ });
264
+
265
+ initializeEntities();
266
+ generateHexGrid();
267
+ populateSidebar();
268
+ renderMap();
269
+ let gameLoop = setInterval(updateTimer, 1000);
270
+ </script>
271
+ </body>
272
+ </html>