gaur3009 commited on
Commit
04e2228
·
verified ·
1 Parent(s): f62d19e

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +365 -18
index.html CHANGED
@@ -1,19 +1,366 @@
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" />
6
+ <title>Sling Humans — Prototype</title>
7
+ <style>
8
+ html,body{height:100%;margin:0;background:linear-gradient(#bfe9ff,#eaf7ff);font-family:Inter,system-ui,Segoe UI,Arial}
9
+ #game {width:100%;height:100vh;overflow:hidden}
10
+ .ui {position:absolute;left:14px;top:14px;background:rgba(255,255,255,0.9);padding:10px;border-radius:10px;box-shadow:0 6px 18px rgba(13,38,76,0.08);z-index:10}
11
+ .ui button{background:#1976d2;color:white;border:none;padding:8px 12px;border-radius:8px;cursor:pointer}
12
+ .ui .small{font-size:13px;color:#0b2540;margin-top:6px}
13
+ .credits{position:absolute;right:14px;top:14px;background:rgba(255,255,255,0.9);padding:8px 10px;border-radius:8px;font-size:13px;z-index:10}
14
+ </style>
15
+ </head>
16
+ <body>
17
+ <div id="game"></div>
18
+ <div class="ui">
19
+ <div style="font-weight:700">Sling Humans — Prototype</div>
20
+ <div style="margin-top:8px;display:flex;gap:8px">
21
+ <button id="restart">Restart</button>
22
+ <button id="next">Next Level</button>
23
+ <button id="powerup">Mega Launch</button>
24
+ </div>
25
+ <div class="small">Score: <span id="score">0</span> • Ammo: <span id="ammo">5</span> • Stars: <span id="stars">0</span></div>
26
+ <div style="margin-top:8px;font-size:13px;color:#444">Human: <select id="hType">
27
+ <option value="regular">Regular</option>
28
+ <option value="heavy">Heavyweight</option>
29
+ <option value="jumper">Jumper</option>
30
+ <option value="boomer">Boomer</option>
31
+ </select></div>
32
+ </div>
33
+ <div class="credits">Cartoon style — non graphic</div>
34
+
35
+ <!-- Phaser 3 CDN -->
36
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/phaser.min.js"></script>
37
+ <script>
38
+ /*
39
+ Sling Humans — Prototype
40
+ - Single-file Phaser 3 game
41
+ - Uses emoji + basic shapes
42
+ - Extendable: add assets, audio, more levels
43
+ */
44
+
45
+ const WIDTH = Math.min(window.innerWidth, 1200);
46
+ const HEIGHT = Math.min(window.innerHeight, 800);
47
+
48
+ const config = {
49
+ type: Phaser.AUTO,
50
+ parent: 'game',
51
+ width: WIDTH,
52
+ height: HEIGHT,
53
+ backgroundColor: 0xe8f7ff,
54
+ physics: { default: 'matter', matter: { gravity: { y: 1.0 }, debug: false } },
55
+ scene: { preload, create, update }
56
+ };
57
+
58
+ const game = new Phaser.Game(config);
59
+
60
+ let slingPos = { x: 160, y: HEIGHT - 180 };
61
+ let currentHuman = null, isDragging=false;
62
+ let dottedLines = [];
63
+ let score = 0, ammo = 5, level = 0, stars = 0;
64
+ let blocksGroup = [], targetsGroup = [];
65
+ let megaLaunchActive = false;
66
+
67
+ function preload() {
68
+ // no external assets; can load sprites/sounds here later
69
+ }
70
+
71
+ function create() {
72
+ const scene = this;
73
+
74
+ // ground
75
+ const ground = scene.matter.add.rectangle(WIDTH/2, HEIGHT-24, WIDTH, 48, { isStatic: true, label: 'ground' });
76
+
77
+ // catapult base visuals
78
+ scene.add.circle(slingPos.x, slingPos.y, 20, 0x6d4c41).setDepth(2);
79
+ scene.add.rectangle(slingPos.x+28, slingPos.y+12, 10, 40, 0x4e342e).setOrigin(0.5).setDepth(2);
80
+
81
+ // UI hooks
82
+ document.getElementById('restart').onclick = () => resetLevel(scene);
83
+ document.getElementById('next').onclick = () => nextLevel(scene);
84
+ document.getElementById('powerup').onclick = () => { megaLaunchActive = true; document.getElementById('powerup').innerText='Mega! (On)'; setTimeout(()=>{megaLaunchActive=false; document.getElementById('powerup').innerText='Mega Launch';}, 8000); };
85
+
86
+ // level build
87
+ buildLevel(scene, level);
88
+
89
+ // spawn human
90
+ spawnHuman(scene);
91
+
92
+ // input handlers
93
+ scene.input.on('pointerdown', (pointer) => {
94
+ if (!currentHuman) return;
95
+ const bodies = Phaser.Physics.Matter.Matter.Query.point([currentHuman.body], pointer);
96
+ if (bodies.length) {
97
+ isDragging = true;
98
+ scene.matter.body.setStatic(currentHuman.body, true); // hold it while dragging
99
+ }
100
+ });
101
+
102
+ scene.input.on('pointermove', (pointer) => {
103
+ if (!isDragging || !currentHuman) return;
104
+ // clamp drag radius
105
+ const maxDrag = 250;
106
+ const dx = pointer.x - slingPos.x;
107
+ const dy = pointer.y - slingPos.y;
108
+ const dist = Math.min(Math.hypot(dx,dy), maxDrag);
109
+ const angle = Math.atan2(dy,dx);
110
+ const px = slingPos.x + Math.cos(angle)*dist;
111
+ const py = slingPos.y + Math.sin(angle)*dist;
112
+ currentHuman.setPosition(px, py);
113
+ drawTrajectory(scene, currentHuman.x, currentHuman.y, slingPos.x - px, slingPos.y - py);
114
+ });
115
+
116
+ scene.input.on('pointerup', (pointer) => {
117
+ if (!isDragging || !currentHuman) return;
118
+ isDragging = false;
119
+ clearTrajectory();
120
+ // compute launch velocity
121
+ const dx = slingPos.x - currentHuman.x;
122
+ const dy = slingPos.y - currentHuman.y;
123
+ let power = Math.sqrt(dx*dx + dy*dy);
124
+ const angle = Math.atan2(dy, dx);
125
+ let velocityFactor = 0.08 * (megaLaunchActive ? 2.2 : 1.0); // mega launch stronger
126
+ const vx = Math.cos(angle) * power * velocityFactor;
127
+ const vy = Math.sin(angle) * power * velocityFactor;
128
+ scene.matter.body.setStatic(currentHuman.body, false);
129
+ scene.matter.body.setVelocity(currentHuman.body, { x: vx, y: vy });
130
+ // small spin
131
+ scene.matter.body.setAngularVelocity(currentHuman.body, (Math.random()*6-3));
132
+ // track with camera
133
+ scene.cameras.main.startFollow(currentHuman, true, 0.06, 0.06);
134
+ // reduce ammo and update UI
135
+ ammo = Math.max(0, ammo-1);
136
+ updateUi();
137
+ // after a delay spawn next if ammo left
138
+ scene.time.delayedCall(800, ()=>{ if (ammo>0) spawnHuman(scene); });
139
+ });
140
+
141
+ // collision detection with blocks/targets
142
+ scene.matter.world.on('collisionstart', (event) => {
143
+ event.pairs.forEach(pair => {
144
+ const { bodyA, bodyB } = pair;
145
+ [bodyA, bodyB].forEach(b => {
146
+ if (!b.gameObject) return;
147
+ const go = b.gameObject;
148
+ // if boomer explosion type and collision strong, explode
149
+ if (go.humanType === 'boomer') {
150
+ const speed = pair.collision.penetration && Math.hypot(pair.collision.penetration.x, pair.collision.penetration.y) || 0;
151
+ if (speed > 1.2 && !go.exploded) {
152
+ go.exploded = true;
153
+ explodeAt(scene, go.x, go.y);
154
+ scene.matter.world.remove(go.body);
155
+ go.destroy();
156
+ }
157
+ }
158
+ });
159
+ // scoring: check if block knocked far or high force
160
+ const bodies = [bodyA.gameObject, bodyB.gameObject];
161
+ bodies.forEach(obj => {
162
+ if (obj && obj.isBlock && !obj.scored) {
163
+ // if block speed large or rotated a lot -> scored
164
+ const speed = obj.body.speed || 0;
165
+ const angle = Math.abs(obj.rotation || 0);
166
+ if (speed > 3 || angle > 0.6) {
167
+ obj.scored = true;
168
+ score += (obj.blockType==='glass' ? 30 : obj.blockType==='wood' ? 15 : 8);
169
+ updateUi();
170
+ // small tint animation
171
+ scene.tweens.add({ targets: obj, alpha: 0.3, duration: 200, yoyo: true });
172
+ }
173
+ }
174
+ });
175
+ });
176
+ });
177
+
178
+ // camera bounds
179
+ scene.cameras.main.setBounds(0,0, WIDTH*1.5, HEIGHT);
180
+ scene.cameras.main.setZoom(1.0);
181
+ }
182
+
183
+ function update() {
184
+ // nothing heavy here; could check win/lose
185
+ const scene = this;
186
+ // check win: all targets destroyed
187
+ if (targetsGroup.every(t=>t.destroyed)) {
188
+ // level clear
189
+ if (!this._cleared) {
190
+ this._cleared = true;
191
+ scene.cameras.main.fadeOut(600, 255,255,255);
192
+ scene.time.delayedCall(700, ()=> {
193
+ // award stars
194
+ const blocksLeft = blocksGroup.filter(b=>!b.scored).length;
195
+ stars = Math.min(3, Math.max(1, Math.floor(score/100)+1));
196
+ document.getElementById('stars').innerText = stars;
197
+ alert('Level Cleared! Score: '+score+' Stars: '+stars);
198
+ nextLevel(scene);
199
+ });
200
+ }
201
+ }
202
+ // if out of ammo and no current human, show message
203
+ if (ammo<=0 && !currentHuman) {
204
+ // optional: show a small hint
205
+ }
206
+ }
207
+
208
+ /* ---------- Helpers ---------- */
209
+
210
+ function spawnHuman(scene) {
211
+ const type = document.getElementById('hType').value;
212
+ const emoji = '🧑';
213
+ const container = scene.add.container(slingPos.x, slingPos.y);
214
+ const circle = scene.add.circle(0,0,22, 0xffcc80).setStrokeStyle(2,0xdb8b3b);
215
+ const txt = scene.add.text(-10,-16, emoji, { fontSize: '28px' });
216
+ container.add([circle, txt]);
217
+ scene.matter.add.gameObject(container, { shape: { type: 'circle', radius: 22 }, label: 'human' });
218
+ container.setDepth(3);
219
+ container.isHuman = true;
220
+ container.humanType = type;
221
+ // set physics params by type
222
+ const body = container.body;
223
+ body.friction = 0.8;
224
+ body.restitution = (type==='jumper' ? 0.8 : 0.2);
225
+ body.density = (type==='heavy' ? 0.009 : type==='boomer' ? 0.002 : 0.004);
226
+ // special behaviours
227
+ if (type==='jumper') {
228
+ container.onGroundBounce = true;
229
+ }
230
+ if (type==='boomer') {
231
+ // boomer will explode on high impact (handled in collision)
232
+ }
233
+ // mark human as current
234
+ currentHuman = container;
235
+ // small bobbing animation
236
+ scene.tweens.add({ targets: container, y: container.y-6, duration: 600, yoyo:true, repeat:-1 });
237
+ // ensure it collides with world and blocks
238
+ scene.matter.world.setCollisionCategory(0);
239
+ // collisions with blocks
240
+ blocksGroup.forEach(b => scene.matter.add.collider(container, b));
241
+ // collisions with targets
242
+ targetsGroup.forEach(t => scene.matter.add.collider(container, t));
243
+ // update UI
244
+ updateUi();
245
+ }
246
+
247
+ function buildLevel(scene, lvl) {
248
+ // clear old
249
+ blocksGroup.forEach(b=>{ try{ b.destroy(); }catch(e){} });
250
+ targetsGroup.forEach(t=>{ try{ t.destroy(); }catch(e){} });
251
+ blocksGroup = []; targetsGroup = [];
252
+
253
+ // create a simple structure of blocks depending on level
254
+ const baseX = WIDTH - 300;
255
+ const baseY = HEIGHT - 120;
256
+
257
+ const pattern = 2 + (lvl % 3); // complexity
258
+ for (let s=0; s<pattern; s++) {
259
+ const cols = 2 + s;
260
+ const rows = 2 + Math.floor(s/1);
261
+ const startX = baseX + s*70;
262
+ for (let i=0;i<cols;i++){
263
+ for (let j=0;j<rows;j++){
264
+ const x = startX + i*48;
265
+ const y = baseY - j*42;
266
+ const type = (Math.random()<0.15 ? 'metal' : Math.random()<0.4 ? 'glass' : 'wood');
267
+ const color = type==='metal' ? 0x90a4ae : type==='glass' ? 0x81d4fa : 0xffcc80;
268
+ const rect = scene.add.rectangle(x,y,44,38,color).setStrokeStyle(2,0x333333);
269
+ scene.matter.add.gameObject(rect, { shape: { type:'rectangle', width:44, height:38 }});
270
+ rect.isBlock = true; rect.blockType = type; rect.scored = false;
271
+ blocksGroup.push(rect);
272
+ }
273
+ }
274
+ }
275
+
276
+ // add a couple of "targets" (robots)
277
+ for (let k=0;k<Math.min(3, 1+lvl); k++) {
278
+ const tx = baseX + 40 + k*70;
279
+ const ty = baseY - (2+k%2)*42 - 20;
280
+ const container = scene.add.container(tx, ty);
281
+ const body = scene.add.circle(0,0,18,0xa5d6a7).setStrokeStyle(2,0x2e7d32);
282
+ const smile = scene.add.text(-9,-12, '🤖', {fontSize:'26px'});
283
+ container.add([body, smile]);
284
+ scene.matter.add.gameObject(container, { shape: { type: 'circle', radius: 18 }});
285
+ container.isTarget = true; container.destroyed = false;
286
+ targetsGroup.push(container);
287
+ // collision behavior: if high impact -> destroyed
288
+ scene.matter.world.on('collisionactive', (ev) => {
289
+ ev.pairs.forEach(pair => {
290
+ if ((pair.bodyA === container.body || pair.bodyB === container.body)) {
291
+ // check relative speed
292
+ const speed = pair.collision.penetration && Math.hypot(pair.collision.penetration.x, pair.collision.penetration.y) || 0;
293
+ if (speed > 1.1 && !container.destroyed) {
294
+ container.destroyed = true;
295
+ // small explosion
296
+ explodeAt(scene, container.x, container.y);
297
+ try { scene.matter.world.remove(container.body); } catch(e){}
298
+ container.destroy();
299
+ score += 80;
300
+ updateUi();
301
+ }
302
+ }
303
+ });
304
+ });
305
+ }
306
+
307
+ // camera reset
308
+ scene.cameras.main.setScroll(0,0);
309
+ scene.cameras.main.stopFollow();
310
+ }
311
+
312
+ function drawTrajectory(scene, x0, y0, vx, vy) {
313
+ // clear old
314
+ clearTrajectory();
315
+ // simulate points using simple physics approx (not matter sim)
316
+ const g = 1.0 * 60; // pixel/s^2 scale approx
317
+ const steps = 25;
318
+ const dt = 1/12;
319
+ for (let i=0;i<steps;i++){
320
+ const t = i*dt;
321
+ const px = x0 + vx * 60 * t; // 60 to scale to pixels
322
+ const py = y0 + vy * 60 * t + 0.5 * g * t * t;
323
+ const dot = scene.add.circle(px, py, 3, 0x0d47a1).setAlpha(0.6).setDepth(1);
324
+ dottedLines.push(dot);
325
+ }
326
+ }
327
+
328
+ function clearTrajectory() {
329
+ dottedLines.forEach(d=>d.destroy());
330
+ dottedLines = [];
331
+ }
332
+
333
+ function explodeAt(scene, x, y) {
334
+ // particle-ish effect using small circles
335
+ for (let i=0;i<18;i++){
336
+ const p = scene.add.circle(x, y, 4, 0xff8a80);
337
+ scene.tweens.add({ targets: p, x: x + Phaser.Math.Between(-120,120), y: y + Phaser.Math.Between(-120,120), alpha: 0, duration: 500 + Math.random()*400, onComplete: ()=>p.destroy() });
338
+ }
339
+ }
340
+
341
+ function updateUi() {
342
+ document.getElementById('score').innerText = score;
343
+ document.getElementById('ammo').innerText = ammo;
344
+ document.getElementById('stars').innerText = stars;
345
+ }
346
+
347
+ function resetLevel(scene) {
348
+ score = 0; ammo = 5; stars = 0;
349
+ currentHuman = null; isDragging=false; megaLaunchActive=false;
350
+ updateUi();
351
+ // remove all matter children and rebuild scene - easiest: reload page
352
+ window.location.reload();
353
+ }
354
+
355
+ function nextLevel(scene) {
356
+ level += 1; ammo = 5 + Math.min(level, 3);
357
+ score = score + 50; // small bonus
358
+ currentHuman = null;
359
+ buildLevel(scene, level);
360
+ spawnHuman(scene);
361
+ updateUi();
362
+ }
363
+
364
+ </script>
365
+ </body>
366
+ </html>