Greats commited on
Commit
848ea3b
·
verified ·
1 Parent(s): 7c920f9

Add 2 files

Browse files
Files changed (2) hide show
  1. index.html +952 -128
  2. prompts.txt +2 -1
index.html CHANGED
@@ -3,25 +3,45 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>GTA Style Game</title>
 
7
  <style>
8
  body {
9
  margin: 0;
10
  overflow: hidden;
11
- background-color: #222;
12
- font-family: Arial, sans-serif;
 
 
13
  }
14
  #gameCanvas {
15
  display: block;
16
- background-color: #87CEEB;
 
17
  }
18
  #ui {
19
  position: absolute;
20
- top: 10px;
21
- left: 10px;
22
- color: white;
23
- font-size: 16px;
24
- text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  }
26
  #startScreen {
27
  position: absolute;
@@ -29,36 +49,206 @@
29
  left: 0;
30
  width: 100%;
31
  height: 100%;
32
- background-color: rgba(0, 0, 0, 0.8);
33
  display: flex;
34
  flex-direction: column;
35
  justify-content: center;
36
  align-items: center;
37
- color: white;
 
 
38
  }
39
  #startButton {
40
  padding: 15px 30px;
41
  font-size: 20px;
42
- background-color: #FF4500;
43
  color: white;
44
- border: none;
45
  border-radius: 5px;
46
  cursor: pointer;
47
- margin-top: 20px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  }
49
  </style>
50
  </head>
51
  <body>
52
  <canvas id="gameCanvas"></canvas>
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  <div id="ui">
54
- <div>Money: $<span id="money">0</span></div>
55
- <div>Health: <span id="health">100</span>%</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  </div>
 
57
  <div id="startScreen">
58
- <h1>GTA Style Game</h1>
59
- <p>Use arrow keys to drive, space to brake</p>
 
 
 
 
 
60
  <button id="startButton">START GAME</button>
61
  </div>
 
 
 
 
 
 
 
62
 
63
  <script>
64
  // Game setup
@@ -66,8 +256,19 @@
66
  const ctx = canvas.getContext('2d');
67
  const startScreen = document.getElementById('startScreen');
68
  const startButton = document.getElementById('startButton');
69
- const moneyDisplay = document.getElementById('money');
70
- const healthDisplay = document.getElementById('health');
 
 
 
 
 
 
 
 
 
 
 
71
 
72
  // Set canvas size
73
  canvas.width = window.innerWidth;
@@ -75,105 +276,654 @@
75
 
76
  // Game state
77
  let gameRunning = false;
78
- let money = 0;
79
- let health = 100;
 
80
 
81
- // Player car
82
  const player = {
83
- x: canvas.width / 2,
84
- y: canvas.height / 2,
85
- width: 40,
86
- height: 70,
87
- speed: 0,
88
- maxSpeed: 5,
89
- rotation: 0,
90
- color: '#FF4500'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  };
92
 
93
- // Roads
94
- const roads = [];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
 
96
- // Generate simple city
97
- function generateCity() {
98
- roads.length = 0;
 
 
 
 
99
 
100
- // Horizontal roads
101
- for (let y = 100; y < canvas.height; y += 200) {
102
- roads.push({
103
- x: 0,
104
- y: y,
105
- width: canvas.width,
106
- height: 60
107
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  }
109
 
110
- // Vertical roads
111
- for (let x = 100; x < canvas.width; x += 200) {
112
- roads.push({
113
- x: x,
114
- y: 0,
115
- width: 60,
116
- height: canvas.height
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  });
118
  }
119
 
120
- // Position player at intersection
121
- player.x = 200;
122
- player.y = 200;
123
  }
124
 
125
- // Draw rotated rectangle
126
- function drawRotatedRect(x, y, width, height, rotation, color) {
127
- ctx.save();
128
- ctx.translate(x, y);
129
- ctx.rotate(rotation);
130
- ctx.fillStyle = color;
131
- ctx.fillRect(-width/2, -height/2, width, height);
132
 
133
- // Add windows
134
- ctx.fillStyle = '#333';
135
- ctx.fillRect(-width/2 + 5, -height/2 + 5, width - 10, height/3);
136
- ctx.restore();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  }
138
 
139
- // Game loop
140
- function gameLoop() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  if (!gameRunning) return;
142
 
143
- // Clear canvas
144
- ctx.clearRect(0, 0, canvas.width, canvas.height);
 
 
 
 
 
 
 
 
 
 
 
 
145
 
146
- // Draw roads
147
- ctx.fillStyle = '#333';
148
- roads.forEach(road => {
149
- ctx.fillRect(road.x, road.y, road.width, road.height);
150
 
151
- // Road markings
152
- ctx.fillStyle = 'white';
153
- if (road.width > road.height) { // horizontal road
154
- for (let x = 0; x < road.width; x += 40) {
155
- ctx.fillRect(road.x + x, road.y + road.height/2 - 2, 20, 4);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  }
157
- } else { // vertical road
158
- for (let y = 0; y < road.height; y += 40) {
159
- ctx.fillRect(road.x + road.width/2 - 2, road.y + y, 4, 20);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  }
161
  }
162
- ctx.fillStyle = '#333';
163
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
 
165
- // Update player position
166
- player.x += Math.cos(player.rotation) * player.speed;
167
- player.y += Math.sin(player.rotation) * player.speed;
 
168
 
169
- // Wrap around screen
170
- if (player.x < 0) player.x = canvas.width;
171
- if (player.x > canvas.width) player.x = 0;
172
- if (player.y < 0) player.y = canvas.height;
173
- if (player.y > canvas.height) player.y = 0;
174
 
175
- // Draw player
176
- drawRotatedRect(player.x, player.y, player.width, player.height, player.rotation, player.color);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
 
178
  // Request next frame
179
  requestAnimationFrame(gameLoop);
@@ -181,49 +931,98 @@
181
 
182
  // Keyboard controls
183
  const keys = {
184
- ArrowUp: false,
185
- ArrowDown: false,
 
 
 
186
  ArrowLeft: false,
187
  ArrowRight: false,
188
- ' ': false
189
  };
190
 
191
  document.addEventListener('keydown', (e) => {
192
  if (e.key in keys) keys[e.key] = true;
 
 
 
 
 
 
 
 
 
 
193
  });
194
 
195
  document.addEventListener('keyup', (e) => {
196
  if (e.key in keys) keys[e.key] = false;
197
  });
198
 
199
- // Update player based on input
200
- function updatePlayer() {
 
 
 
 
 
 
 
 
 
 
 
 
201
  if (!gameRunning) return;
202
 
203
- // Acceleration
204
- if (keys.ArrowUp) {
205
- player.speed = Math.min(player.speed + 0.05, player.maxSpeed);
206
- } else if (keys.ArrowDown) {
207
- player.speed = Math.max(player.speed - 0.05, -player.maxSpeed/2);
208
- } else {
209
- // Friction
210
- player.speed *= 0.95;
211
- if (Math.abs(player.speed) < 0.1) player.speed = 0;
212
- }
213
 
214
- // Brake
215
- if (keys[' ']) {
216
- player.speed *= 0.9;
 
 
 
 
 
 
 
217
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
 
219
- // Steering
220
- if (keys.ArrowLeft && player.speed !== 0) {
221
- player.rotation -= 0.05 * (player.speed / player.maxSpeed);
222
- }
223
- if (keys.ArrowRight && player.speed !== 0) {
224
- player.rotation += 0.05 * (player.speed / player.maxSpeed);
 
 
 
 
 
 
 
 
225
  }
226
- }
 
 
 
 
227
 
228
  // Start game
229
  function startGame() {
@@ -231,30 +1030,55 @@
231
  gameRunning = true;
232
 
233
  // Reset game state
234
- money = 0;
235
- health = 100;
236
- moneyDisplay.textContent = money;
237
- healthDisplay.textContent = health;
 
238
 
239
- // Generate city
240
- generateCity();
241
 
242
  // Start game loop
243
  gameLoop();
244
-
245
- // Start input update loop
246
- setInterval(updatePlayer, 1000/60);
 
 
 
247
  }
248
 
249
  // Start button event
250
  startButton.addEventListener('click', startGame);
 
251
 
252
  // Handle window resize
253
  window.addEventListener('resize', () => {
254
  canvas.width = window.innerWidth;
255
  canvas.height = window.innerHeight;
256
- if (gameRunning) generateCity();
257
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  </script>
259
  <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Greats/clone" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
260
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>DOOM Style Game</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
  <style>
9
  body {
10
  margin: 0;
11
  overflow: hidden;
12
+ background-color: #000;
13
+ font-family: 'Courier New', monospace;
14
+ color: white;
15
+ touch-action: none;
16
  }
17
  #gameCanvas {
18
  display: block;
19
+ width: 100%;
20
+ height: 100%;
21
  }
22
  #ui {
23
  position: absolute;
24
+ bottom: 0;
25
+ left: 0;
26
+ width: 100%;
27
+ padding: 20px;
28
+ box-sizing: border-box;
29
+ background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));
30
+ display: flex;
31
+ flex-direction: column;
32
+ align-items: center;
33
+ }
34
+ #healthAmmo {
35
+ display: flex;
36
+ justify-content: space-between;
37
+ width: 100%;
38
+ max-width: 600px;
39
+ margin-bottom: 10px;
40
+ }
41
+ #weapon {
42
+ font-size: 24px;
43
+ margin-bottom: 10px;
44
+ text-shadow: 0 0 5px red;
45
  }
46
  #startScreen {
47
  position: absolute;
 
49
  left: 0;
50
  width: 100%;
51
  height: 100%;
52
+ background-color: rgba(0, 0, 0, 0.9);
53
  display: flex;
54
  flex-direction: column;
55
  justify-content: center;
56
  align-items: center;
57
+ color: red;
58
+ text-align: center;
59
+ z-index: 10;
60
  }
61
  #startButton {
62
  padding: 15px 30px;
63
  font-size: 20px;
64
+ background-color: #8B0000;
65
  color: white;
66
+ border: 2px solid #FF0000;
67
  border-radius: 5px;
68
  cursor: pointer;
69
+ margin-top: 30px;
70
+ font-family: 'Courier New', monospace;
71
+ text-transform: uppercase;
72
+ letter-spacing: 2px;
73
+ }
74
+ #startButton:hover {
75
+ background-color: #FF0000;
76
+ }
77
+ #crosshair {
78
+ position: absolute;
79
+ top: 50%;
80
+ left: 50%;
81
+ width: 20px;
82
+ height: 20px;
83
+ transform: translate(-50%, -50%);
84
+ pointer-events: none;
85
+ }
86
+ #crosshair::before, #crosshair::after {
87
+ content: '';
88
+ position: absolute;
89
+ background-color: red;
90
+ }
91
+ #crosshair::before {
92
+ width: 20px;
93
+ height: 2px;
94
+ top: 9px;
95
+ left: 0;
96
+ }
97
+ #crosshair::after {
98
+ width: 2px;
99
+ height: 20px;
100
+ left: 9px;
101
+ top: 0;
102
+ }
103
+ #gameOverScreen {
104
+ position: absolute;
105
+ top: 0;
106
+ left: 0;
107
+ width: 100%;
108
+ height: 100%;
109
+ background-color: rgba(0, 0, 0, 0.9);
110
+ display: none;
111
+ flex-direction: column;
112
+ justify-content: center;
113
+ align-items: center;
114
+ color: red;
115
+ text-align: center;
116
+ z-index: 10;
117
+ }
118
+ #restartButton {
119
+ padding: 15px 30px;
120
+ font-size: 20px;
121
+ background-color: #8B0000;
122
+ color: white;
123
+ border: 2px solid #FF0000;
124
+ border-radius: 5px;
125
+ cursor: pointer;
126
+ margin-top: 30px;
127
+ font-family: 'Courier New', monospace;
128
+ text-transform: uppercase;
129
+ letter-spacing: 2px;
130
+ }
131
+ #restartButton:hover {
132
+ background-color: #FF0000;
133
+ }
134
+ #hud {
135
+ position: absolute;
136
+ top: 10px;
137
+ left: 10px;
138
+ font-size: 16px;
139
+ color: white;
140
+ text-shadow: 0 0 5px black;
141
+ }
142
+ #enemiesLeft {
143
+ position: absolute;
144
+ top: 10px;
145
+ right: 10px;
146
+ font-size: 16px;
147
+ color: white;
148
+ text-shadow: 0 0 5px black;
149
+ }
150
+ .health-bar, .ammo-bar {
151
+ width: 200px;
152
+ height: 20px;
153
+ border: 2px solid #333;
154
+ border-radius: 3px;
155
+ overflow: hidden;
156
+ position: relative;
157
+ }
158
+ .health-fill {
159
+ height: 100%;
160
+ background: linear-gradient(to right, #8B0000, #FF0000);
161
+ transition: width 0.3s;
162
+ }
163
+ .ammo-fill {
164
+ height: 100%;
165
+ background: linear-gradient(to right, #006400, #00FF00);
166
+ transition: width 0.3s;
167
+ }
168
+ #weaponImage {
169
+ width: 200px;
170
+ height: 100px;
171
+ background-size: contain;
172
+ background-repeat: no-repeat;
173
+ background-position: center;
174
+ margin-bottom: 10px;
175
+ }
176
+ #bloodEffect {
177
+ position: absolute;
178
+ top: 0;
179
+ left: 0;
180
+ width: 100%;
181
+ height: 100%;
182
+ background-color: rgba(255, 0, 0, 0);
183
+ pointer-events: none;
184
+ transition: background-color 0.1s;
185
+ z-index: 5;
186
+ }
187
+ #damageIndicator {
188
+ position: absolute;
189
+ top: 50%;
190
+ left: 50%;
191
+ transform: translate(-50%, -50%);
192
+ font-size: 24px;
193
+ color: red;
194
+ opacity: 0;
195
+ pointer-events: none;
196
+ transition: opacity 0.3s;
197
+ text-shadow: 0 0 5px black;
198
  }
199
  </style>
200
  </head>
201
  <body>
202
  <canvas id="gameCanvas"></canvas>
203
+ <div id="crosshair"></div>
204
+ <div id="bloodEffect"></div>
205
+ <div id="damageIndicator">HIT!</div>
206
+
207
+ <div id="hud">
208
+ <div>Level: <span id="level">1</span></div>
209
+ <div>Kills: <span id="kills">0</span></div>
210
+ </div>
211
+
212
+ <div id="enemiesLeft">
213
+ Enemies: <span id="enemiesCount">0</span>
214
+ </div>
215
+
216
  <div id="ui">
217
+ <div id="weaponImage"></div>
218
+ <div id="weapon">PISTOL</div>
219
+ <div id="healthAmmo">
220
+ <div>
221
+ <div>HEALTH</div>
222
+ <div class="health-bar">
223
+ <div class="health-fill" id="healthBar"></div>
224
+ </div>
225
+ </div>
226
+ <div>
227
+ <div>AMMO</div>
228
+ <div class="ammo-bar">
229
+ <div class="ammo-fill" id="ammoBar"></div>
230
+ </div>
231
+ </div>
232
+ </div>
233
  </div>
234
+
235
  <div id="startScreen">
236
+ <h1 class="text-4xl font-bold mb-4">DOOM STYLE GAME</h1>
237
+ <p class="text-xl mb-8">KILL ALL DEMONS TO ADVANCE TO THE NEXT LEVEL</p>
238
+ <p class="mb-2">WASD - Move</p>
239
+ <p class="mb-2">Mouse - Look and Shoot</p>
240
+ <p class="mb-2">R - Reload</p>
241
+ <p class="mb-2">1-3 - Switch Weapons</p>
242
+ <p class="mb-2">Space - Jump</p>
243
  <button id="startButton">START GAME</button>
244
  </div>
245
+
246
+ <div id="gameOverScreen">
247
+ <h1 class="text-4xl font-bold mb-4">GAME OVER</h1>
248
+ <p class="text-xl mb-2">You killed <span id="finalKills">0</span> demons</p>
249
+ <p class="text-xl mb-8">Reached level <span id="finalLevel">1</span></p>
250
+ <button id="restartButton">TRY AGAIN</button>
251
+ </div>
252
 
253
  <script>
254
  // Game setup
 
256
  const ctx = canvas.getContext('2d');
257
  const startScreen = document.getElementById('startScreen');
258
  const startButton = document.getElementById('startButton');
259
+ const gameOverScreen = document.getElementById('gameOverScreen');
260
+ const restartButton = document.getElementById('restartButton');
261
+ const weaponImage = document.getElementById('weaponImage');
262
+ const weaponDisplay = document.getElementById('weapon');
263
+ const healthBar = document.getElementById('healthBar');
264
+ const ammoBar = document.getElementById('ammoBar');
265
+ const levelDisplay = document.getElementById('level');
266
+ const killsDisplay = document.getElementById('kills');
267
+ const enemiesCountDisplay = document.getElementById('enemiesCount');
268
+ const finalKillsDisplay = document.getElementById('finalKills');
269
+ const finalLevelDisplay = document.getElementById('finalLevel');
270
+ const bloodEffect = document.getElementById('bloodEffect');
271
+ const damageIndicator = document.getElementById('damageIndicator');
272
 
273
  // Set canvas size
274
  canvas.width = window.innerWidth;
 
276
 
277
  // Game state
278
  let gameRunning = false;
279
+ let level = 1;
280
+ let kills = 0;
281
+ let enemiesLeft = 0;
282
 
283
+ // Player
284
  const player = {
285
+ x: 1.5,
286
+ y: 1.5,
287
+ dirX: -1,
288
+ dirY: 0,
289
+ planeX: 0,
290
+ planeY: 0.66,
291
+ moveSpeed: 0.05,
292
+ rotSpeed: 0.03,
293
+ health: 100,
294
+ weapons: [
295
+ {
296
+ name: "PISTOL",
297
+ damage: 25,
298
+ ammo: 12,
299
+ maxAmmo: 12,
300
+ reloadTime: 1000,
301
+ fireRate: 500,
302
+ range: 10,
303
+ accuracy: 0.95,
304
+ color: "#888",
305
+ image: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 100'%3E%3Crect x='20' y='40' width='120' height='20' fill='%23ccc'/%3E%3Crect x='140' y='30' width='40' height='40' fill='%23aaa'/%3E%3Crect x='180' y='40' width='10' height='20' fill='%23888'/%3E%3C/svg%3E"
306
+ },
307
+ {
308
+ name: "SHOTGUN",
309
+ damage: 50,
310
+ ammo: 6,
311
+ maxAmmo: 6,
312
+ reloadTime: 1500,
313
+ fireRate: 1000,
314
+ range: 5,
315
+ accuracy: 0.7,
316
+ color: "#964B00",
317
+ image: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 100'%3E%3Crect x='20' y='40' width='150' height='20' fill='%23b87333'/%3E%3Crect x='170' y='20' width='20' height='60' fill='%238B4513'/%3E%3C/svg%3E"
318
+ },
319
+ {
320
+ name: "CHAINGUN",
321
+ damage: 15,
322
+ ammo: 50,
323
+ maxAmmo: 50,
324
+ reloadTime: 2000,
325
+ fireRate: 100,
326
+ range: 15,
327
+ accuracy: 0.85,
328
+ color: "#333",
329
+ image: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 100'%3E%3Crect x='20' y='40' width='150' height='20' fill='%23444'/%3E%3Crect x='170' y='30' width='20' height='40' fill='%23222'/%3E%3Ccircle cx='40' cy='50' r='15' fill='%23555'/%3E%3C/svg%3E"
330
+ }
331
+ ],
332
+ currentWeapon: 0,
333
+ lastShot: 0,
334
+ reloading: false,
335
+ isMoving: false,
336
+ isShooting: false,
337
+ jumpHeight: 0,
338
+ isJumping: false
339
  };
340
 
341
+ // Map (1 = wall, 0 = empty space)
342
+ let map = [
343
+ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
344
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
345
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
346
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
347
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
348
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
349
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
350
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
351
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
352
+ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
353
+ ];
354
+
355
+ // Wall textures (colors for simplicity)
356
+ const wallTextures = [
357
+ '#8B0000', // Red brick
358
+ '#006400', // Green stone
359
+ '#00008B', // Blue metal
360
+ '#4B0082', // Purple tech
361
+ '#8B4513' // Brown wood
362
+ ];
363
 
364
+ // Enemies
365
+ let enemies = [];
366
+
367
+ // Generate level
368
+ function generateLevel() {
369
+ // Clear previous enemies
370
+ enemies = [];
371
 
372
+ // Generate maze-like map
373
+ const size = 10 + level * 2;
374
+ map = Array(size).fill().map(() => Array(size).fill(1));
375
+
376
+ // Carve out maze
377
+ const stack = [];
378
+ const visited = Array(size).fill().map(() => Array(size).fill(false));
379
+
380
+ // Start at player position
381
+ player.x = 1.5;
382
+ player.y = 1.5;
383
+ map[1][1] = 0;
384
+ visited[1][1] = true;
385
+ stack.push([1, 1]);
386
+
387
+ while (stack.length > 0) {
388
+ const [x, y] = stack[stack.length - 1];
389
+ const directions = [
390
+ [0, 1], [1, 0], [0, -1], [-1, 0]
391
+ ].sort(() => Math.random() - 0.5);
392
+
393
+ let moved = false;
394
+
395
+ for (const [dx, dy] of directions) {
396
+ const nx = x + dx * 2;
397
+ const ny = y + dy * 2;
398
+
399
+ if (nx > 0 && nx < size - 1 && ny > 0 && ny < size - 1 && !visited[nx][ny]) {
400
+ map[x + dx][y + dy] = 0;
401
+ map[nx][ny] = 0;
402
+ visited[nx][ny] = true;
403
+ stack.push([nx, ny]);
404
+ moved = true;
405
+ break;
406
+ }
407
+ }
408
+
409
+ if (!moved) {
410
+ stack.pop();
411
+ }
412
  }
413
 
414
+ // Add some random walls
415
+ for (let i = 1; i < size - 1; i++) {
416
+ for (let j = 1; j < size - 1; j++) {
417
+ if (map[i][j] === 0 && Math.random() < 0.1) {
418
+ map[i][j] = 2 + Math.floor(Math.random() * (wallTextures.length - 1));
419
+ }
420
+ }
421
+ }
422
+
423
+ // Place exit
424
+ const exitX = size - 2;
425
+ const exitY = size - 2;
426
+ map[exitX][exitY] = 0;
427
+
428
+ // Place enemies
429
+ enemiesLeft = 5 + level * 3;
430
+ for (let i = 0; i < enemiesLeft; i++) {
431
+ let x, y;
432
+ do {
433
+ x = 1 + Math.floor(Math.random() * (size - 2));
434
+ y = 1 + Math.floor(Math.random() * (size - 2));
435
+ } while (map[x][y] !== 0 || (x === 1 && y === 1) || (x === exitX && y === exitY));
436
+
437
+ enemies.push({
438
+ x: x + 0.5,
439
+ y: y + 0.5,
440
+ health: 50 + level * 10,
441
+ speed: 0.02 + level * 0.005,
442
+ damage: 10 + level * 2,
443
+ color: `hsl(${Math.random() * 60}, 100%, 50%)`,
444
+ lastAttack: 0,
445
+ attackCooldown: 1000,
446
+ size: 0.5
447
  });
448
  }
449
 
450
+ // Update UI
451
+ enemiesCountDisplay.textContent = enemiesLeft;
 
452
  }
453
 
454
+ // Raycasting
455
+ function castRays() {
456
+ const width = canvas.width;
457
+ const height = canvas.height;
 
 
 
458
 
459
+ for (let x = 0; x < width; x++) {
460
+ // Calculate ray position and direction
461
+ const cameraX = 2 * x / width - 1;
462
+ const rayDirX = player.dirX + player.planeX * cameraX;
463
+ const rayDirY = player.dirY + player.planeY * cameraX;
464
+
465
+ // Which box of the map we're in
466
+ let mapX = Math.floor(player.x);
467
+ let mapY = Math.floor(player.y);
468
+
469
+ // Length of ray from current position to next x or y-side
470
+ let sideDistX, sideDistY;
471
+
472
+ // Length of ray from one x or y-side to next x or y-side
473
+ const deltaDistX = Math.abs(1 / rayDirX);
474
+ const deltaDistY = Math.abs(1 / rayDirY);
475
+
476
+ // Direction to step in x or y direction (either +1 or -1)
477
+ let stepX, stepY;
478
+
479
+ // Was a wall hit?
480
+ let hit = false;
481
+ // Was a wall hit that was NS or EW?
482
+ let side;
483
+ // Distance to wall
484
+ let perpWallDist;
485
+
486
+ // Calculate step and initial sideDist
487
+ if (rayDirX < 0) {
488
+ stepX = -1;
489
+ sideDistX = (player.x - mapX) * deltaDistX;
490
+ } else {
491
+ stepX = 1;
492
+ sideDistX = (mapX + 1.0 - player.x) * deltaDistX;
493
+ }
494
+
495
+ if (rayDirY < 0) {
496
+ stepY = -1;
497
+ sideDistY = (player.y - mapY) * deltaDistY;
498
+ } else {
499
+ stepY = 1;
500
+ sideDistY = (mapY + 1.0 - player.y) * deltaDistY;
501
+ }
502
+
503
+ // Perform DDA (Digital Differential Analysis)
504
+ while (!hit) {
505
+ // Jump to next map square, either in x-direction, or in y-direction
506
+ if (sideDistX < sideDistY) {
507
+ sideDistX += deltaDistX;
508
+ mapX += stepX;
509
+ side = 0;
510
+ } else {
511
+ sideDistY += deltaDistY;
512
+ mapY += stepY;
513
+ side = 1;
514
+ }
515
+
516
+ // Check if ray has hit a wall
517
+ if (mapX < 0 || mapX >= map.length || mapY < 0 || mapY >= map[0].length) {
518
+ hit = true;
519
+ } else if (map[mapX][mapY] > 0) {
520
+ hit = true;
521
+ }
522
+ }
523
+
524
+ // Calculate distance projected on camera direction
525
+ if (side === 0) {
526
+ perpWallDist = (mapX - player.x + (1 - stepX) / 2) / rayDirX;
527
+ } else {
528
+ perpWallDist = (mapY - player.y + (1 - stepY) / 2) / rayDirY;
529
+ }
530
+
531
+ // Calculate height of line to draw on screen
532
+ let lineHeight = Math.floor(height / perpWallDist);
533
+
534
+ // Calculate lowest and highest pixel to fill in current stripe
535
+ let drawStart = -lineHeight / 2 + height / 2;
536
+ if (drawStart < 0) drawStart = 0;
537
+ let drawEnd = lineHeight / 2 + height / 2;
538
+ if (drawEnd >= height) drawEnd = height - 1;
539
+
540
+ // Choose wall color based on map value
541
+ let color;
542
+ if (mapX < 0 || mapX >= map.length || mapY < 0 || mapY >= map[0].length) {
543
+ color = '#000';
544
+ } else {
545
+ const wallType = map[mapX][mapY];
546
+ color = wallTextures[wallType - 1] || '#FFF';
547
+ }
548
+
549
+ // Give x and y sides different brightness
550
+ if (side === 1) {
551
+ color = shadeColor(color, -30);
552
+ }
553
+
554
+ // Draw the wall slice
555
+ ctx.fillStyle = color;
556
+ ctx.fillRect(x, drawStart + player.jumpHeight, 1, drawEnd - drawStart);
557
+
558
+ // Draw floor (simplified)
559
+ ctx.fillStyle = '#333';
560
+ ctx.fillRect(x, drawEnd + player.jumpHeight, 1, height - drawEnd);
561
+ }
562
  }
563
 
564
+ // Draw enemies
565
+ function drawEnemies() {
566
+ const width = canvas.width;
567
+ const height = canvas.height;
568
+
569
+ // Sort enemies by distance (for proper rendering order)
570
+ enemies.sort((a, b) => {
571
+ const distA = Math.pow(player.x - a.x, 2) + Math.pow(player.y - a.y, 2);
572
+ const distB = Math.pow(player.x - b.x, 2) + Math.pow(player.y - b.y, 2);
573
+ return distB - distA;
574
+ });
575
+
576
+ for (const enemy of enemies) {
577
+ // Calculate enemy position relative to player
578
+ const relX = enemy.x - player.x;
579
+ const relY = enemy.y - player.y;
580
+
581
+ // Transform enemy position with inverse camera matrix
582
+ const invDet = 1.0 / (player.planeX * player.dirY - player.dirX * player.planeY);
583
+ const transformX = invDet * (player.dirY * relX - player.dirX * relY);
584
+ const transformY = invDet * (-player.planeY * relX + player.planeX * relY);
585
+
586
+ // Don't draw enemies behind the player
587
+ if (transformY <= 0) continue;
588
+
589
+ // Calculate sprite position on screen
590
+ const spriteScreenX = Math.floor((width / 2) * (1 + transformX / transformY));
591
+
592
+ // Calculate sprite dimensions
593
+ const spriteHeight = Math.abs(Math.floor(height / transformY));
594
+ const spriteWidth = spriteHeight;
595
+
596
+ // Calculate drawing coordinates
597
+ let drawStartX = -spriteWidth / 2 + spriteScreenX;
598
+ let drawEndX = spriteWidth / 2 + spriteScreenX;
599
+ let drawStartY = -spriteHeight / 2 + height / 2;
600
+ let drawEndY = spriteHeight / 2 + height / 2;
601
+
602
+ // Clamp to screen bounds
603
+ if (drawStartX < 0) drawStartX = 0;
604
+ if (drawEndX >= width) drawEndX = width - 1;
605
+ if (drawStartY < 0) drawStartY = 0;
606
+ if (drawEndY >= height) drawEndY = height - 1;
607
+
608
+ // Draw enemy
609
+ for (let stripe = drawStartX; stripe < drawEndX; stripe++) {
610
+ const texX = Math.floor((stripe - (-spriteWidth / 2 + spriteScreenX)) * enemy.size / spriteWidth);
611
+
612
+ if (transformY > 0 && stripe > 0 && stripe < width) {
613
+ for (let y = drawStartY; y < drawEndY; y++) {
614
+ const d = (y - (-spriteHeight / 2 + height / 2)) * 256 / spriteHeight;
615
+ const texY = Math.floor(d * enemy.size / spriteHeight);
616
+
617
+ // Simple enemy drawing (just a colored rectangle)
618
+ if (texX >= 0 && texX < enemy.size * 100 && texY >= 0 && texY < enemy.size * 100) {
619
+ ctx.fillStyle = enemy.color;
620
+ ctx.fillRect(stripe, y + player.jumpHeight, 1, 1);
621
+ }
622
+ }
623
+ }
624
+ }
625
+ }
626
+ }
627
+
628
+ // Draw weapon
629
+ function drawWeapon() {
630
+ const weapon = player.weapons[player.currentWeapon];
631
+ weaponImage.style.backgroundImage = `url("${weapon.image}")`;
632
+ weaponDisplay.textContent = weapon.name;
633
+
634
+ // Weapon bob when moving
635
+ let bobOffset = 0;
636
+ if (player.isMoving) {
637
+ bobOffset = Math.sin(Date.now() / 100) * 5;
638
+ }
639
+
640
+ // Weapon recoil when shooting
641
+ let recoilOffset = 0;
642
+ if (player.isShooting) {
643
+ recoilOffset = Math.sin(Date.now() / 50) * 10;
644
+ }
645
+
646
+ weaponImage.style.transform = `translateY(${bobOffset + recoilOffset}px)`;
647
+ }
648
+
649
+ // Update HUD
650
+ function updateHUD() {
651
+ const weapon = player.weapons[player.currentWeapon];
652
+ healthBar.style.width = `${player.health}%`;
653
+ ammoBar.style.width = `${(weapon.ammo / weapon.maxAmmo) * 100}%`;
654
+ levelDisplay.textContent = level;
655
+ killsDisplay.textContent = kills;
656
+ enemiesCountDisplay.textContent = enemiesLeft;
657
+
658
+ // Blood effect when hurt
659
+ if (player.health < 30) {
660
+ bloodEffect.style.backgroundColor = `rgba(255, 0, 0, ${0.3 - (player.health / 100)})`;
661
+ } else {
662
+ bloodEffect.style.backgroundColor = 'rgba(255, 0, 0, 0)';
663
+ }
664
+ }
665
+
666
+ // Move player
667
+ function movePlayer() {
668
  if (!gameRunning) return;
669
 
670
+ // Movement speed
671
+ const moveSpeed = player.moveSpeed;
672
+ const rotSpeed = player.rotSpeed;
673
+
674
+ // Rotate left/right
675
+ if (keys.ArrowLeft) {
676
+ const oldDirX = player.dirX;
677
+ player.dirX = player.dirX * Math.cos(rotSpeed) - player.dirY * Math.sin(rotSpeed);
678
+ player.dirY = oldDirX * Math.sin(rotSpeed) + player.dirY * Math.cos(rotSpeed);
679
+
680
+ const oldPlaneX = player.planeX;
681
+ player.planeX = player.planeX * Math.cos(rotSpeed) - player.planeY * Math.sin(rotSpeed);
682
+ player.planeY = oldPlaneX * Math.sin(rotSpeed) + player.planeY * Math.cos(rotSpeed);
683
+ }
684
 
685
+ if (keys.ArrowRight) {
686
+ const oldDirX = player.dirX;
687
+ player.dirX = player.dirX * Math.cos(-rotSpeed) - player.dirY * Math.sin(-rotSpeed);
688
+ player.dirY = oldDirX * Math.sin(-rotSpeed) + player.dirY * Math.cos(-rotSpeed);
689
 
690
+ const oldPlaneX = player.planeX;
691
+ player.planeX = player.planeX * Math.cos(-rotSpeed) - player.planeY * Math.sin(-rotSpeed);
692
+ player.planeY = oldPlaneX * Math.sin(-rotSpeed) + player.planeY * Math.cos(-rotSpeed);
693
+ }
694
+
695
+ // Move forward/backward
696
+ let moveX = 0, moveY = 0;
697
+ player.isMoving = false;
698
+
699
+ if (keys.w) {
700
+ moveX += player.dirX * moveSpeed;
701
+ moveY += player.dirY * moveSpeed;
702
+ player.isMoving = true;
703
+ }
704
+
705
+ if (keys.s) {
706
+ moveX -= player.dirX * moveSpeed;
707
+ moveY -= player.dirY * moveSpeed;
708
+ player.isMoving = true;
709
+ }
710
+
711
+ // Strafe left/right
712
+ if (keys.a) {
713
+ moveX -= player.planeX * moveSpeed;
714
+ moveY -= player.planeY * moveSpeed;
715
+ player.isMoving = true;
716
+ }
717
+
718
+ if (keys.d) {
719
+ moveX += player.planeX * moveSpeed;
720
+ moveY += player.planeY * moveSpeed;
721
+ player.isMoving = true;
722
+ }
723
+
724
+ // Jump
725
+ if (keys[' '] && !player.isJumping) {
726
+ player.isJumping = true;
727
+ player.jumpHeight = -20;
728
+ }
729
+
730
+ // Handle jumping
731
+ if (player.isJumping) {
732
+ player.jumpHeight += 2;
733
+ if (player.jumpHeight >= 0) {
734
+ player.jumpHeight = 0;
735
+ player.isJumping = false;
736
+ }
737
+ }
738
+
739
+ // Collision detection
740
+ if (map[Math.floor(player.x + moveX)][Math.floor(player.y)] === 0) {
741
+ player.x += moveX;
742
+ }
743
+
744
+ if (map[Math.floor(player.x)][Math.floor(player.y + moveY)] === 0) {
745
+ player.y += moveY;
746
+ }
747
+
748
+ // Check if player reached exit
749
+ if (Math.floor(player.x) === map.length - 2 && Math.floor(player.y) === map[0].length - 2) {
750
+ if (enemiesLeft === 0) {
751
+ level++;
752
+ generateLevel();
753
+ }
754
+ }
755
+ }
756
+
757
+ // Update enemies
758
+ function updateEnemies() {
759
+ const now = Date.now();
760
+
761
+ for (let i = enemies.length - 1; i >= 0; i--) {
762
+ const enemy = enemies[i];
763
+
764
+ // Move towards player
765
+ const dx = player.x - enemy.x;
766
+ const dy = player.y - enemy.y;
767
+ const dist = Math.sqrt(dx * dx + dy * dy);
768
+
769
+ if (dist > 0.5) { // Don't get too close
770
+ enemy.x += (dx / dist) * enemy.speed;
771
+ enemy.y += (dy / dist) * enemy.speed;
772
+
773
+ // Simple collision with walls
774
+ if (map[Math.floor(enemy.x)][Math.floor(enemy.y)] !== 0) {
775
+ enemy.x -= (dx / dist) * enemy.speed;
776
+ enemy.y -= (dy / dist) * enemy.speed;
777
  }
778
+ }
779
+
780
+ // Attack player if close enough
781
+ if (dist < 1.5 && now - enemy.lastAttack > enemy.attackCooldown) {
782
+ player.health -= enemy.damage;
783
+ enemy.lastAttack = now;
784
+
785
+ // Show damage indicator
786
+ damageIndicator.style.opacity = 1;
787
+ setTimeout(() => {
788
+ damageIndicator.style.opacity = 0;
789
+ }, 300);
790
+
791
+ // Blood effect
792
+ bloodEffect.style.backgroundColor = 'rgba(255, 0, 0, 0.5)';
793
+ setTimeout(() => {
794
+ bloodEffect.style.backgroundColor = 'rgba(255, 0, 0, 0)';
795
+ }, 100);
796
+
797
+ // Check if player died
798
+ if (player.health <= 0) {
799
+ gameOver();
800
  }
801
  }
802
+
803
+ // Remove dead enemies
804
+ if (enemy.health <= 0) {
805
+ enemies.splice(i, 1);
806
+ enemiesLeft--;
807
+ kills++;
808
+
809
+ // Update UI
810
+ enemiesCountDisplay.textContent = enemiesLeft;
811
+ killsDisplay.textContent = kills;
812
+ }
813
+ }
814
+ }
815
+
816
+ // Shoot
817
+ function shoot() {
818
+ const now = Date.now();
819
+ const weapon = player.weapons[player.currentWeapon];
820
 
821
+ // Check if can shoot
822
+ if (now - player.lastShot < weapon.fireRate || player.reloading || weapon.ammo <= 0) {
823
+ return;
824
+ }
825
 
826
+ player.lastShot = now;
827
+ player.isShooting = true;
828
+ setTimeout(() => {
829
+ player.isShooting = false;
830
+ }, 100);
831
 
832
+ // Reduce ammo
833
+ weapon.ammo--;
834
+
835
+ // Check for hits
836
+ for (let i = 0; i < enemies.length; i++) {
837
+ const enemy = enemies[i];
838
+
839
+ // Calculate angle to enemy
840
+ const dx = enemy.x - player.x;
841
+ const dy = enemy.y - player.y;
842
+ const dist = Math.sqrt(dx * dx + dy * dy);
843
+
844
+ // Angle between player direction and enemy
845
+ const playerAngle = Math.atan2(player.dirY, player.dirX);
846
+ const enemyAngle = Math.atan2(dy, dx);
847
+ let angleDiff = Math.abs(playerAngle - enemyAngle);
848
+
849
+ // Normalize angle
850
+ if (angleDiff > Math.PI) {
851
+ angleDiff = 2 * Math.PI - angleDiff;
852
+ }
853
+
854
+ // Check if enemy is in front and within range
855
+ if (dist < weapon.range && angleDiff < 0.5 * weapon.accuracy) {
856
+ // Hit the enemy
857
+ enemy.health -= weapon.damage;
858
+
859
+ // Show damage indicator
860
+ damageIndicator.style.opacity = 1;
861
+ setTimeout(() => {
862
+ damageIndicator.style.opacity = 0;
863
+ }, 300);
864
+
865
+ // Enemy hit effect
866
+ enemy.color = `hsl(${Math.random() * 60}, 100%, 70%)`;
867
+ setTimeout(() => {
868
+ enemy.color = `hsl(${Math.random() * 60}, 100%, 50%)`;
869
+ }, 100);
870
+ }
871
+ }
872
+
873
+ // Reload if out of ammo
874
+ if (weapon.ammo <= 0) {
875
+ reload();
876
+ }
877
+ }
878
+
879
+ // Reload
880
+ function reload() {
881
+ if (player.reloading) return;
882
+
883
+ const weapon = player.weapons[player.currentWeapon];
884
+ if (weapon.ammo === weapon.maxAmmo) return;
885
+
886
+ player.reloading = true;
887
+ setTimeout(() => {
888
+ weapon.ammo = weapon.maxAmmo;
889
+ player.reloading = false;
890
+ }, weapon.reloadTime);
891
+ }
892
+
893
+ // Game over
894
+ function gameOver() {
895
+ gameRunning = false;
896
+ finalKillsDisplay.textContent = kills;
897
+ finalLevelDisplay.textContent = level;
898
+ gameOverScreen.style.display = 'flex';
899
+ }
900
+
901
+ // Game loop
902
+ function gameLoop() {
903
+ if (!gameRunning) return;
904
+
905
+ // Clear canvas
906
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
907
+
908
+ // Draw ceiling (simplified)
909
+ ctx.fillStyle = '#111';
910
+ ctx.fillRect(0, 0, canvas.width, canvas.height / 2);
911
+
912
+ // Cast rays and draw walls
913
+ castRays();
914
+
915
+ // Draw enemies
916
+ drawEnemies();
917
+
918
+ // Update player and enemies
919
+ movePlayer();
920
+ updateEnemies();
921
+
922
+ // Draw weapon
923
+ drawWeapon();
924
+
925
+ // Update HUD
926
+ updateHUD();
927
 
928
  // Request next frame
929
  requestAnimationFrame(gameLoop);
 
931
 
932
  // Keyboard controls
933
  const keys = {
934
+ w: false,
935
+ a: false,
936
+ s: false,
937
+ d: false,
938
+ ' ': false,
939
  ArrowLeft: false,
940
  ArrowRight: false,
941
+ r: false
942
  };
943
 
944
  document.addEventListener('keydown', (e) => {
945
  if (e.key in keys) keys[e.key] = true;
946
+
947
+ // Switch weapons
948
+ if (e.key >= '1' && e.key <= '3') {
949
+ player.currentWeapon = parseInt(e.key) - 1;
950
+ }
951
+
952
+ // Reload
953
+ if (e.key === 'r') {
954
+ reload();
955
+ }
956
  });
957
 
958
  document.addEventListener('keyup', (e) => {
959
  if (e.key in keys) keys[e.key] = false;
960
  });
961
 
962
+ // Mouse controls
963
+ let mouseX = 0;
964
+ let mouseDown = false;
965
+
966
+ canvas.addEventListener('mousedown', () => {
967
+ mouseDown = true;
968
+ if (gameRunning) shoot();
969
+ });
970
+
971
+ canvas.addEventListener('mouseup', () => {
972
+ mouseDown = false;
973
+ });
974
+
975
+ canvas.addEventListener('mousemove', (e) => {
976
  if (!gameRunning) return;
977
 
978
+ const movementX = e.movementX || 0;
 
 
 
 
 
 
 
 
 
979
 
980
+ // Rotate view based on mouse movement
981
+ if (movementX !== 0) {
982
+ const rotSpeed = 0.002 * movementX;
983
+ const oldDirX = player.dirX;
984
+ player.dirX = player.dirX * Math.cos(rotSpeed) - player.dirY * Math.sin(rotSpeed);
985
+ player.dirY = oldDirX * Math.sin(rotSpeed) + player.dirY * Math.cos(rotSpeed);
986
+
987
+ const oldPlaneX = player.planeX;
988
+ player.planeX = player.planeX * Math.cos(rotSpeed) - player.planeY * Math.sin(rotSpeed);
989
+ player.planeY = oldPlaneX * Math.sin(rotSpeed) + player.planeY * Math.cos(rotSpeed);
990
  }
991
+ });
992
+
993
+ // Touch controls for mobile
994
+ let touchStartX = 0;
995
+
996
+ canvas.addEventListener('touchstart', (e) => {
997
+ e.preventDefault();
998
+ touchStartX = e.touches[0].clientX;
999
+ if (gameRunning) shoot();
1000
+ });
1001
+
1002
+ canvas.addEventListener('touchmove', (e) => {
1003
+ e.preventDefault();
1004
+ if (!gameRunning) return;
1005
 
1006
+ const touchX = e.touches[0].clientX;
1007
+ const movementX = (touchX - touchStartX) * 0.1;
1008
+ touchStartX = touchX;
1009
+
1010
+ // Rotate view based on touch movement
1011
+ if (movementX !== 0) {
1012
+ const rotSpeed = 0.002 * movementX;
1013
+ const oldDirX = player.dirX;
1014
+ player.dirX = player.dirX * Math.cos(rotSpeed) - player.dirY * Math.sin(rotSpeed);
1015
+ player.dirY = oldDirX * Math.sin(rotSpeed) + player.dirY * Math.cos(rotSpeed);
1016
+
1017
+ const oldPlaneX = player.planeX;
1018
+ player.planeX = player.planeX * Math.cos(rotSpeed) - player.planeY * Math.sin(rotSpeed);
1019
+ player.planeY = oldPlaneX * Math.sin(rotSpeed) + player.planeY * Math.cos(rotSpeed);
1020
  }
1021
+ });
1022
+
1023
+ canvas.addEventListener('touchend', (e) => {
1024
+ e.preventDefault();
1025
+ });
1026
 
1027
  // Start game
1028
  function startGame() {
 
1030
  gameRunning = true;
1031
 
1032
  // Reset game state
1033
+ level = 1;
1034
+ kills = 0;
1035
+ player.health = 100;
1036
+ player.currentWeapon = 0;
1037
+ player.weapons.forEach(w => w.ammo = w.maxAmmo);
1038
 
1039
+ // Generate level
1040
+ generateLevel();
1041
 
1042
  // Start game loop
1043
  gameLoop();
1044
+ }
1045
+
1046
+ // Restart game
1047
+ function restartGame() {
1048
+ gameOverScreen.style.display = 'none';
1049
+ startGame();
1050
  }
1051
 
1052
  // Start button event
1053
  startButton.addEventListener('click', startGame);
1054
+ restartButton.addEventListener('click', restartGame);
1055
 
1056
  // Handle window resize
1057
  window.addEventListener('resize', () => {
1058
  canvas.width = window.innerWidth;
1059
  canvas.height = window.innerHeight;
 
1060
  });
1061
+
1062
+ // Helper function to shade colors
1063
+ function shadeColor(color, percent) {
1064
+ let R = parseInt(color.substring(1, 3), 16);
1065
+ let G = parseInt(color.substring(3, 5), 16);
1066
+ let B = parseInt(color.substring(5, 7), 16);
1067
+
1068
+ R = parseInt(R * (100 + percent) / 100);
1069
+ G = parseInt(G * (100 + percent) / 100);
1070
+ B = parseInt(B * (100 + percent) / 100);
1071
+
1072
+ R = R < 255 ? R : 255;
1073
+ G = G < 255 ? G : 255;
1074
+ B = B < 255 ? B : 255;
1075
+
1076
+ const RR = R.toString(16).length === 1 ? '0' + R.toString(16) : R.toString(16);
1077
+ const GG = G.toString(16).length === 1 ? '0' + G.toString(16) : G.toString(16);
1078
+ const BB = B.toString(16).length === 1 ? '0' + B.toString(16) : B.toString(16);
1079
+
1080
+ return '#' + RR + GG + BB;
1081
+ }
1082
  </script>
1083
  <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Greats/clone" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1084
  </html>
prompts.txt CHANGED
@@ -1,4 +1,5 @@
1
  создай чудо
2
  сделай огромный проект ссобой полностью законченный и рабочий
3
  сделай сайт онлайн игру на подобе гта5
4
- не работает
 
 
1
  создай чудо
2
  сделай огромный проект ссобой полностью законченный и рабочий
3
  сделай сайт онлайн игру на подобе гта5
4
+ не работает
5
+ сделай полную игру в стиле doom