@@ -578,109 +578,198 @@ export function createBootHouse(gradientMap) { |
| 578 | // Sprite body colors | 578 | // Sprite body colors |
| 579 | const spriteColors = [0xff6b9d, 0x9b59b6, 0x3498db, 0x2ecc71] | 579 | const spriteColors = [0xff6b9d, 0x9b59b6, 0x3498db, 0x2ecc71] |
| 580 | | 580 | |
| 581 | - // === BOOT STRUCTURE === | 581 | + // === BOOT STRUCTURE (Continuous realistic boot shape) === |
| 582 | - | 582 | + |
| 583 | - // Boot sole (the base) | 583 | + // The boot is built as overlapping shapes with the same material |
| 584 | - const soleGeom = new THREE.BoxGeometry(1.0, 0.12, 0.6) | 584 | + // to create a seamless, continuous appearance |
| 585 | - soleGeom.translate(0.1, 0, 0) // Offset for toe curve | 585 | + |
| 586 | - const sole = new THREE.Mesh(soleGeom, soleMaterial) | 586 | + // --- SOLE (follows the boot footprint) --- |
| 587 | - sole.position.y = 0.06 | 587 | + // Main sole - elongated with rounded ends |
| 588 | - group.add(sole) | 588 | + const soleLength = 1.1 |
| 589 | - | 589 | + const soleWidth = 0.5 |
| 590 | - // Toe section - curved front of boot (rounded box) | 590 | + const soleHeight = 0.1 |
| 591 | - const toeGeom = new THREE.SphereGeometry(0.35, 10, 8) | 591 | + |
| 592 | - toeGeom.scale(1.2, 0.7, 1.0) | 592 | + // Sole base |
| 593 | - const toe = new THREE.Mesh(toeGeom, leatherMaterial) | 593 | + const soleBaseGeom = new THREE.BoxGeometry(soleLength - 0.3, soleHeight, soleWidth - 0.1) |
| 594 | - toe.position.set(-0.35, 0.25, 0) | 594 | + const soleBase = new THREE.Mesh(soleBaseGeom, soleMaterial) |
| 595 | - group.add(toe) | 595 | + soleBase.position.set(0, soleHeight / 2, 0) |
| 596 | - | 596 | + group.add(soleBase) |
| 597 | - // Main boot body (the ankle/shaft part) - this is the house | 597 | + |
| 598 | - const shaftGeom = new THREE.CylinderGeometry(0.32, 0.38, 0.9, 10) | 598 | + // Sole toe cap (rounded front) |
| | 599 | + const soleToeGeom = new THREE.CylinderGeometry(soleWidth / 2 - 0.05, soleWidth / 2 - 0.05, soleHeight, 12) |
| | 600 | + soleToeGeom.rotateX(Math.PI / 2) |
| | 601 | + const soleToe = new THREE.Mesh(soleToeGeom, soleMaterial) |
| | 602 | + soleToe.position.set(-soleLength / 2 + 0.15, soleHeight / 2, 0) |
| | 603 | + group.add(soleToe) |
| | 604 | + |
| | 605 | + // Sole heel cap (rounded back) |
| | 606 | + const soleHeelGeom = new THREE.CylinderGeometry(soleWidth / 2 - 0.05, soleWidth / 2 - 0.05, soleHeight * 1.3, 12) |
| | 607 | + soleHeelGeom.rotateX(Math.PI / 2) |
| | 608 | + const soleHeel = new THREE.Mesh(soleHeelGeom, soleMaterial) |
| | 609 | + soleHeel.position.set(soleLength / 2 - 0.2, soleHeight * 0.65, 0) |
| | 610 | + group.add(soleHeel) |
| | 611 | + |
| | 612 | + // --- FOOT PORTION (continuous with ankle) --- |
| | 613 | + |
| | 614 | + // Lower foot - the part that sits on the sole |
| | 615 | + // Uses a squashed capsule shape tilted up at the toe |
| | 616 | + const footBaseGeom = new THREE.CapsuleGeometry(0.22, 0.5, 8, 12) |
| | 617 | + footBaseGeom.rotateZ(Math.PI / 2) // Lay it horizontal |
| | 618 | + footBaseGeom.scale(1, 0.75, 1) // Flatten slightly |
| | 619 | + const footBase = new THREE.Mesh(footBaseGeom, leatherMaterial) |
| | 620 | + footBase.position.set(-0.1, 0.28, 0) |
| | 621 | + footBase.rotation.z = -0.15 // Tilt toe up slightly |
| | 622 | + group.add(footBase) |
| | 623 | + |
| | 624 | + // Toe box - rounded front that curves upward |
| | 625 | + const toeBoxGeom = new THREE.SphereGeometry(0.28, 12, 10) |
| | 626 | + toeBoxGeom.scale(0.9, 0.85, 1.0) |
| | 627 | + const toeBox = new THREE.Mesh(toeBoxGeom, leatherMaterial) |
| | 628 | + toeBox.position.set(-0.48, 0.26, 0) |
| | 629 | + group.add(toeBox) |
| | 630 | + |
| | 631 | + // --- ANKLE/SHAFT (rises from heel, connects to foot) --- |
| | 632 | + |
| | 633 | + // Ankle transition - connects foot to shaft smoothly |
| | 634 | + const ankleTransitionGeom = new THREE.SphereGeometry(0.34, 12, 10) |
| | 635 | + ankleTransitionGeom.scale(1.0, 0.8, 1.0) |
| | 636 | + const ankleTransition = new THREE.Mesh(ankleTransitionGeom, leatherMaterial) |
| | 637 | + ankleTransition.position.set(0.25, 0.35, 0) |
| | 638 | + group.add(ankleTransition) |
| | 639 | + |
| | 640 | + // Main shaft (ankle part) - tapers slightly upward |
| | 641 | + const shaftGeom = new THREE.CylinderGeometry(0.28, 0.34, 0.75, 14) |
| 599 | const shaft = new THREE.Mesh(shaftGeom, leatherMaterial) | 642 | const shaft = new THREE.Mesh(shaftGeom, leatherMaterial) |
| 600 | - shaft.position.set(0.25, 0.6, 0) | 643 | + shaft.position.set(0.25, 0.72, 0) |
| 601 | group.add(shaft) | 644 | group.add(shaft) |
| 602 | | 645 | |
| 603 | - // Boot rim/collar at top | 646 | + // Shaft top rim |
| 604 | - const rimGeom = new THREE.TorusGeometry(0.34, 0.05, 6, 16) | 647 | + const shaftTopGeom = new THREE.TorusGeometry(0.30, 0.04, 8, 20) |
| 605 | - const rim = new THREE.Mesh(rimGeom, darkLeatherMaterial) | 648 | + const shaftTop = new THREE.Mesh(shaftTopGeom, leatherMaterial) |
| 606 | - rim.position.set(0.25, 1.05, 0) | 649 | + shaftTop.position.set(0.25, 1.1, 0) |
| 607 | - rim.rotation.x = Math.PI / 2 | 650 | + shaftTop.rotation.x = Math.PI / 2 |
| 608 | - group.add(rim) | 651 | + group.add(shaftTop) |
| 609 | - | 652 | + |
| 610 | - // Tongue (extending from shaft toward toe) | 653 | + // --- INSTEP/VAMP (connects toe to ankle on top) --- |
| 611 | - const tongueGeom = new THREE.BoxGeometry(0.18, 0.4, 0.08) | 654 | + |
| | 655 | + // This fills the gap between toe and shaft on top of the foot |
| | 656 | + const vampGeom = new THREE.CapsuleGeometry(0.18, 0.35, 6, 10) |
| | 657 | + vampGeom.rotateZ(Math.PI / 2) |
| | 658 | + vampGeom.scale(1, 0.7, 0.9) |
| | 659 | + const vamp = new THREE.Mesh(vampGeom, leatherMaterial) |
| | 660 | + vamp.position.set(-0.08, 0.38, 0) |
| | 661 | + vamp.rotation.z = -0.4 // Angle down toward toe |
| | 662 | + group.add(vamp) |
| | 663 | + |
| | 664 | + // --- HEEL COUNTER (back of heel, reinforcement) --- |
| | 665 | + const heelCounterGeom = new THREE.CylinderGeometry(0.26, 0.3, 0.25, 14, 1, false, -Math.PI * 0.6, Math.PI * 1.2) |
| | 666 | + const heelCounter = new THREE.Mesh(heelCounterGeom, darkLeatherMaterial) |
| | 667 | + heelCounter.position.set(0.35, 0.22, 0) |
| | 668 | + group.add(heelCounter) |
| | 669 | + |
| | 670 | + // --- TONGUE --- |
| | 671 | + const tongueGeom = new THREE.CapsuleGeometry(0.08, 0.25, 4, 8) |
| 612 | const tongue = new THREE.Mesh(tongueGeom, laceMaterial) | 672 | const tongue = new THREE.Mesh(tongueGeom, laceMaterial) |
| 613 | - tongue.position.set(0.05, 0.5, 0.32) | 673 | + tongue.position.set(0.0, 0.55, 0.26) |
| 614 | - tongue.rotation.x = 0.3 | 674 | + tongue.rotation.x = 0.35 |
| | 675 | + tongue.rotation.z = -0.1 |
| 615 | group.add(tongue) | 676 | group.add(tongue) |
| 616 | | 677 | |
| 617 | - // Lace holes (decorative dots) | 678 | + // --- LACING DETAILS --- |
| 618 | - const holeGeom = new THREE.CylinderGeometry(0.025, 0.025, 0.02, 8) | | |
| 619 | - for (let i = 0; i < 4; i++) { | | |
| 620 | - const holeL = new THREE.Mesh(holeGeom, soleMaterial) | | |
| 621 | - holeL.position.set(-0.05, 0.35 + i * 0.15, 0.36) | | |
| 622 | - holeL.rotation.x = Math.PI / 2 | | |
| 623 | - group.add(holeL) | | |
| 624 | - | | |
| 625 | - const holeR = new THREE.Mesh(holeGeom, soleMaterial) | | |
| 626 | - holeR.position.set(0.15, 0.35 + i * 0.15, 0.36) | | |
| 627 | - holeR.rotation.x = Math.PI / 2 | | |
| 628 | - group.add(holeR) | | |
| 629 | - } | | |
| 630 | - | | |
| 631 | - // Cross-laces between holes | | |
| 632 | const laceCordMaterial = new THREE.MeshToonMaterial({ | 679 | const laceCordMaterial = new THREE.MeshToonMaterial({ |
| 633 | color: 0xf5deb3, | 680 | color: 0xf5deb3, |
| 634 | gradientMap | 681 | gradientMap |
| 635 | }) | 682 | }) |
| | 683 | + |
| | 684 | + // Lace eyelets (holes) |
| | 685 | + const eyeletGeom = new THREE.TorusGeometry(0.025, 0.008, 6, 12) |
| | 686 | + for (let i = 0; i < 4; i++) { |
| | 687 | + const y = 0.42 + i * 0.12 |
| | 688 | + const z = 0.28 - i * 0.02 |
| | 689 | + |
| | 690 | + const eyeletL = new THREE.Mesh(eyeletGeom, darkLeatherMaterial) |
| | 691 | + eyeletL.position.set(-0.06, y, z) |
| | 692 | + eyeletL.rotation.x = Math.PI / 2 - 0.3 |
| | 693 | + group.add(eyeletL) |
| | 694 | + |
| | 695 | + const eyeletR = new THREE.Mesh(eyeletGeom, darkLeatherMaterial) |
| | 696 | + eyeletR.position.set(0.08, y, z) |
| | 697 | + eyeletR.rotation.x = Math.PI / 2 - 0.3 |
| | 698 | + group.add(eyeletR) |
| | 699 | + } |
| | 700 | + |
| | 701 | + // Cross-laces |
| 636 | for (let i = 0; i < 3; i++) { | 702 | for (let i = 0; i < 3; i++) { |
| 637 | - const cordGeom = new THREE.CylinderGeometry(0.01, 0.01, 0.22, 4) | 703 | + const y = 0.48 + i * 0.12 |
| | 704 | + const z = 0.30 - i * 0.02 |
| | 705 | + const cordGeom = new THREE.CylinderGeometry(0.008, 0.008, 0.16, 4) |
| 638 | const cord = new THREE.Mesh(cordGeom, laceCordMaterial) | 706 | const cord = new THREE.Mesh(cordGeom, laceCordMaterial) |
| 639 | - cord.position.set(0.05, 0.42 + i * 0.15, 0.37) | 707 | + cord.position.set(0.01, y, z) |
| 640 | cord.rotation.z = Math.PI / 2 | 708 | cord.rotation.z = Math.PI / 2 |
| 641 | - cord.rotation.x = 0.3 | 709 | + cord.rotation.y = 0.3 |
| 642 | group.add(cord) | 710 | group.add(cord) |
| 643 | } | 711 | } |
| 644 | | 712 | |
| 645 | - // Heel bump | 713 | + // Bow at top of lacing |
| 646 | - const heelGeom = new THREE.SphereGeometry(0.18, 8, 6) | 714 | + const bowLoopGeom = new THREE.TorusGeometry(0.04, 0.012, 6, 12, Math.PI) |
| 647 | - heelGeom.scale(1.0, 0.8, 0.6) | 715 | + const bowL = new THREE.Mesh(bowLoopGeom, laceCordMaterial) |
| 648 | - const heel = new THREE.Mesh(heelGeom, soleMaterial) | 716 | + bowL.position.set(-0.04, 0.82, 0.24) |
| 649 | - heel.position.set(0.55, 0.1, 0) | 717 | + bowL.rotation.y = Math.PI / 2 |
| 650 | - group.add(heel) | 718 | + bowL.rotation.x = 0.5 |
| | 719 | + group.add(bowL) |
| | 720 | + |
| | 721 | + const bowR = new THREE.Mesh(bowLoopGeom, laceCordMaterial) |
| | 722 | + bowR.position.set(0.06, 0.82, 0.24) |
| | 723 | + bowR.rotation.y = -Math.PI / 2 |
| | 724 | + bowR.rotation.x = 0.5 |
| | 725 | + group.add(bowR) |
| | 726 | + |
| | 727 | + // Bow tails |
| | 728 | + const tailGeom = new THREE.CylinderGeometry(0.01, 0.006, 0.12, 4) |
| | 729 | + const tailL = new THREE.Mesh(tailGeom, laceCordMaterial) |
| | 730 | + tailL.position.set(-0.06, 0.76, 0.26) |
| | 731 | + tailL.rotation.z = 0.4 |
| | 732 | + tailL.rotation.x = 0.3 |
| | 733 | + group.add(tailL) |
| | 734 | + |
| | 735 | + const tailR = new THREE.Mesh(tailGeom, laceCordMaterial) |
| | 736 | + tailR.position.set(0.08, 0.76, 0.26) |
| | 737 | + tailR.rotation.z = -0.4 |
| | 738 | + tailR.rotation.x = 0.3 |
| | 739 | + group.add(tailR) |
| 651 | | 740 | |
| 652 | // === WINDOWS === | 741 | // === WINDOWS === |
| 653 | | 742 | |
| 654 | // Round window on toe | 743 | // Round window on toe |
| 655 | - const toeWindowGeom = new THREE.CircleGeometry(0.08, 10) | 744 | + const toeWindowGeom = new THREE.CircleGeometry(0.07, 12) |
| 656 | const toeWindow = new THREE.Mesh(toeWindowGeom, windowMaterial) | 745 | const toeWindow = new THREE.Mesh(toeWindowGeom, windowMaterial) |
| 657 | - toeWindow.position.set(-0.58, 0.3, 0) | 746 | + toeWindow.position.set(-0.72, 0.28, 0) |
| 658 | toeWindow.rotation.y = -Math.PI / 2 | 747 | toeWindow.rotation.y = -Math.PI / 2 |
| 659 | group.add(toeWindow) | 748 | group.add(toeWindow) |
| 660 | | 749 | |
| 661 | // Window frame | 750 | // Window frame |
| 662 | - const toeFrameGeom = new THREE.TorusGeometry(0.08, 0.015, 4, 16) | 751 | + const toeFrameGeom = new THREE.TorusGeometry(0.07, 0.012, 4, 16) |
| 663 | const toeFrame = new THREE.Mesh(toeFrameGeom, darkLeatherMaterial) | 752 | const toeFrame = new THREE.Mesh(toeFrameGeom, darkLeatherMaterial) |
| 664 | - toeFrame.position.set(-0.57, 0.3, 0) | 753 | + toeFrame.position.set(-0.71, 0.28, 0) |
| 665 | toeFrame.rotation.y = -Math.PI / 2 | 754 | toeFrame.rotation.y = -Math.PI / 2 |
| 666 | group.add(toeFrame) | 755 | group.add(toeFrame) |
| 667 | | 756 | |
| 668 | - // Windows on shaft (2 small ones) | 757 | + // Windows on shaft (2 on sides) |
| 669 | for (let i = 0; i < 2; i++) { | 758 | for (let i = 0; i < 2; i++) { |
| 670 | - const angle = (i === 0) ? Math.PI * 0.7 : -Math.PI * 0.7 | 759 | + const angle = (i === 0) ? Math.PI * 0.65 : -Math.PI * 0.65 |
| 671 | - const wx = 0.25 + Math.sin(angle) * 0.33 | 760 | + const wx = 0.25 + Math.sin(angle) * 0.29 |
| 672 | - const wz = Math.cos(angle) * 0.33 | 761 | + const wz = Math.cos(angle) * 0.29 |
| 673 | | 762 | |
| 674 | - const shaftWindowGeom = new THREE.PlaneGeometry(0.12, 0.15) | 763 | + const shaftWindowGeom = new THREE.CircleGeometry(0.06, 10) |
| 675 | const shaftWindow = new THREE.Mesh(shaftWindowGeom, windowMaterial) | 764 | const shaftWindow = new THREE.Mesh(shaftWindowGeom, windowMaterial) |
| 676 | - shaftWindow.position.set(wx, 0.6, wz) | 765 | + shaftWindow.position.set(wx, 0.7, wz) |
| 677 | shaftWindow.rotation.y = angle + Math.PI | 766 | shaftWindow.rotation.y = angle + Math.PI |
| 678 | group.add(shaftWindow) | 767 | group.add(shaftWindow) |
| 679 | | 768 | |
| 680 | // Frame | 769 | // Frame |
| 681 | - const frameGeom = new THREE.BoxGeometry(0.14, 0.17, 0.02) | 770 | + const frameGeom = new THREE.TorusGeometry(0.06, 0.01, 4, 12) |
| 682 | const frame = new THREE.Mesh(frameGeom, darkLeatherMaterial) | 771 | const frame = new THREE.Mesh(frameGeom, darkLeatherMaterial) |
| 683 | - frame.position.set(wx, 0.6, wz) | 772 | + frame.position.set(wx, 0.7, wz) |
| 684 | frame.rotation.y = angle + Math.PI | 773 | frame.rotation.y = angle + Math.PI |
| 685 | group.add(frame) | 774 | group.add(frame) |
| 686 | } | 775 | } |
@@ -743,34 +832,36 @@ export function createBootHouse(gradientMap) { |
| 743 | } | 832 | } |
| 744 | chimneyGroup.add(smokeGroup) | 833 | chimneyGroup.add(smokeGroup) |
| 745 | | 834 | |
| 746 | - chimneyGroup.position.set(0.1, 1.0, -0.15) | 835 | + chimneyGroup.position.set(0.15, 1.1, -0.12) |
| 747 | group.add(chimneyGroup) | 836 | group.add(chimneyGroup) |
| 748 | | 837 | |
| 749 | // === DOOR === | 838 | // === DOOR === |
| 750 | | 839 | |
| 751 | const doorGroup = new THREE.Group() | 840 | const doorGroup = new THREE.Group() |
| 752 | | 841 | |
| 753 | - // Arched door on the toe | 842 | + // Arched door on the side of the toe/vamp area |
| 754 | - const doorGeom = new THREE.BoxGeometry(0.15, 0.25, 0.03) | 843 | + const doorGeom = new THREE.BoxGeometry(0.12, 0.22, 0.03) |
| 755 | const door = new THREE.Mesh(doorGeom, darkLeatherMaterial) | 844 | const door = new THREE.Mesh(doorGeom, darkLeatherMaterial) |
| 756 | - door.position.y = 0.125 | 845 | + door.position.y = 0.11 |
| 757 | doorGroup.add(door) | 846 | doorGroup.add(door) |
| 758 | | 847 | |
| 759 | // Door arch | 848 | // Door arch |
| 760 | - const doorArchGeom = new THREE.SphereGeometry(0.075, 8, 4, 0, Math.PI * 2, 0, Math.PI / 2) | 849 | + const doorArchGeom = new THREE.SphereGeometry(0.06, 8, 4, 0, Math.PI * 2, 0, Math.PI / 2) |
| 761 | const doorArch = new THREE.Mesh(doorArchGeom, darkLeatherMaterial) | 850 | const doorArch = new THREE.Mesh(doorArchGeom, darkLeatherMaterial) |
| 762 | - doorArch.position.y = 0.25 | 851 | + doorArch.position.y = 0.22 |
| 763 | doorArch.rotation.x = Math.PI | 852 | doorArch.rotation.x = Math.PI |
| 764 | doorGroup.add(doorArch) | 853 | doorGroup.add(doorArch) |
| 765 | | 854 | |
| 766 | // Door knob | 855 | // Door knob |
| 767 | - const knobGeom = new THREE.SphereGeometry(0.018, 6, 4) | 856 | + const knobGeom = new THREE.SphereGeometry(0.015, 6, 4) |
| 768 | const knobMat = new THREE.MeshToonMaterial({ color: 0xffd700, gradientMap }) | 857 | const knobMat = new THREE.MeshToonMaterial({ color: 0xffd700, gradientMap }) |
| 769 | const knob = new THREE.Mesh(knobGeom, knobMat) | 858 | const knob = new THREE.Mesh(knobGeom, knobMat) |
| 770 | - knob.position.set(0.05, 0.12, 0.02) | 859 | + knob.position.set(0.04, 0.1, 0.02) |
| 771 | doorGroup.add(knob) | 860 | doorGroup.add(knob) |
| 772 | | 861 | |
| 773 | - doorGroup.position.set(-0.25, 0.12, 0.35) | 862 | + // Position door on the front-side of the boot |
| | 863 | + doorGroup.position.set(-0.32, 0.1, 0.22) |
| | 864 | + doorGroup.rotation.y = -0.4 |
| 774 | group.add(doorGroup) | 865 | group.add(doorGroup) |
| 775 | | 866 | |
| 776 | // === YARD WITH TALL GRASS PATCHES === | 867 | // === YARD WITH TALL GRASS PATCHES === |
@@ -780,12 +871,12 @@ export function createBootHouse(gradientMap) { |
| 780 | | 871 | |
| 781 | // Create grass patches around the boot | 872 | // Create grass patches around the boot |
| 782 | const grassPositions = [ | 873 | const grassPositions = [ |
| 783 | - { x: -0.7, z: 0.4, count: 8 }, | 874 | + { x: -0.8, z: 0.35, count: 8 }, |
| 784 | - { x: -0.6, z: -0.35, count: 6 }, | 875 | + { x: -0.75, z: -0.35, count: 6 }, |
| 785 | - { x: 0.7, z: 0.35, count: 7 }, | 876 | + { x: 0.7, z: 0.4, count: 7 }, |
| 786 | - { x: 0.65, z: -0.3, count: 5 }, | 877 | + { x: 0.75, z: -0.35, count: 5 }, |
| 787 | - { x: -0.1, z: -0.5, count: 6 }, | 878 | + { x: 0.0, z: -0.55, count: 6 }, |
| 788 | - { x: 0.4, z: 0.5, count: 5 } | 879 | + { x: 0.0, z: 0.55, count: 5 } |
| 789 | ] | 880 | ] |
| 790 | | 881 | |
| 791 | for (const patch of grassPositions) { | 882 | for (const patch of grassPositions) { |
@@ -877,11 +968,11 @@ export function createBootHouse(gradientMap) { |
| 877 | sprite.add(pupilR) | 968 | sprite.add(pupilR) |
| 878 | | 969 | |
| 879 | // Animation data | 970 | // Animation data |
| 880 | - sprite.userData.orbitRadius = 0.5 + Math.random() * 0.3 | 971 | + sprite.userData.orbitRadius = 0.6 + Math.random() * 0.25 |
| 881 | sprite.userData.orbitSpeed = 0.8 + Math.random() * 0.6 | 972 | sprite.userData.orbitSpeed = 0.8 + Math.random() * 0.6 |
| 882 | sprite.userData.orbitPhase = (i / 4) * Math.PI * 2 | 973 | sprite.userData.orbitPhase = (i / 4) * Math.PI * 2 |
| 883 | sprite.userData.bobPhase = Math.random() * Math.PI * 2 | 974 | sprite.userData.bobPhase = Math.random() * Math.PI * 2 |
| 884 | - sprite.userData.orbitCenterX = 0.1 // Roughly center of boot | 975 | + sprite.userData.orbitCenterX = 0.0 // Center of boot footprint |
| 885 | sprite.userData.orbitCenterZ = 0 | 976 | sprite.userData.orbitCenterZ = 0 |
| 886 | | 977 | |
| 887 | // Initial position | 978 | // Initial position |