dricampbell commited on
Commit
971c2f9
·
verified ·
1 Parent(s): de5d341

Add 1 files

Browse files
Files changed (1) hide show
  1. index.html +211 -20
index.html CHANGED
@@ -259,6 +259,7 @@
259
  let diceObjects = [];
260
  let diceMeshes = [];
261
  let diceValues = {};
 
262
 
263
  // Initialize Three.js and Cannon.js
264
  function init() {
@@ -273,6 +274,9 @@
273
  // Add directional light
274
  const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
275
  directionalLight.position.set(1, 1, 1).normalize();
 
 
 
276
  scene.add(directionalLight);
277
 
278
  // Add point light
@@ -323,10 +327,37 @@
323
  // Handle window resize
324
  window.addEventListener('resize', onWindowResize);
325
 
 
 
 
 
 
 
326
  // Start animation loop
327
  animate();
328
  }
329
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
330
  // Add decorative elements to the scene
331
  function addDecorativeElements() {
332
  // Add some floating runes
@@ -346,25 +377,6 @@
346
  );
347
  scene.add(rune);
348
  }
349
-
350
- // Add some floating particles
351
- const particlesGeometry = new THREE.BufferGeometry();
352
- const particlesCount = 100;
353
- const posArray = new Float32Array(particlesCount * 3);
354
-
355
- for (let i = 0; i < particlesCount * 3; i++) {
356
- posArray[i] = (Math.random() - 0.5) * 20;
357
- }
358
-
359
- particlesGeometry.setAttribute('position', new THREE.BufferAttribute(posArray, 3));
360
- const particlesMaterial = new THREE.PointsMaterial({
361
- color: 0x8b5a2b,
362
- size: 0.05,
363
- transparent: true,
364
- opacity: 0.5
365
- });
366
- const particlesMesh = new THREE.Points(particlesGeometry, particlesMaterial);
367
- scene.add(particlesMesh);
368
  }
369
 
370
  // Handle window resize
@@ -501,5 +513,184 @@
501
  case 8:
502
  color = 0x005b96; // Blue
503
  break;
504
- case
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
505
  </html>
 
259
  let diceObjects = [];
260
  let diceMeshes = [];
261
  let diceValues = {};
262
+ let isRolling = false;
263
 
264
  // Initialize Three.js and Cannon.js
265
  function init() {
 
274
  // Add directional light
275
  const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
276
  directionalLight.position.set(1, 1, 1).normalize();
277
+ directionalLight.castShadow = true;
278
+ directionalLight.shadow.mapSize.width = 1024;
279
+ directionalLight.shadow.mapSize.height = 1024;
280
  scene.add(directionalLight);
281
 
282
  // Add point light
 
327
  // Handle window resize
328
  window.addEventListener('resize', onWindowResize);
329
 
330
+ // Set up dice selection
331
+ setupDiceSelection();
332
+
333
+ // Set up roll button
334
+ document.getElementById('rollButton').addEventListener('click', rollDice);
335
+
336
  // Start animation loop
337
  animate();
338
  }
339
 
340
+ // Set up dice selection
341
+ function setupDiceSelection() {
342
+ const diceSelectors = document.querySelectorAll('.dice-selector');
343
+
344
+ diceSelectors.forEach(selector => {
345
+ selector.addEventListener('click', function() {
346
+ // Remove active class from all selectors
347
+ diceSelectors.forEach(s => s.classList.remove('active'));
348
+
349
+ // Add active class to clicked selector
350
+ this.classList.add('active');
351
+
352
+ // Update selected sides
353
+ selectedSides = parseInt(this.getAttribute('data-sides'));
354
+ });
355
+ });
356
+
357
+ // Activate D20 by default
358
+ document.querySelector('.dice-selector[data-sides="20"]').classList.add('active');
359
+ }
360
+
361
  // Add decorative elements to the scene
362
  function addDecorativeElements() {
363
  // Add some floating runes
 
377
  );
378
  scene.add(rune);
379
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
380
  }
381
 
382
  // Handle window resize
 
513
  case 8:
514
  color = 0x005b96; // Blue
515
  break;
516
+ case 10:
517
+ color = 0x5e8c31; // Green
518
+ break;
519
+ case 12:
520
+ color = 0x7d26cd; // Purple
521
+ break;
522
+ case 20:
523
+ color = 0xd4af37; // Gold
524
+ break;
525
+ default:
526
+ color = 0xffffff; // White
527
+ }
528
+
529
+ return new THREE.MeshStandardMaterial({
530
+ color: color,
531
+ roughness: 0.3,
532
+ metalness: 0.5,
533
+ emissive: color,
534
+ emissiveIntensity: 0.1
535
+ });
536
+ }
537
+
538
+ // Roll the dice
539
+ function rollDice() {
540
+ if (isRolling) return;
541
+
542
+ isRolling = true;
543
+
544
+ // Clear previous dice
545
+ clearDice();
546
+
547
+ // Get quantity
548
+ const quantity = parseInt(document.getElementById('diceQuantity').value) || 1;
549
+ const modifier = parseInt(document.getElementById('diceModifier').value) || 0;
550
+
551
+ // Hide result display
552
+ document.getElementById('resultDisplay').classList.add('hidden');
553
+ document.getElementById('criticalText').classList.add('hidden');
554
+
555
+ // Create new dice
556
+ for (let i = 0; i < quantity; i++) {
557
+ // Position the dice in a line above the ground
558
+ const x = (i - (quantity - 1) / 2) * 2;
559
+ const position = new CANNON.Vec3(x, 5, 0);
560
+
561
+ // Create physics body
562
+ const body = createDiceBody(selectedSides, position);
563
+
564
+ // Add some random force to make it roll
565
+ body.velocity.set(
566
+ Math.random() * 5 - 2.5,
567
+ Math.random() * 2,
568
+ Math.random() * 5 - 2.5
569
+ );
570
+
571
+ body.angularVelocity.set(
572
+ Math.random() * 5,
573
+ Math.random() * 5,
574
+ Math.random() * 5
575
+ );
576
+
577
+ world.addBody(body);
578
+ diceObjects.push(body);
579
+
580
+ // Create visual mesh
581
+ const geometry = createDiceGeometry(selectedSides);
582
+ const material = createDiceMaterial(selectedSides);
583
+ const mesh = new THREE.Mesh(geometry, material);
584
+ mesh.castShadow = true;
585
+ mesh.receiveShadow = true;
586
+ scene.add(mesh);
587
+ diceMeshes.push(mesh);
588
+ }
589
+
590
+ // Wait for dice to settle
591
+ setTimeout(() => {
592
+ checkDiceResults(quantity, modifier);
593
+ }, 2000);
594
+ }
595
+
596
+ // Clear all dice from scene
597
+ function clearDice() {
598
+ // Remove physics bodies
599
+ diceObjects.forEach(body => {
600
+ world.removeBody(body);
601
+ });
602
+
603
+ // Remove meshes
604
+ diceMeshes.forEach(mesh => {
605
+ scene.remove(mesh);
606
+ if (mesh.geometry) mesh.geometry.dispose();
607
+ if (mesh.material) mesh.material.dispose();
608
+ });
609
+
610
+ diceObjects = [];
611
+ diceMeshes = [];
612
+ diceValues = {};
613
+ }
614
+
615
+ // Check dice results after they've settled
616
+ function checkDiceResults(quantity, modifier) {
617
+ const results = [];
618
+ let total = 0;
619
+ let isCritical = false;
620
+
621
+ // Generate random results (since we can't actually detect dice faces in this simplified version)
622
+ for (let i = 0; i < quantity; i++) {
623
+ const value = Math.floor(Math.random() * selectedSides) + 1;
624
+ results.push(value);
625
+ total += value;
626
+
627
+ // Check for critical (20 on d20)
628
+ if (selectedSides === 20 && value === 20) {
629
+ isCritical = true;
630
+ }
631
+ }
632
+
633
+ // Add modifier
634
+ total += modifier;
635
+
636
+ // Display results
637
+ displayResults(results, total, modifier, isCritical);
638
+
639
+ // Add to history
640
+ addToHistory(results, total, modifier);
641
+
642
+ isRolling = false;
643
+ }
644
+
645
+ // Display the results
646
+ function displayResults(results, total, modifier, isCritical) {
647
+ const resultDisplay = document.getElementById('resultDisplay');
648
+ const totalResult = document.getElementById('totalResult');
649
+ const individualResults = document.getElementById('individualResults');
650
+ const criticalText = document.getElementById('criticalText');
651
+
652
+ // Show total
653
+ totalResult.textContent = total;
654
+
655
+ // Show individual results
656
+ let individualText = `Rolls: ${results.join(', ')}`;
657
+ if (modifier !== 0) {
658
+ individualText += ` + ${modifier}`;
659
+ }
660
+ individualResults.textContent = individualText;
661
+
662
+ // Show critical if applicable
663
+ if (isCritical) {
664
+ criticalText.classList.remove('hidden');
665
+ }
666
+
667
+ // Show the display
668
+ resultDisplay.classList.remove('hidden');
669
+ }
670
+
671
+ // Add roll to history
672
+ function addToHistory(results, total, modifier) {
673
+ const historyContainer = document.getElementById('rollHistory');
674
+ const historyItem = document.createElement('div');
675
+ historyItem.className = 'roll-history-item p-3 bg-gray-800 rounded';
676
+
677
+ let historyText = `D${selectedSides}: ${results.join(' + ')}`;
678
+ if (modifier !== 0) {
679
+ historyText += ` + ${modifier}`;
680
+ }
681
+ historyText += ` = ${total}`;
682
+
683
+ historyItem.textContent = historyText;
684
+ historyContainer.insertBefore(historyItem, historyContainer.firstChild);
685
+
686
+ // Limit history to 10 items
687
+ if (historyContainer.children.length > 10) {
688
+ historyContainer.removeChild(historyContainer.lastChild);
689
+ }
690
+ }
691
+
692
+ // Initialize when DOM is loaded
693
+ document.addEventListener('DOMContentLoaded', init);
694
+ </script>
695
+ <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=dricampbell/d-d-dice" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
696
  </html>