furuknap commited on
Commit
ae970f3
·
verified ·
1 Parent(s): ce0ef5a

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +1152 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Pvzclone
3
- emoji: 🏃
4
- colorFrom: green
5
- colorTo: green
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: pvzclone
3
+ emoji: 🐳
4
+ colorFrom: blue
5
+ colorTo: blue
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,1152 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>Plants vs Zombies Clone</title>
7
+ <style>
8
+ @import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap');
9
+
10
+ * {
11
+ margin: 0;
12
+ padding: 0;
13
+ box-sizing: border-box;
14
+ }
15
+
16
+ body {
17
+ background-color: #2c3e50;
18
+ font-family: 'Press Start 2P', cursive;
19
+ overflow: hidden;
20
+ color: #ecf0f1;
21
+ }
22
+
23
+ #game-container {
24
+ width: 100vw;
25
+ height: 100vh;
26
+ position: relative;
27
+ background-image: linear-gradient(#5da130, #3b7a1f);
28
+ }
29
+
30
+ #lawn {
31
+ width: 100%;
32
+ height: calc(100% - 120px);
33
+ position: relative;
34
+ display: grid;
35
+ grid-template-columns: repeat(9, 1fr);
36
+ grid-template-rows: repeat(5, 1fr);
37
+ }
38
+
39
+ .lawn-cell {
40
+ border: 1px dashed rgba(255, 255, 255, 0.2);
41
+ position: relative;
42
+ }
43
+
44
+ #ui-container {
45
+ height: 120px;
46
+ background-color: #4a2512;
47
+ border-top: 4px solid #6d4724;
48
+ display: flex;
49
+ justify-content: space-between;
50
+ padding: 10px;
51
+ }
52
+
53
+ #sun-counter {
54
+ width: 100px;
55
+ height: 100px;
56
+ background-color: #f1c40f;
57
+ border-radius: 50%;
58
+ display: flex;
59
+ justify-content: center;
60
+ align-items: center;
61
+ font-size: 24px;
62
+ color: #e67e22;
63
+ box-shadow: 0 0 10px rgba(241, 196, 15, 0.5);
64
+ position: relative;
65
+ }
66
+
67
+ #plant-selection {
68
+ display: flex;
69
+ gap: 10px;
70
+ }
71
+
72
+ .plant-option {
73
+ width: 80px;
74
+ height: 100px;
75
+ background-color: #3498db;
76
+ border-radius: 10px;
77
+ display: flex;
78
+ flex-direction: column;
79
+ justify-content: space-between;
80
+ align-items: center;
81
+ padding: 5px;
82
+ cursor: pointer;
83
+ transition: all 0.2s;
84
+ border: 3px solid transparent;
85
+ }
86
+
87
+ .plant-option:hover {
88
+ transform: scale(1.05);
89
+ }
90
+
91
+ .plant-option.selected {
92
+ border-color: #f1c40f;
93
+ box-shadow: 0 0 10px rgba(241, 196, 15, 0.8);
94
+ }
95
+
96
+ .plant-option .plant-icon {
97
+ width: 50px;
98
+ height: 50px;
99
+ border-radius: 50%;
100
+ background-size: contain;
101
+ background-repeat: no-repeat;
102
+ background-position: center;
103
+ }
104
+
105
+ .plant-option .cost {
106
+ font-size: 12px;
107
+ color: #f1c40f;
108
+ }
109
+
110
+ /* Plant elements */
111
+ .plant {
112
+ width: 80%;
113
+ height: 80%;
114
+ position: absolute;
115
+ top: 10%;
116
+ left: 10%;
117
+ background-size: contain;
118
+ background-repeat: no-repeat;
119
+ background-position: center;
120
+ z-index: 10;
121
+ }
122
+
123
+ .sunflower .plant {
124
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50"><circle cx="25" cy="25" r="20" fill="yellow"/><circle cx="25" cy="25" r="10" fill="orange"/><path d="M10,25 Q25,10 40,25 Q25,40 10,25" fill="yellow"/><path d="M25,10 Q40,25 25,40 Q10,25 25,10" fill="yellow"/></svg>');
125
+ }
126
+
127
+ .peashooter .plant {
128
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50"><ellipse cx="25" cy="30" rx="15" ry="20" fill="green"/><circle cx="25" cy="15" r="10" fill="lime"/><circle cx="30" cy="12" r="3" fill="black"/></svg>');
129
+ }
130
+
131
+ .wallnut .plant {
132
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50"><circle cx="25" cy="25" r="20" fill="saddlebrown"/><path d="M15,15 Q25,10 35,15 Q40,25 35,35 Q25,40 15,35 Q10,25 15,15" fill="peru"/></svg>');
133
+ }
134
+
135
+ /* Projectiles */
136
+ .pea {
137
+ width: 15px;
138
+ height: 15px;
139
+ background-color: lime;
140
+ border-radius: 50%;
141
+ position: absolute;
142
+ z-index: 20;
143
+ }
144
+
145
+ /* Zombie elements */
146
+ .zombie {
147
+ width: 60px;
148
+ height: 100px;
149
+ position: absolute;
150
+ right: -60px;
151
+ background-size: contain;
152
+ background-repeat: no-repeat;
153
+ background-position: center;
154
+ z-index: 5;
155
+ animation: zombie-walk 3s linear infinite;
156
+ }
157
+
158
+ @keyframes zombie-walk {
159
+ 0% { transform: translateX(0); }
160
+ 50% { transform: translateX(-5px) rotate(2deg); }
161
+ 100% { transform: translateX(0); }
162
+ }
163
+
164
+ .basic-zombie {
165
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50"><circle cx="25" cy="15" r="10" fill="darkgreen"/><rect x="15" y="25" width="20" height="15" fill="green"/><circle cx="20" cy="12" r="2" fill="black"/><circle cx="30" cy="12" r="2" fill="black"/></svg>');
166
+ }
167
+
168
+ .conehead-zombie {
169
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50"><path d="M15,5 L35,5 L25,15 Z" fill="gray"/><circle cx="25" cy="15" r="10" fill="darkgreen"/><rect x="15" y="25" width="20" height="15" fill="green"/><circle cx="20" cy="12" r="2" fill="black"/><circle cx="30" cy="12" r="2" fill="black"/></svg>');
170
+ }
171
+
172
+ .buckethead-zombie {
173
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50"><circle cx="25" cy="15" r="10" fill="darkgreen"/><rect x="20" y="15" width="10" height="10" fill="silver"/><rect x="15" y="25" width="20" height="15" fill="green"/><circle cx="20" cy="12" r="2" fill="black"/><circle cx="30" cy="12" r="2" fill="black"/></svg>');
174
+ }
175
+
176
+ /* Sun elements */
177
+ .sun {
178
+ width: 50px;
179
+ height: 50px;
180
+ position: absolute;
181
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50"><circle cx="25" cy="25" r="15" fill="yellow"/></svg>');
182
+ background-size: contain;
183
+ cursor: pointer;
184
+ z-index: 30;
185
+ animation: sun-fall 6s linear, sun-spin 2s linear infinite;
186
+ }
187
+
188
+ @keyframes sun-fall {
189
+ 0% { transform: translateY(-100px); opacity: 0; }
190
+ 10% { opacity: 1; }
191
+ 90% { opacity: 1; }
192
+ 100% { transform: translateY(calc(100vh - 170px)); opacity: 0; }
193
+ }
194
+
195
+ @keyframes sun-spin {
196
+ from { transform: rotate(0deg); }
197
+ to { transform: rotate(360deg); }
198
+ }
199
+
200
+ /* Game messages */
201
+ .game-message {
202
+ position: absolute;
203
+ top: 50%;
204
+ left: 50%;
205
+ transform: translate(-50%, -50%);
206
+ font-size: 2rem;
207
+ background-color: rgba(0, 0, 0, 0.7);
208
+ padding: 20px 40px;
209
+ border-radius: 10px;
210
+ z-index: 100;
211
+ display: none;
212
+ }
213
+
214
+ #start-screen {
215
+ display: flex;
216
+ flex-direction: column;
217
+ align-items: center;
218
+ justify-content: center;
219
+ gap: 20px;
220
+ }
221
+
222
+ #start-screen h1 {
223
+ font-size: 3rem;
224
+ color: #f1c40f;
225
+ text-shadow: 5px 5px #e67e22;
226
+ }
227
+
228
+ #start-button {
229
+ padding: 15px 30px;
230
+ background-color: #e74c3c;
231
+ border: none;
232
+ border-radius: 10px;
233
+ font-family: 'Press Start 2P', cursive;
234
+ font-size: 1.2rem;
235
+ color: white;
236
+ cursor: pointer;
237
+ transition: all 0.2s;
238
+ }
239
+
240
+ #start-button:hover {
241
+ transform: scale(1.1);
242
+ background-color: #c0392b;
243
+ }
244
+
245
+ #level-select {
246
+ display: flex;
247
+ gap: 20px;
248
+ }
249
+
250
+ .level-button {
251
+ padding: 10px 20px;
252
+ background-color: #3498db;
253
+ border: none;
254
+ border-radius: 5px;
255
+ font-family: 'Press Start 2P', cursive;
256
+ font-size: 0.8rem;
257
+ color: white;
258
+ cursor: pointer;
259
+ }
260
+
261
+ .level-button:hover {
262
+ background-color: #2980b9;
263
+ }
264
+
265
+ /* Progress bars */
266
+ .health-bar {
267
+ width: 100%;
268
+ height: 5px;
269
+ background-color: #2ecc71;
270
+ position: absolute;
271
+ bottom: -10px;
272
+ left: 0;
273
+ }
274
+
275
+ #wave-indicator {
276
+ position: absolute;
277
+ top: 10px;
278
+ right: 10px;
279
+ background-color: rgba(0, 0, 0, 0.5);
280
+ padding: 5px 10px;
281
+ border-radius: 5px;
282
+ z-index: 50;
283
+ }
284
+
285
+ /* Plant cooldown indicator */
286
+ .cooldown-overlay {
287
+ position: absolute;
288
+ bottom: 0;
289
+ left: 0;
290
+ width: 100%;
291
+ background-color: rgba(0, 0, 0, 0.5);
292
+ transition: height 0.5s linear;
293
+ }
294
+ </style>
295
+ </head>
296
+ <body>
297
+ <div id="game-container">
298
+ <div id="start-screen" class="game-message">
299
+ <h1>PLANTS vs ZOMBIES</h1>
300
+ <div id="level-select">
301
+ <button class="level-button" data-level="1">Backyard Day</button>
302
+ <button class="level-button" data-level="2">Backyard Night</button>
303
+ </div>
304
+ <button id="start-button">START GAME</button>
305
+ </div>
306
+
307
+ <div id="game-over-message" class="game-message">
308
+ <h2>GAME OVER</h2>
309
+ <p id="game-over-text"></p>
310
+ <button id="restart-button">TRY AGAIN</button>
311
+ </div>
312
+
313
+ <div id="wave-indicator">Wave: 1</div>
314
+
315
+ <div id="lawn"></div>
316
+
317
+ <div id="ui-container">
318
+ <div id="sun-counter">0</div>
319
+ <div id="plant-selection">
320
+ <div class="plant-option" data-plant="sunflower" data-cost="50">
321
+ <div class="plant-icon" style="background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 50 50\"><circle cx=\"25\" cy=\"25\" r=\"20\" fill=\"yellow\"/><circle cx=\"25\" cy=\"25\" r=\"10\" fill=\"orange\"/></svg>')"></div>
322
+ <div class="cost">50</div>
323
+ </div>
324
+ <div class="plant-option" data-plant="peashooter" data-cost="100">
325
+ <div class="plant-icon" style="background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 50 50\"><ellipse cx=\"25\" cy=\"30\" rx=\"15\" ry=\"20\" fill=\"green\"/><circle cx=\"25\" cy=\"15\" r=\"10\" fill=\"lime\"/></svg>')"></div>
326
+ <div class="cost">100</div>
327
+ </div>
328
+ <div class="plant-option" data-plant="wallnut" data-cost="50">
329
+ <div class="plant-icon" style="background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 50 50\"><circle cx=\"25\" cy=\"25\" r=\"20\" fill=\"saddlebrown\"/></svg>')"></div>
330
+ <div class="cost">50</div>
331
+ </div>
332
+ </div>
333
+ </div>
334
+ </div>
335
+
336
+ <script>
337
+ // Game state
338
+ const gameState = {
339
+ suns: 50,
340
+ selectedPlant: null,
341
+ plants: [],
342
+ zombies: [],
343
+ projectiles: [],
344
+ sunDrops: [],
345
+ currentWave: 0,
346
+ totalWaves: 5,
347
+ gameActive: false,
348
+ currentLevel: 1,
349
+ zombieSpeed: 0.5,
350
+ gameClock: 0,
351
+ lastSunProduced: 0,
352
+ lastZombieSpawned: 0,
353
+ plantCooldowns: {
354
+ sunflower: 0,
355
+ peashooter: 0,
356
+ wallnut: 0
357
+ },
358
+ zombiesReachedEnd: 0
359
+ };
360
+
361
+ // Plant properties
362
+ const plantProperties = {
363
+ sunflower: {
364
+ cost: 50,
365
+ health: 100,
366
+ cooldown: 10,
367
+ produceSunInterval: 10,
368
+ produceSunAmount: 25
369
+ },
370
+ peashooter: {
371
+ cost: 100,
372
+ health: 100,
373
+ cooldown: 7.5,
374
+ shootInterval: 3,
375
+ damage: 20
376
+ },
377
+ wallnut: {
378
+ cost: 50,
379
+ health: 400,
380
+ cooldown: 30,
381
+ damage: 0
382
+ }
383
+ };
384
+
385
+ // Zombie properties
386
+ const zombieProperties = {
387
+ basic: {
388
+ health: 100,
389
+ damage: 1,
390
+ speed: 0.5, // px per frame
391
+ value: 10
392
+ },
393
+ conehead: {
394
+ health: 200,
395
+ damage: 1,
396
+ speed: 0.4,
397
+ value: 20
398
+ },
399
+ buckethead: {
400
+ health: 300,
401
+ damage: 2,
402
+ speed: 0.3,
403
+ value: 30
404
+ }
405
+ };
406
+
407
+ // Level definitions
408
+ const levels = {
409
+ 1: {
410
+ name: "Backyard Day",
411
+ background: "#5da130",
412
+ zombieTypes: ["basic", "conehead"],
413
+ waves: [
414
+ { delay: 5, zombies: 5, zombieTypeWeights: [0.8, 0.2] },
415
+ { delay: 15, zombies: 8, zombieTypeWeights: [0.7, 0.3] },
416
+ { delay: 25, zombies: 12, zombieTypeWeights: [0.6, 0.4] },
417
+ { delay: 35, zombies: 15, zombieTypeWeights: [0.5, 0.5] },
418
+ { delay: 45, zombies: 20, zombieTypeWeights: [0.4, 0.6] }
419
+ ]
420
+ },
421
+ 2: {
422
+ name: "Backyard Night",
423
+ background: "#1a2330",
424
+ zombieTypes: ["basic", "conehead", "buckethead"],
425
+ waves: [
426
+ { delay: 5, zombies: 6, zombieTypeWeights: [0.6, 0.3, 0.1] },
427
+ { delay: 15, zombies: 10, zombieTypeWeights: [0.5, 0.3, 0.2] },
428
+ { delay: 25, zombies: 14, zombieTypeWeights: [0.4, 0.3, 0.3] },
429
+ { delay: 35, zombies: 18, zombieTypeWeights: [0.3, 0.3, 0.4] },
430
+ { delay: 45, zombies: 25, zombieTypeWeights: [0.2, 0.3, 0.5] }
431
+ ]
432
+ }
433
+ };
434
+
435
+ // DOM elements
436
+ const gameContainer = document.getElementById('game-container');
437
+ const lawn = document.getElementById('lawn');
438
+ const sunCounter = document.getElementById('sun-counter');
439
+ const plantSelection = document.getElementById('plant-selection');
440
+ const plantOptions = document.querySelectorAll('.plant-option');
441
+ const startScreen = document.getElementById('start-screen');
442
+ const gameOverMessage = document.getElementById('game-over-message');
443
+ const gameOverText = document.getElementById('game-over-text');
444
+ const startButton = document.getElementById('start-button');
445
+ const restartButton = document.getElementById('restart-button');
446
+ const levelButtons = document.querySelectorAll('.level-button');
447
+ const waveIndicator = document.getElementById('wave-indicator');
448
+
449
+ // Initialize the game
450
+ function initLawn() {
451
+ lawn.innerHTML = '';
452
+ for (let i = 0; i < 5; i++) {
453
+ for (let j = 0; j < 9; j++) {
454
+ const cell = document.createElement('div');
455
+ cell.className = 'lawn-cell';
456
+ cell.dataset.row = i;
457
+ cell.dataset.col = j;
458
+ cell.addEventListener('click', placePlant);
459
+ lawn.appendChild(cell);
460
+ }
461
+ }
462
+ }
463
+
464
+ // Initialize event listeners
465
+ function initEventListeners() {
466
+ plantOptions.forEach(option => {
467
+ option.addEventListener('click', () => {
468
+ const plantType = option.dataset.plant;
469
+ const plantCost = parseInt(option.dataset.cost);
470
+
471
+ if (gameState.plantCooldowns[plantType] > 0) return;
472
+
473
+ if (gameState.selectedPlant === plantType) {
474
+ gameState.selectedPlant = null;
475
+ plantOptions.forEach(opt => opt.classList.remove('selected'));
476
+ } else if (gameState.suns >= plantCost) {
477
+ gameState.selectedPlant = plantType;
478
+ plantOptions.forEach(opt => opt.classList.remove('selected'));
479
+ option.classList.add('selected');
480
+ }
481
+ });
482
+ });
483
+
484
+ document.addEventListener('click', (e) => {
485
+ if (e.target === gameContainer || e.target === lawn) {
486
+ gameState.selectedPlant = null;
487
+ plantOptions.forEach(opt => opt.classList.remove('selected'));
488
+ }
489
+ });
490
+
491
+ startButton.addEventListener('click', startGame);
492
+ restartButton.addEventListener('click', resetGame);
493
+
494
+ levelButtons.forEach(button => {
495
+ button.addEventListener('click', () => {
496
+ const level = parseInt(button.dataset.level);
497
+ selectLevel(level);
498
+ });
499
+ });
500
+ }
501
+
502
+ // Select level
503
+ function selectLevel(level) {
504
+ gameState.currentLevel = level;
505
+ levelButtons.forEach(button => {
506
+ button.style.backgroundColor = button.dataset.level == level ? '#2980b9' : '#3498db';
507
+ });
508
+ }
509
+
510
+ // Start game
511
+ function startGame() {
512
+ if (gameState.gameActive) return;
513
+
514
+ gameState.gameActive = true;
515
+ gameState.suns = 50;
516
+ gameState.plants = [];
517
+ gameState.zombies = [];
518
+ gameState.projectiles = [];
519
+ gameState.sunDrops = [];
520
+ gameState.currentWave = 0;
521
+ gameState.gameClock = 0;
522
+ gameState.lastSunProduced = 0;
523
+ gameState.lastZombieSpawned = 0;
524
+ gameState.zombiesReachedEnd = 0;
525
+
526
+ // Reset plant cooldowns
527
+ for (const plantType in gameState.plantCooldowns) {
528
+ gameState.plantCooldowns[plantType] = 0;
529
+ }
530
+
531
+ // Set background based on level
532
+ gameContainer.style.backgroundImage = `linear-gradient(${levels[gameState.currentLevel].background}, #3b7a1f)`;
533
+
534
+ // Hide start screen
535
+ startScreen.style.display = 'none';
536
+ gameOverMessage.style.display = 'none';
537
+
538
+ // Start game loop
539
+ gameLoop();
540
+
541
+ // Start random sun drops
542
+ setInterval(createRandomSun, 10000);
543
+ }
544
+
545
+ // Reset game
546
+ function resetGame() {
547
+ gameState.gameActive = false;
548
+
549
+ // Clear game elements
550
+ document.querySelectorAll('.plant, .zombie, .pea, .sun').forEach(el => el.remove());
551
+
552
+ // Show start screen
553
+ startScreen.style.display = 'flex';
554
+ gameOverMessage.style.display = 'none';
555
+ }
556
+
557
+ // Place plant
558
+ function placePlant(e) {
559
+ if (!gameState.selectedPlant || !gameState.gameActive) return;
560
+
561
+ const row = parseInt(e.currentTarget.dataset.row);
562
+ const col = parseInt(e.currentTarget.dataset.col);
563
+
564
+ // Check if cell is already occupied
565
+ const cellOccupied = gameState.plants.some(plant => plant.row === row && plant.col === col);
566
+ if (cellOccupied) return;
567
+
568
+ const plantType = gameState.selectedPlant;
569
+ const plantCost = plantProperties[plantType].cost;
570
+
571
+ if (gameState.suns >= plantCost) {
572
+ // Deduct sun cost
573
+ gameState.suns -= plantCost;
574
+ updateSunCounter();
575
+
576
+ // Create plant
577
+ const plant = {
578
+ type: plantType,
579
+ row: row,
580
+ col: col,
581
+ health: plantProperties[plantType].health,
582
+ lastActionTime: 0,
583
+ element: createPlantElement(plantType, row, col)
584
+ };
585
+
586
+ gameState.plants.push(plant);
587
+
588
+ // Start cooldown
589
+ gameState.plantCooldowns[plantType] = plantProperties[plantType].cooldown;
590
+ updateCooldownDisplay(plantType);
591
+
592
+ // Deselect plant
593
+ gameState.selectedPlant = null;
594
+ plantOptions.forEach(opt => opt.classList.remove('selected'));
595
+ }
596
+ }
597
+
598
+ // Create plant element
599
+ function createPlantElement(plantType, row, col) {
600
+ const plant = document.createElement('div');
601
+ plant.className = `plant ${plantType}`;
602
+
603
+ // Create health bar
604
+ const healthBar = document.createElement('div');
605
+ healthBar.className = 'health-bar';
606
+ healthBar.style.width = '100%';
607
+ plant.appendChild(healthBar);
608
+
609
+ // Find the cell and append the plant
610
+ const cell = document.querySelector(`.lawn-cell[data-row="${row}"][data-col="${col}"]`);
611
+ cell.appendChild(plant);
612
+
613
+ return plant;
614
+ }
615
+
616
+ // Create zombie
617
+ function createZombie(type, row) {
618
+ const zombie = document.createElement('div');
619
+ zombie.className = `zombie ${type}-zombie`;
620
+
621
+ // Create health bar
622
+ const healthBar = document.createElement('div');
623
+ healthBar.className = 'health-bar';
624
+ healthBar.style.width = '100%';
625
+ zombie.appendChild(healthBar);
626
+
627
+ // Position zombie
628
+ const cellHeight = lawn.clientHeight / 5;
629
+ zombie.style.top = `${row * cellHeight + cellHeight / 2 - 50}px`;
630
+
631
+ gameContainer.appendChild(zombie);
632
+
633
+ // Add to game state
634
+ const zombieObj = {
635
+ type: type,
636
+ row: row,
637
+ x: gameContainer.clientWidth,
638
+ element: zombie,
639
+ health: zombieProperties[type].health,
640
+ maxHealth: zombieProperties[type].health,
641
+ speed: zombieProperties[type].speed * (gameState.currentLevel === 2 ? 0.8 : 1), // Slower at night
642
+ damage: zombieProperties[type].damage,
643
+ moving: true
644
+ };
645
+
646
+ gameState.zombies.push(zombieObj);
647
+
648
+ return zombieObj;
649
+ }
650
+
651
+ // Create projectile
652
+ function createProjectile(x, y) {
653
+ const pea = document.createElement('div');
654
+ pea.className = 'pea';
655
+ pea.style.left = `${x}px`;
656
+ pea.style.top = `${y}px`;
657
+ gameContainer.appendChild(pea);
658
+
659
+ const projectile = {
660
+ x: x,
661
+ y: y,
662
+ speed: 5,
663
+ damage: 20,
664
+ element: pea
665
+ };
666
+
667
+ gameState.projectiles.push(projectile);
668
+ return projectile;
669
+ }
670
+
671
+ // Create sun drop
672
+ function createSunDrop(x, y, autoCollect = false) {
673
+ const sun = document.createElement('div');
674
+ sun.className = 'sun';
675
+ sun.style.left = `${x}px`;
676
+ sun.style.top = `${y}px`;
677
+
678
+ if (autoCollect) {
679
+ // Animation for suns produced by sunflowers
680
+ sun.style.animation = 'sun-bounce 4s ease-in-out, sun-spin 2s linear infinite';
681
+ } else {
682
+ // Regular falling sun animation
683
+ sun.style.animation = 'sun-fall 6s linear, sun-spin 2s linear infinite';
684
+ }
685
+
686
+ sun.addEventListener('click', collectSun);
687
+ gameContainer.appendChild(sun);
688
+
689
+ const sunDrop = {
690
+ x: x,
691
+ y: y,
692
+ element: sun,
693
+ autoCollect: autoCollect,
694
+ collected: false,
695
+ value: 25
696
+ };
697
+
698
+ gameState.sunDrops.push(sunDrop);
699
+
700
+ if (autoCollect) {
701
+ // Auto-collect after animation
702
+ setTimeout(() => {
703
+ if (!sunDrop.collected) {
704
+ collectSun({ target: sun });
705
+ }
706
+ }, 4000);
707
+ } else {
708
+ // Remove if not collected
709
+ setTimeout(() => {
710
+ if (!sunDrop.collected) {
711
+ sun.remove();
712
+ gameState.sunDrops = gameState.sunDrops.filter(s => s !== sunDrop);
713
+ }
714
+ }, 6000);
715
+ }
716
+
717
+ return sunDrop;
718
+ }
719
+
720
+ // Create random sun
721
+ function createRandomSun() {
722
+ if (!gameState.gameActive) return;
723
+
724
+ const x = Math.random() * (gameContainer.clientWidth - 100) + 50;
725
+ createSunDrop(x, -50);
726
+ }
727
+
728
+ // Collect sun
729
+ function collectSun(e) {
730
+ e.stopPropagation();
731
+
732
+ const sunElement = e.target;
733
+ const sunDrop = gameState.sunDrops.find(sun => sun.element === sunElement);
734
+
735
+ if (sunDrop && !sunDrop.collected) {
736
+ sunDrop.collected = true;
737
+ gameState.suns += sunDrop.value;
738
+ updateSunCounter();
739
+
740
+ // Animate collection
741
+ sunElement.style.transition = 'all 0.3s ease-out';
742
+ sunElement.style.transform = 'translateY(-20px) scale(1.5)';
743
+ sunElement.style.opacity = '0';
744
+
745
+ // Remove after animation
746
+ setTimeout(() => {
747
+ sunElement.remove();
748
+ gameState.sunDrops = gameState.sunDrops.filter(s => s !== sunDrop);
749
+ }, 300);
750
+ }
751
+ }
752
+
753
+ // Update sun counter display
754
+ function updateSunCounter() {
755
+ sunCounter.textContent = gameState.suns;
756
+
757
+ // Update plant option availability
758
+ plantOptions.forEach(option => {
759
+ const plantType = option.dataset.plant;
760
+ const plantCost = parseInt(option.dataset.cost);
761
+
762
+ if (gameState.suns < plantCost || gameState.plantCooldowns[plantType] > 0) {
763
+ option.style.opacity = '0.5';
764
+ } else {
765
+ option.style.opacity = '1';
766
+ }
767
+ });
768
+ }
769
+
770
+ // Update cooldown display
771
+ function updateCooldownDisplay(plantType) {
772
+ const option = document.querySelector(`.plant-option[data-plant="${plantType}"]`);
773
+ if (!option) return;
774
+
775
+ // Remove existing cooldown overlay
776
+ const existingOverlay = option.querySelector('.cooldown-overlay');
777
+ if (existingOverlay) existingOverlay.remove();
778
+
779
+ // Create new cooldown overlay
780
+ const overlay = document.createElement('div');
781
+ overlay.className = 'cooldown-overlay';
782
+ overlay.style.height = '100%';
783
+ option.appendChild(overlay);
784
+
785
+ // Animate cooldown
786
+ const cooldown = plantProperties[plantType].cooldown;
787
+ const startTime = Date.now();
788
+
789
+ const animateCooldown = () => {
790
+ const elapsed = (Date.now() - startTime) / 1000;
791
+ const remaining = Math.max(0, cooldown - elapsed);
792
+
793
+ overlay.style.height = `${(remaining / cooldown) * 100}%`;
794
+
795
+ if (remaining > 0) {
796
+ gameState.plantCooldowns[plantType] = remaining;
797
+ requestAnimationFrame(animateCooldown);
798
+ } else {
799
+ gameState.plantCooldowns[plantType] = 0;
800
+ overlay.remove();
801
+
802
+ // Update sun counter to refresh availability
803
+ updateSunCounter();
804
+ }
805
+ };
806
+
807
+ requestAnimationFrame(animateCooldown);
808
+ }
809
+
810
+ // Game loop
811
+ function gameLoop() {
812
+ if (!gameState.gameActive) return;
813
+
814
+ // Update game clock
815
+ gameState.gameClock += 0.016; // Assuming 60 FPS
816
+
817
+ // Check for wave completion and spawn new waves
818
+ checkWaveCompletion();
819
+
820
+ // Update zombies
821
+ updateZombies();
822
+
823
+ // Update plants
824
+ updatePlants();
825
+
826
+ // Update projectiles
827
+ updateProjectiles();
828
+
829
+ // Check game over conditions
830
+ checkGameOver();
831
+
832
+ // Continue game loop
833
+ requestAnimationFrame(gameLoop);
834
+ }
835
+
836
+ // Check wave completion
837
+ function checkWaveCompletion() {
838
+ const level = levels[gameState.currentLevel];
839
+
840
+ // Check if we need to start a new wave
841
+ if (gameState.currentWave < level.waves.length) {
842
+ const currentWaveData = level.waves[gameState.currentWave];
843
+
844
+ if (gameState.gameClock >= currentWaveData.delay &&
845
+ gameState.lastZombieSpawned + 1 < gameState.gameClock &&
846
+ gameState.zombies.length < 5 + gameState.currentWave) {
847
+
848
+ // Spawn zombie
849
+ const zombieType = getRandomZombieType(currentWaveData.zombieTypeWeights);
850
+ const row = Math.floor(Math.random() * 5);
851
+ createZombie(zombieType, row);
852
+
853
+ // Update last spawned time
854
+ gameState.lastZombieSpawned = gameState.gameClock;
855
+
856
+ // Update wave indicator if this is the first zombie of a new wave
857
+ if (gameState.zombies.length === 1) {
858
+ waveIndicator.textContent = `Wave: ${gameState.currentWave + 1}/${level.waves.length}`;
859
+ }
860
+ }
861
+
862
+ // Check if we've spawned enough zombies for this wave
863
+ const zombiesSpawnedThisWave = gameState.zombies.filter(z =>
864
+ z.spawnTime >= currentWaveData.delay - 1
865
+ ).length;
866
+
867
+ if (zombiesSpawnedThisWave >= currentWaveData.zombies &&
868
+ gameState.zombies.length === 0 &&
869
+ gameState.currentWave < level.waves.length - 1) {
870
+
871
+ // Move to next wave
872
+ gameState.currentWave++;
873
+ }
874
+ }
875
+ }
876
+
877
+ // Get random zombie type based on weights
878
+ function getRandomZombieType(weights) {
879
+ const randomValue = Math.random();
880
+ let cumulativeWeight = 0;
881
+
882
+ for (let i = 0; i < weights.length; i++) {
883
+ cumulativeWeight += weights[i];
884
+ if (randomValue < cumulativeWeight) {
885
+ return levels[gameState.currentLevel].zombieTypes[i];
886
+ }
887
+ }
888
+
889
+ return levels[gameState.currentLevel].zombieTypes[0]; // Fallback
890
+ }
891
+
892
+ // Update zombies
893
+ function updateZombies() {
894
+ const cellWidth = lawn.clientWidth / 9;
895
+ const cellHeight = lawn.clientHeight / 5;
896
+
897
+ for (let i = gameState.zombies.length - 1; i >= 0; i--) {
898
+ const zombie = gameState.zombies[i];
899
+
900
+ if (zombie.moving) {
901
+ // Move zombie
902
+ zombie.x -= zombie.speed;
903
+ zombie.element.style.left = `${zombie.x}px`;
904
+
905
+ // Check if zombie reached left side
906
+ if (zombie.x < -zombie.element.clientWidth) {
907
+ gameState.zombiesReachedEnd++;
908
+ zombie.element.remove();
909
+ gameState.zombies.splice(i, 1);
910
+ continue;
911
+ }
912
+
913
+ // Check for collision with plants
914
+ const zombieRect = {
915
+ left: zombie.x,
916
+ right: zombie.x + zombie.element.clientWidth,
917
+ top: parseInt(zombie.element.style.top),
918
+ bottom: parseInt(zombie.element.style.top) + zombie.element.clientHeight
919
+ };
920
+
921
+ // Find plants in the same row
922
+ const plantsInRow = gameState.plants.filter(p => p.row === zombie.row);
923
+
924
+ for (const plant of plantsInRow) {
925
+ const cell = document.querySelector(`.lawn-cell[data-row="${plant.row}"][data-col="${plant.col}"]`);
926
+ const rect = cell.getBoundingClientRect();
927
+
928
+ const plantRect = {
929
+ left: rect.left - gameContainer.getBoundingClientRect().left,
930
+ right: rect.right - gameContainer.getBoundingClientRect().left,
931
+ top: rect.top - gameContainer.getBoundingClientRect().top,
932
+ bottom: rect.bottom - gameContainer.getBoundingClientRect().top
933
+ };
934
+
935
+ // Simple collision detection
936
+ if (zombieRect.right > plantRect.left && zombieRect.left < plantRect.right &&
937
+ zombieRect.bottom > plantRect.top && zombieRect.top < plantRect.bottom) {
938
+
939
+ zombie.moving = false;
940
+
941
+ // Damage plant
942
+ plant.health -= zombie.damage / 60; // Assuming 60 FPS
943
+ updatePlantHealth(plant);
944
+
945
+ // Zombie eats animation
946
+ if (Math.random() < 0.02) {
947
+ zombie.element.style.transform = 'scaleX(1.1)';
948
+ setTimeout(() => {
949
+ if (zombie.element) {
950
+ zombie.element.style.transform = 'scaleX(1)';
951
+ }
952
+ }, 100);
953
+ }
954
+
955
+ // Check if plant is dead
956
+ if (plant.health <= 0) {
957
+ plant.element.remove();
958
+ gameState.plants = gameState.plants.filter(p => p !== plant);
959
+ zombie.moving = true;
960
+ }
961
+
962
+ break;
963
+ }
964
+ }
965
+ }
966
+
967
+ // Update zombie appearance based on health
968
+ updateZombieHealth(zombie);
969
+ }
970
+ }
971
+
972
+ // Update plants
973
+ function updatePlants() {
974
+ for (const plant of gameState.plants) {
975
+ // Sunflower behavior
976
+ if (plant.type === 'sunflower') {
977
+ if (gameState.gameClock - plant.lastActionTime >= plantProperties.sunflower.produceSunInterval) {
978
+ plant.lastActionTime = gameState.gameClock;
979
+
980
+ // Produce sun
981
+ const cell = document.querySelector(`.lawn-cell[data-row="${plant.row}"][data-col="${plant.col}"]`);
982
+ const rect = cell.getBoundingClientRect();
983
+
984
+ const x = rect.left - gameContainer.getBoundingClientRect().left + rect.width / 2;
985
+ const y = rect.top - gameContainer.getBoundingClientRect().top + rect.height / 2;
986
+
987
+ createSunDrop(x, y, true);
988
+ }
989
+ }
990
+
991
+ // Peashooter behavior
992
+ if (plant.type === 'peashooter' && gameState.zombies.some(z => z.row === plant.row)) {
993
+ if (gameState.gameClock - plant.lastActionTime >= plantProperties.peashooter.shootInterval) {
994
+ plant.lastActionTime = gameState.gameClock;
995
+
996
+ // Shoot pea
997
+ const cell = document.querySelector(`.lawn-cell[data-row="${plant.row}"][data-col="${plant.col}"]`);
998
+ const rect = cell.getBoundingClientRect();
999
+
1000
+ const x = rect.right - gameContainer.getBoundingClientRect().left;
1001
+ const y = rect.top - gameContainer.getBoundingClientRect().top + rect.height / 2;
1002
+
1003
+ createProjectile(x, y);
1004
+ }
1005
+ }
1006
+
1007
+ // Update plant appearance based on health
1008
+ updatePlantHealth(plant);
1009
+ }
1010
+ }
1011
+
1012
+ // Update projectiles
1013
+ function updateProjectiles() {
1014
+ for (let i = gameState.projectiles.length - 1; i >= 0; i--) {
1015
+ const projectile = gameState.projectiles[i];
1016
+
1017
+ // Move projectile
1018
+ projectile.x += projectile.speed;
1019
+ projectile.element.style.left = `${projectile.x}px`;
1020
+
1021
+ // Remove if off screen
1022
+ if (projectile.x > gameContainer.clientWidth) {
1023
+ projectile.element.remove();
1024
+ gameState.projectiles.splice(i, 1);
1025
+ continue;
1026
+ }
1027
+
1028
+ // Check for collision with zombies
1029
+ const peaRect = {
1030
+ left: projectile.x,
1031
+ right: projectile.x + projectile.element.clientWidth,
1032
+ top: parseInt(projectile.element.style.top),
1033
+ bottom: parseInt(projectile.element.style.top) + projectile.element.clientHeight
1034
+ };
1035
+
1036
+ for (const zombie of gameState.zombies) {
1037
+ const zombieRect = {
1038
+ left: zombie.x,
1039
+ right: zombie.x + zombie.element.clientWidth,
1040
+ top: parseInt(zombie.element.style.top),
1041
+ bottom: parseInt(zombie.element.style.top) + zombie.element.clientHeight
1042
+ };
1043
+
1044
+ // Simple collision detection
1045
+ if (peaRect.right > zombieRect.left && peaRect.left < zombieRect.right &&
1046
+ peaRect.bottom > zombieRect.top && peaRect.top < zombieRect.bottom) {
1047
+
1048
+ // Damage zombie
1049
+ zombie.health -= projectile.damage;
1050
+
1051
+ // Update zombie appearance
1052
+ updateZombieHealth(zombie);
1053
+
1054
+ // Remove projectile
1055
+ projectile.element.remove();
1056
+ gameState.projectiles.splice(i, 1);
1057
+
1058
+ // Check if zombie is dead
1059
+ if (zombie.health <= 0) {
1060
+ // Add suns
1061
+ gameState.suns += zombieProperties[zombie.type].value;
1062
+ updateSunCounter();
1063
+
1064
+ // Remove zombie
1065
+ zombie.element.remove();
1066
+ gameState.zombies = gameState.zombies.filter(z => z !== zombie);
1067
+ }
1068
+
1069
+ break;
1070
+ }
1071
+ }
1072
+ }
1073
+ }
1074
+
1075
+ // Update plant health display
1076
+ function updatePlantHealth(plant) {
1077
+ const healthPercent = Math.max(0, plant.health / plantProperties[plant.type].health * 100);
1078
+ const healthBar = plant.element.querySelector('.health-bar');
1079
+
1080
+ if (healthBar) {
1081
+ healthBar.style.width = `${healthPercent}%`;
1082
+ healthBar.style.backgroundColor = healthPercent > 50 ? '#2ecc71' :
1083
+ healthPercent > 25 ? '#f39c12' :
1084
+ '#e74c3c';
1085
+ }
1086
+ }
1087
+
1088
+ // Update zombie health display
1089
+ function updateZombieHealth(zombie) {
1090
+ const healthPercent = Math.max(0, zombie.health / zombie.maxHealth * 100);
1091
+ const healthBar = zombie.element.querySelector('.health-bar');
1092
+
1093
+ if (healthBar) {
1094
+ healthBar.style.width = `${healthPercent}%`;
1095
+
1096
+ // Visual damage effects
1097
+ if (healthPercent < 50) {
1098
+ zombie.element.style.filter = 'brightness(0.8)';
1099
+ }
1100
+ if (healthPercent < 25) {
1101
+ zombie.element.style.filter = 'brightness(0.6) hue-rotate(30deg)';
1102
+ }
1103
+ }
1104
+ }
1105
+
1106
+ // Check game over conditions
1107
+ function checkGameOver() {
1108
+ // Check for too many zombies reaching the end
1109
+ if (gameState.zombiesReachedEnd >= 5) {
1110
+ endGame(false);
1111
+ return;
1112
+ }
1113
+
1114
+ // Check for level completion
1115
+ const level = levels[gameState.currentLevel];
1116
+ if (gameState.currentWave >= level.waves.length - 1 &&
1117
+ gameState.zombies.length === 0 &&
1118
+ gameState.gameClock - gameState.lastZombieSpawned > 5) {
1119
+
1120
+ endGame(true);
1121
+ return;
1122
+ }
1123
+ }
1124
+
1125
+ // End game
1126
+ function endGame(victory) {
1127
+ gameState.gameActive = false;
1128
+
1129
+ gameOverText.textContent = victory ?
1130
+ `You survived the zombie attack! Final score: ${gameState.suns}` :
1131
+ `The zombies ate your brains! You survived ${gameState.currentWave + 1} waves.`;
1132
+
1133
+ gameOverMessage.style.display = 'flex';
1134
+ }
1135
+
1136
+ // Initialize the game
1137
+ function initGame() {
1138
+ initLawn();
1139
+ initEventListeners();
1140
+
1141
+ // Select first level by default
1142
+ selectLevel(1);
1143
+
1144
+ // Show start screen
1145
+ startScreen.style.display = 'flex';
1146
+ }
1147
+
1148
+ // Start the game
1149
+ window.onload = initGame;
1150
+ </script>
1151
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: absolute; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">This website has been generated by <a href="https://enzostvs-deepsite.hf.space" style="color: #fff;" target="_blank" >DeepSite</a> <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;"></p></body>
1152
+ </html>