awacke1 commited on
Commit
c95b789
·
verified ·
1 Parent(s): 6d3655d

Create lunar_lander.htm

Browse files
Files changed (1) hide show
  1. lunar_lander.htm +229 -0
lunar_lander.htm ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <style>
5
+ body { margin: 0; }
6
+ #game-container {
7
+ width: 100%;
8
+ height: 400px;
9
+ background: black;
10
+ position: relative;
11
+ overflow: hidden;
12
+ }
13
+ .lander {
14
+ width: 32px;
15
+ height: 32px;
16
+ position: absolute;
17
+ transform: translate(-50%, -50%);
18
+ }
19
+ .thrust-particle {
20
+ width: 4px;
21
+ height: 4px;
22
+ background: red;
23
+ position: absolute;
24
+ border-radius: 50%;
25
+ }
26
+ .flag {
27
+ width: 4px;
28
+ height: 24px;
29
+ background: yellow;
30
+ position: absolute;
31
+ bottom: 48px;
32
+ }
33
+ .hud {
34
+ position: absolute;
35
+ color: white;
36
+ padding: 16px;
37
+ font-family: sans-serif;
38
+ }
39
+ .controls {
40
+ position: absolute;
41
+ top: 16px;
42
+ right: 16px;
43
+ color: white;
44
+ font-family: sans-serif;
45
+ font-size: 14px;
46
+ }
47
+ </style>
48
+ </head>
49
+ <body>
50
+ <div id="game-container">
51
+ <div class="hud">
52
+ <div id="fuel">Fuel: 100%</div>
53
+ <div id="velocity">Velocity: 0 m/s</div>
54
+ <div id="score"></div>
55
+ </div>
56
+ <div class="controls">
57
+ <div>↑ - Thrust</div>
58
+ <div>← → - Move</div>
59
+ <div>Land between flags</div>
60
+ </div>
61
+ </div>
62
+
63
+ <script>
64
+ class LunarLander {
65
+ constructor() {
66
+ this.container = document.getElementById('game-container');
67
+ this.position = { x: 200, y: 50 };
68
+ this.velocity = { x: 0, y: 0 };
69
+ this.fuel = 100;
70
+ this.gameState = 'playing';
71
+ this.thrust = false;
72
+
73
+ this.GRAVITY = 0.05;
74
+ this.THRUST = 0.15;
75
+ this.LANDING_SPEED = 3;
76
+
77
+ this.groundPoints = [
78
+ {x: 0, y: 380}, {x: 100, y: 360}, {x: 150, y: 370},
79
+ {x: 200, y: 350}, {x: 300, y: 350}, {x: 350, y: 370},
80
+ {x: 400, y: 360}, {x: 450, y: 380}, {x: 500, y: 370}
81
+ ];
82
+
83
+ this.setupGame();
84
+ }
85
+
86
+ setupGame() {
87
+ this.createLander();
88
+ this.createFlags();
89
+ this.createGround();
90
+ this.setupControls();
91
+ this.gameLoop();
92
+ }
93
+
94
+ createLander() {
95
+ this.lander = document.createElement('div');
96
+ this.lander.className = 'lander';
97
+ this.lander.style.background = '#a855f7';
98
+ this.container.appendChild(this.lander);
99
+ }
100
+
101
+ createFlags() {
102
+ const flag1 = document.createElement('div');
103
+ flag1.className = 'flag';
104
+ flag1.style.left = '190px';
105
+
106
+ const flag2 = document.createElement('div');
107
+ flag2.className = 'flag';
108
+ flag2.style.left = '310px';
109
+
110
+ this.container.appendChild(flag1);
111
+ this.container.appendChild(flag2);
112
+ }
113
+
114
+ createGround() {
115
+ const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
116
+ svg.style.position = 'absolute';
117
+ svg.style.bottom = '0';
118
+ svg.style.width = '100%';
119
+ svg.style.height = '100%';
120
+
121
+ const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
122
+ const d = `M${this.groundPoints.map(p => `${p.x} ${p.y}`).join(' L')}`;
123
+ path.setAttribute('d', d);
124
+ path.setAttribute('stroke', 'white');
125
+ path.setAttribute('fill', 'none');
126
+ path.setAttribute('stroke-width', '2');
127
+
128
+ svg.appendChild(path);
129
+ this.container.appendChild(svg);
130
+ }
131
+
132
+ setupControls() {
133
+ document.addEventListener('keydown', (e) => {
134
+ if (this.gameState !== 'playing' || this.fuel <= 0) return;
135
+
136
+ switch (e.key) {
137
+ case 'ArrowUp':
138
+ this.thrust = true;
139
+ this.velocity.y -= this.THRUST;
140
+ this.fuel = Math.max(0, this.fuel - 0.5);
141
+ this.updateThrust();
142
+ break;
143
+ case 'ArrowLeft':
144
+ this.velocity.x -= 0.1;
145
+ this.fuel = Math.max(0, this.fuel - 0.2);
146
+ break;
147
+ case 'ArrowRight':
148
+ this.velocity.x += 0.1;
149
+ this.fuel = Math.max(0, this.fuel - 0.2);
150
+ break;
151
+ }
152
+ });
153
+
154
+ document.addEventListener('keyup', (e) => {
155
+ if (e.key === 'ArrowUp') {
156
+ this.thrust = false;
157
+ this.updateThrust();
158
+ }
159
+ });
160
+ }
161
+
162
+ updateThrust() {
163
+ const particles = this.lander.querySelectorAll('.thrust-particle');
164
+ particles.forEach(p => p.remove());
165
+
166
+ if (this.thrust) {
167
+ for (let i = 0; i < 4; i++) {
168
+ const particle = document.createElement('div');
169
+ particle.className = 'thrust-particle';
170
+ particle.style.left = `${Math.random() * 8 - 4}px`;
171
+ particle.style.top = `${Math.random() * 8}px`;
172
+ this.lander.appendChild(particle);
173
+ }
174
+ }
175
+ }
176
+
177
+ checkCollision() {
178
+ for (let i = 0; i < this.groundPoints.length - 1; i++) {
179
+ const p1 = this.groundPoints[i];
180
+ const p2 = this.groundPoints[i + 1];
181
+
182
+ if (this.position.x >= p1.x && this.position.x <= p2.x) {
183
+ const groundY = p1.y + ((p2.y - p1.y) * (this.position.x - p1.x)) / (p2.x - p1.x);
184
+
185
+ if (this.position.y >= groundY - 10) {
186
+ if (this.velocity.y < this.LANDING_SPEED * 1.5 &&
187
+ Math.abs(this.velocity.x) < 2 &&
188
+ this.position.x >= 190 &&
189
+ this.position.x <= 310) {
190
+ this.gameState = 'won';
191
+ document.getElementById('score').textContent = `Score: ${Math.floor(this.fuel * 100)}`;
192
+ } else {
193
+ this.gameState = 'crashed';
194
+ }
195
+ return true;
196
+ }
197
+ }
198
+ }
199
+ return false;
200
+ }
201
+
202
+ updateHUD() {
203
+ document.getElementById('fuel').textContent = `Fuel: ${Math.floor(this.fuel)}%`;
204
+ document.getElementById('velocity').textContent = `Velocity: ${Math.floor(this.velocity.y * 10)} m/s`;
205
+ }
206
+
207
+ gameLoop = () => {
208
+ if (this.gameState === 'playing') {
209
+ this.position.x += this.velocity.x;
210
+ this.position.y += this.velocity.y;
211
+
212
+ this.velocity.x *= 0.99;
213
+ this.velocity.y += this.GRAVITY;
214
+
215
+ this.lander.style.left = `${this.position.x}px`;
216
+ this.lander.style.top = `${this.position.y}px`;
217
+
218
+ this.updateHUD();
219
+ this.checkCollision();
220
+ }
221
+
222
+ requestAnimationFrame(this.gameLoop);
223
+ }
224
+ }
225
+
226
+ new LunarLander();
227
+ </script>
228
+ </body>
229
+ </html>