LukasBe commited on
Commit
19e5b53
·
verified ·
1 Parent(s): 3dbce06

Add 2 files

Browse files
Files changed (2) hide show
  1. index.html +123 -29
  2. prompts.txt +2 -1
index.html CHANGED
@@ -69,6 +69,15 @@
69
  border-radius: 50%;
70
  pointer-events: none;
71
  }
 
 
 
 
 
 
 
 
 
72
  </style>
73
  </head>
74
  <body>
@@ -77,6 +86,7 @@
77
  <h1 class="text-3xl font-bold">🚀 Rocket Launcher</h1>
78
  <p class="text-lg">Drag the flag to set target, then launch!</p>
79
  </div>
 
80
  <div id="flag"></div>
81
  <button id="launch-btn">LAUNCH ROCKET</button>
82
 
@@ -138,10 +148,21 @@
138
  launchPad.receiveShadow = true;
139
  scene.add(launchPad);
140
 
 
 
 
 
 
141
  // Rocket
142
- let rocket;
143
  function createRocket() {
144
  const group = new THREE.Group();
 
 
 
 
 
 
 
145
 
146
  // Rocket body
147
  const bodyGeometry = new THREE.CylinderGeometry(0.5, 0.3, 3, 32);
@@ -218,6 +239,35 @@
218
  return group;
219
  }
220
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  // Flag dragging
222
  const flag = document.getElementById('flag');
223
  let isDragging = false;
@@ -258,35 +308,36 @@
258
 
259
  // Launch rocket
260
  const launchBtn = document.getElementById('launch-btn');
261
- let isRocketFlying = false;
262
- let rocketTarget = new THREE.Vector3(10, 0, 10);
263
- let rocketStartTime = 0;
264
- const flightDuration = 5000; // ms
265
 
266
  launchBtn.addEventListener('click', () => {
267
- if (isRocketFlying) return;
268
-
269
  // Get flag position in 3D world
270
  const flagRect = flag.getBoundingClientRect();
271
  const flagCenterX = flagRect.left + flagRect.width / 2;
272
  const flagCenterY = flagRect.top + flagRect.height / 2;
273
- rocketTarget = screenToWorld(flagCenterX, flagCenterY);
274
 
275
  // Create rocket
276
- if (rocket) scene.remove(rocket);
277
- rocket = createRocket();
 
 
 
 
278
  scene.add(rocket);
 
279
 
280
- isRocketFlying = true;
281
- rocketStartTime = Date.now();
 
282
 
283
  // Animate flame
284
- animateFlame();
285
  });
286
 
287
  // Animate rocket flame
288
- function animateFlame() {
289
- if (!isRocketFlying || !rocket) return;
290
 
291
  const flame = rocket.userData.flame;
292
  if (flame) {
@@ -295,7 +346,7 @@
295
  flame.scale.set(scale, scale, scale);
296
  }
297
 
298
- requestAnimationFrame(animateFlame);
299
  }
300
 
301
  // Create explosion
@@ -386,6 +437,46 @@
386
  animateParticles();
387
  }
388
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
389
  // Animation loop
390
  function animate() {
391
  requestAnimationFrame(animate);
@@ -393,31 +484,34 @@
393
  // Update controls
394
  controls.update();
395
 
396
- // Update rocket flight
397
- if (isRocketFlying && rocket) {
398
- const elapsed = Date.now() - rocketStartTime;
399
- const progress = Math.min(elapsed / flightDuration, 1);
 
 
 
 
400
 
401
  if (progress >= 1) {
402
  // Rocket reached target - explode!
403
  createExplosion(rocket.position);
404
  scene.remove(rocket);
405
- isRocketFlying = false;
406
- rocket = null;
407
  } else {
408
  // Calculate bezier curve path
409
  const startPoint = new THREE.Vector3(0, 0, 0);
410
  const controlPoint1 = new THREE.Vector3(
411
- rocketTarget.x * 0.3,
412
- rocketTarget.y + 30,
413
- rocketTarget.z * 0.3
414
  );
415
  const controlPoint2 = new THREE.Vector3(
416
- rocketTarget.x * 0.7,
417
- rocketTarget.y + 20,
418
- rocketTarget.z * 0.7
419
  );
420
- const endPoint = new THREE.Vector3(rocketTarget.x, rocketTarget.y, rocketTarget.z);
421
 
422
  // Get position on curve
423
  const t = progress;
 
69
  border-radius: 50%;
70
  pointer-events: none;
71
  }
72
+ #counter {
73
+ position: absolute;
74
+ top: 20px;
75
+ right: 20px;
76
+ color: white;
77
+ font-size: 18px;
78
+ text-shadow: 1px 1px 2px black;
79
+ z-index: 100;
80
+ }
81
  </style>
82
  </head>
83
  <body>
 
86
  <h1 class="text-3xl font-bold">🚀 Rocket Launcher</h1>
87
  <p class="text-lg">Drag the flag to set target, then launch!</p>
88
  </div>
89
+ <div id="counter">Rockets launched: <span id="rocket-count">0</span></div>
90
  <div id="flag"></div>
91
  <button id="launch-btn">LAUNCH ROCKET</button>
92
 
 
148
  launchPad.receiveShadow = true;
149
  scene.add(launchPad);
150
 
151
+ // Active rockets and smoke trails
152
+ let activeRockets = [];
153
+ let smokeParticles = [];
154
+ let rocketCount = 0;
155
+
156
  // Rocket
 
157
  function createRocket() {
158
  const group = new THREE.Group();
159
+ group.userData = {
160
+ isFlying: false,
161
+ startTime: 0,
162
+ target: new THREE.Vector3(10, 0, 10),
163
+ lastPosition: new THREE.Vector3(0, 0, 0),
164
+ smokeTrail: []
165
+ };
166
 
167
  // Rocket body
168
  const bodyGeometry = new THREE.CylinderGeometry(0.5, 0.3, 3, 32);
 
239
  return group;
240
  }
241
 
242
+ // Create smoke particle
243
+ function createSmokeParticle(position) {
244
+ const size = 1 + Math.random() * 2;
245
+ const geometry = new THREE.SphereGeometry(size, 8, 8);
246
+ const material = new THREE.MeshStandardMaterial({
247
+ color: 0xeeeeee,
248
+ transparent: true,
249
+ opacity: 0.7,
250
+ roughness: 0.9,
251
+ metalness: 0
252
+ });
253
+
254
+ const particle = new THREE.Mesh(geometry, material);
255
+ particle.position.copy(position);
256
+ particle.userData = {
257
+ createdAt: Date.now(),
258
+ lifeTime: 3000 + Math.random() * 2000, // 3-5 seconds
259
+ velocity: new THREE.Vector3(
260
+ (Math.random() - 0.5) * 0.1,
261
+ Math.random() * 0.05,
262
+ (Math.random() - 0.5) * 0.1
263
+ ),
264
+ growthRate: 0.02 + Math.random() * 0.03
265
+ };
266
+
267
+ scene.add(particle);
268
+ return particle;
269
+ }
270
+
271
  // Flag dragging
272
  const flag = document.getElementById('flag');
273
  let isDragging = false;
 
308
 
309
  // Launch rocket
310
  const launchBtn = document.getElementById('launch-btn');
311
+ const rocketCountElement = document.getElementById('rocket-count');
 
 
 
312
 
313
  launchBtn.addEventListener('click', () => {
 
 
314
  // Get flag position in 3D world
315
  const flagRect = flag.getBoundingClientRect();
316
  const flagCenterX = flagRect.left + flagRect.width / 2;
317
  const flagCenterY = flagRect.top + flagRect.height / 2;
318
+ const target = screenToWorld(flagCenterX, flagCenterY);
319
 
320
  // Create rocket
321
+ const rocket = createRocket();
322
+ rocket.userData.isFlying = true;
323
+ rocket.userData.startTime = Date.now();
324
+ rocket.userData.target = target;
325
+ rocket.userData.lastPosition = new THREE.Vector3(0, 0, 0);
326
+
327
  scene.add(rocket);
328
+ activeRockets.push(rocket);
329
 
330
+ // Update counter
331
+ rocketCount++;
332
+ rocketCountElement.textContent = rocketCount;
333
 
334
  // Animate flame
335
+ animateFlame(rocket);
336
  });
337
 
338
  // Animate rocket flame
339
+ function animateFlame(rocket) {
340
+ if (!rocket.userData.isFlying) return;
341
 
342
  const flame = rocket.userData.flame;
343
  if (flame) {
 
346
  flame.scale.set(scale, scale, scale);
347
  }
348
 
349
+ requestAnimationFrame(() => animateFlame(rocket));
350
  }
351
 
352
  // Create explosion
 
437
  animateParticles();
438
  }
439
 
440
+ // Update smoke particles
441
+ function updateSmokeParticles() {
442
+ const now = Date.now();
443
+
444
+ // Update existing smoke particles
445
+ for (let i = smokeParticles.length - 1; i >= 0; i--) {
446
+ const particle = smokeParticles[i];
447
+ const age = now - particle.userData.createdAt;
448
+
449
+ if (age > particle.userData.lifeTime) {
450
+ // Remove expired particles
451
+ scene.remove(particle);
452
+ smokeParticles.splice(i, 1);
453
+ } else {
454
+ // Update position and size
455
+ particle.position.x += particle.userData.velocity.x;
456
+ particle.position.y += particle.userData.velocity.y;
457
+ particle.position.z += particle.userData.velocity.z;
458
+
459
+ // Grow over time
460
+ const scale = 1 + (particle.userData.growthRate * age / 1000);
461
+ particle.scale.set(scale, scale, scale);
462
+
463
+ // Fade out
464
+ particle.material.opacity = 0.7 * (1 - (age / particle.userData.lifeTime));
465
+ }
466
+ }
467
+
468
+ // Add new smoke particles for each rocket
469
+ for (const rocket of activeRockets) {
470
+ if (rocket.userData.isFlying && rocket.position.y > 1) {
471
+ // Only add smoke when rocket is above ground
472
+ if (Math.random() < 0.3) { // Control density of smoke trail
473
+ const smokeParticle = createSmokeParticle(rocket.position.clone());
474
+ smokeParticles.push(smokeParticle);
475
+ }
476
+ }
477
+ }
478
+ }
479
+
480
  // Animation loop
481
  function animate() {
482
  requestAnimationFrame(animate);
 
484
  // Update controls
485
  controls.update();
486
 
487
+ // Update smoke particles
488
+ updateSmokeParticles();
489
+
490
+ // Update all active rockets
491
+ for (let i = activeRockets.length - 1; i >= 0; i--) {
492
+ const rocket = activeRockets[i];
493
+ const elapsed = Date.now() - rocket.userData.startTime;
494
+ const progress = Math.min(elapsed / 5000, 1); // 5 second flight duration
495
 
496
  if (progress >= 1) {
497
  // Rocket reached target - explode!
498
  createExplosion(rocket.position);
499
  scene.remove(rocket);
500
+ activeRockets.splice(i, 1);
 
501
  } else {
502
  // Calculate bezier curve path
503
  const startPoint = new THREE.Vector3(0, 0, 0);
504
  const controlPoint1 = new THREE.Vector3(
505
+ rocket.userData.target.x * 0.3,
506
+ rocket.userData.target.y + 30,
507
+ rocket.userData.target.z * 0.3
508
  );
509
  const controlPoint2 = new THREE.Vector3(
510
+ rocket.userData.target.x * 0.7,
511
+ rocket.userData.target.y + 20,
512
+ rocket.userData.target.z * 0.7
513
  );
514
+ const endPoint = rocket.userData.target.clone();
515
 
516
  // Get position on curve
517
  const t = progress;
prompts.txt CHANGED
@@ -1 +1,2 @@
1
- Create and amazing 3d threejs based rocket laucning toy, the user can drag a flag over the screen, then then launch great looking 3d procedural detailed rocket that flies in indirect interesting bezier path slowly to the flag where it exploded in a beaturiful particle based smoke,fire and sparks ...
 
 
1
+ Create and amazing 3d threejs based rocket laucning toy, the user can drag a flag over the screen, then then launch great looking 3d procedural detailed rocket that flies in indirect interesting bezier path slowly to the flag where it exploded in a beaturiful particle based smoke,fire and sparks ...
2
+ Allow to launch unlimited number of rockets. Make the rocket leave a white puffy smoke particle trail that slowly disappears.