@@ -16,64 +16,64 @@ class Spider { |
| 16 | this.munchCooldown = 0 | 16 | this.munchCooldown = 0 |
| 17 | } | 17 | } |
| 18 | | 18 | |
| 19 | -jump(targetX, targetY) { | 19 | + jump(targetX, targetY) { |
| 20 | - if (!this.canJump) return; | 20 | + if (!this.canJump) return; |
| 21 | - | 21 | + |
| 22 | - let direction = createVector(targetX - this.pos.x, targetY - this.pos.y); | 22 | + let direction = createVector(targetX - this.pos.x, targetY - this.pos.y); |
| 23 | - let clickDistance = direction.mag(); | 23 | + let clickDistance = direction.mag(); |
| 24 | - direction.normalize(); | 24 | + direction.normalize(); |
| 25 | - | 25 | + |
| 26 | - // Scale jump power based on click distance (closer clicks = smaller jumps) | 26 | + // Scale jump power based on click distance (closer clicks = smaller jumps) |
| 27 | - let actualJumpPower = map(clickDistance, 0, 200, 3, this.jumpPower); | 27 | + let actualJumpPower = map(clickDistance, 0, 200, 3, this.jumpPower); |
| 28 | - actualJumpPower = constrain(actualJumpPower, 3, this.jumpPower); | 28 | + actualJumpPower = constrain(actualJumpPower, 3, this.jumpPower); |
| 29 | - direction.mult(actualJumpPower); | 29 | + direction.mult(actualJumpPower); |
| 30 | - | 30 | + |
| 31 | - this.vel = direction; | 31 | + this.vel = direction; |
| 32 | - this.isAirborne = true; | 32 | + this.isAirborne = true; |
| 33 | - this.canJump = false; | 33 | + this.canJump = false; |
| 34 | - this.lastAnchorPoint = this.pos.copy(); | 34 | + this.lastAnchorPoint = this.pos.copy(); |
| | 35 | + |
| | 36 | + // Check if we're jumping off a web strand |
| | 37 | + for (let strand of webStrands) { |
| | 38 | + if (strand === currentStrand) continue; |
| | 39 | + |
| | 40 | + if (this.checkStrandCollision(strand)) { |
| | 41 | + // Much simpler shimmy detection based on actual jump power used |
| | 42 | + let isShimmy = actualJumpPower < 6; // If we used less than half power, it's a shimmy |
| 35 | | 43 | |
| 36 | - // Check if we're jumping off a web strand | 44 | + // Apply appropriate recoil based on movement type |
| 37 | - for (let strand of webStrands) { | 45 | + if (isShimmy) { |
| 38 | - if (strand === currentStrand) continue; | 46 | + // Trigger shimmy visual effect |
| 39 | - | 47 | + this.shimmyEffect = 20; |
| 40 | - if (this.checkStrandCollision(strand)) { | 48 | + |
| 41 | - // Much simpler shimmy detection based on actual jump power used | 49 | + // NO recoil at all for shimmying - just tiny vibration |
| 42 | - let isShimmy = actualJumpPower < 6; // If we used less than half power, it's a shimmy | 50 | + strand.vibrate(0.3); |
| 43 | - | 51 | + |
| 44 | - // Apply appropriate recoil based on movement type | 52 | + // Tiny yellow particles |
| 45 | - if (isShimmy) { | 53 | + let p = new Particle(this.pos.x, this.pos.y); |
| 46 | - // Trigger shimmy visual effect | 54 | + p.color = color(255, 255, 100, 80); |
| 47 | - this.shimmyEffect = 20; | 55 | + p.vel = createVector(random(-0.3, 0.3), random(-0.3, 0.3)); |
| 48 | - | 56 | + p.size = 2; |
| 49 | - // NO recoil at all for shimmying - just tiny vibration | 57 | + particles.push(p); |
| 50 | - strand.vibrate(0.3); | 58 | + } else { |
| 51 | - | 59 | + // Scale recoil based on actual jump power |
| 52 | - // Tiny yellow particles | 60 | + let recoilForce = -(actualJumpPower / this.jumpPower) * 0.08; // Scale by power ratio |
| 53 | - let p = new Particle(this.pos.x, this.pos.y); | 61 | + strand.applyRecoil(recoilForce); |
| 54 | - p.color = color(255, 255, 100, 80); | 62 | + |
| 55 | - p.vel = createVector(random(-0.3, 0.3), random(-0.3, 0.3)); | 63 | + // Create particles only for real jumps |
| 56 | - p.size = 2; | 64 | + for (let i = 0; i < 2; i++) { |
| 57 | - particles.push(p); | 65 | + let p = new Particle(this.pos.x, this.pos.y); |
| 58 | - } else { | 66 | + p.color = color(255, 255, 255, 120); |
| 59 | - // Scale recoil based on actual jump power | 67 | + p.vel = createVector(random(-0.8, 0.8), random(1, 2)); |
| 60 | - let recoilForce = -(actualJumpPower / this.jumpPower) * 0.08; // Scale by power ratio | 68 | + p.size = 3; |
| 61 | - strand.applyRecoil(recoilForce); | 69 | + particles.push(p); |
| 62 | - | 70 | + } |
| 63 | - // Create particles only for real jumps | | |
| 64 | - for (let i = 0; i < 2; i++) { | | |
| 65 | - let p = new Particle(this.pos.x, this.pos.y); | | |
| 66 | - p.color = color(255, 255, 255, 120); | | |
| 67 | - p.vel = createVector(random(-0.8, 0.8), random(1, 2)); | | |
| 68 | - p.size = 3; | | |
| 69 | - particles.push(p); | | |
| 70 | - } | | |
| 71 | - } | | |
| 72 | - | | |
| 73 | - break; | | |
| 74 | - } | | |
| 75 | } | 71 | } |
| | 72 | + |
| | 73 | + break; |
| | 74 | + } |
| 76 | } | 75 | } |
| | 76 | + } |
| 77 | | 77 | |
| 78 | munch () { | 78 | munch () { |
| 79 | if (this.munchCooldown > 0) return | 79 | if (this.munchCooldown > 0) return |
@@ -559,14 +559,46 @@ class Fly { |
| 559 | | 559 | |
| 560 | class Obstacle { | 560 | class Obstacle { |
| 561 | constructor (x, y, radius, type) { | 561 | constructor (x, y, radius, type) { |
| | 562 | + // Store original position for drift tracking |
| | 563 | + this.originalX = x |
| | 564 | + this.originalY = y |
| 562 | this.x = x | 565 | this.x = x |
| 563 | this.y = y | 566 | this.y = y |
| 564 | this.radius = radius | 567 | this.radius = radius |
| 565 | - this.type = type || (random() < 0.5 ? 'branch' : 'leaf') | 568 | + this.type = type || 'leaf' |
| 566 | this.rotation = random(TWO_PI) | 569 | this.rotation = random(TWO_PI) |
| 567 | this.leafPoints = [] | 570 | this.leafPoints = [] |
| 568 | - | 571 | + |
| 569 | - if (this.type === 'leaf') { | 572 | + // Movement properties for all types |
| | 573 | + this.bobOffset = random(TWO_PI) |
| | 574 | + this.bobSpeed = random(0.02, 0.04) |
| | 575 | + this.bobAmount = 0 |
| | 576 | + |
| | 577 | + // Type-specific initialization |
| | 578 | + if (this.type === 'balloon') { |
| | 579 | + this.bobAmount = 8 // Balloons bob more |
| | 580 | + this.balloonColors = [ |
| | 581 | + color(255, 100, 100), // Red |
| | 582 | + color(100, 200, 255), // Blue |
| | 583 | + color(255, 200, 100) // Yellow |
| | 584 | + ] |
| | 585 | + this.balloonColor = random(this.balloonColors) |
| | 586 | + this.stringWave = 0 |
| | 587 | + this.antLegPhase = random(TWO_PI) |
| | 588 | + |
| | 589 | + } else if (this.type === 'beetle') { |
| | 590 | + this.bobAmount = 4 |
| | 591 | + this.driftSpeed = random(0.15, 0.35) |
| | 592 | + this.driftAngle = random(TWO_PI) |
| | 593 | + this.driftChangeRate = random(0.005, 0.015) |
| | 594 | + this.wingPhase = random(TWO_PI) |
| | 595 | + this.beetleColor = random() < 0.5 ? |
| | 596 | + color(20, 60, 20) : // Dark green |
| | 597 | + color(40, 20, 60) // Purple |
| | 598 | + this.driftDistance = 0 // Track total drift |
| | 599 | + |
| | 600 | + } else if (this.type === 'leaf') { |
| | 601 | + this.bobAmount = 2 // Leaves bob slightly |
| 570 | let numPoints = 8 | 602 | let numPoints = 8 |
| 571 | for (let i = 0; i < numPoints; i++) { | 603 | for (let i = 0; i < numPoints; i++) { |
| 572 | let angle = (TWO_PI / numPoints) * i | 604 | let angle = (TWO_PI / numPoints) * i |
@@ -574,44 +606,292 @@ class Obstacle { |
| 574 | if (i === 0 || i === numPoints / 2) r = radius * 1.3 | 606 | if (i === 0 || i === numPoints / 2) r = radius * 1.3 |
| 575 | this.leafPoints.push({ angle: angle, radius: r }) | 607 | this.leafPoints.push({ angle: angle, radius: r }) |
| 576 | } | 608 | } |
| | 609 | + } else if (this.type === 'branch') { |
| | 610 | + // Keep for backwards compatibility |
| | 611 | + this.bobAmount = 0 |
| | 612 | + } |
| | 613 | + } |
| | 614 | + |
| | 615 | + update() { |
| | 616 | + // Bobbing motion for all types |
| | 617 | + let bob = sin(frameCount * this.bobSpeed + this.bobOffset) * this.bobAmount |
| | 618 | + this.y = this.originalY + bob |
| | 619 | + |
| | 620 | + // Beetle-specific drift |
| | 621 | + if (this.type === 'beetle') { |
| | 622 | + // Store initial position if not set |
| | 623 | + if (!this.initialX) { |
| | 624 | + this.initialX = this.x |
| | 625 | + this.initialY = this.y |
| | 626 | + } |
| | 627 | + |
| | 628 | + // Slowly change drift direction using Perlin noise |
| | 629 | + this.driftAngle += (noise(frameCount * this.driftChangeRate, this.originalX * 0.01) - 0.5) * 0.1 |
| | 630 | + |
| | 631 | + // Apply drift to original position |
| | 632 | + this.originalX += cos(this.driftAngle) * this.driftSpeed |
| | 633 | + this.originalY += sin(this.driftAngle) * this.driftSpeed * 0.5 |
| | 634 | + |
| | 635 | + // Calculate total drift distance from initial position |
| | 636 | + this.driftDistance = dist(this.originalX, this.originalY, this.initialX, this.initialY) |
| | 637 | + |
| | 638 | + // Keep beetles on screen with soft boundaries |
| | 639 | + if (this.originalX < 80) { |
| | 640 | + this.driftAngle = random(-PI/4, PI/4) |
| | 641 | + this.originalX = 80 |
| | 642 | + } |
| | 643 | + if (this.originalX > width - 80) { |
| | 644 | + this.driftAngle = random(3*PI/4, 5*PI/4) |
| | 645 | + this.originalX = width - 80 |
| | 646 | + } |
| | 647 | + if (this.originalY < 80) { |
| | 648 | + this.driftAngle = random(-3*PI/4, -PI/4) |
| | 649 | + this.originalY = 80 |
| | 650 | + } |
| | 651 | + if (this.originalY > height - 150) { |
| | 652 | + this.driftAngle = random(PI/4, 3*PI/4) |
| | 653 | + this.originalY = height - 150 |
| | 654 | + } |
| | 655 | + |
| | 656 | + // Update actual position (with bob already applied to y) |
| | 657 | + this.x = this.originalX |
| | 658 | + |
| | 659 | + // Check if beetle has drifted too far and break attached strands |
| | 660 | + if (this.driftDistance > 100) { |
| | 661 | + this.breakAttachedStrands() |
| | 662 | + } |
| | 663 | + } |
| | 664 | + |
| | 665 | + // Update animation phases |
| | 666 | + if (this.type === 'balloon') { |
| | 667 | + this.stringWave = sin(frameCount * 0.05 + this.bobOffset) * 0.1 |
| | 668 | + this.antLegPhase += 0.1 |
| | 669 | + } else if (this.type === 'beetle') { |
| | 670 | + this.wingPhase += 0.15 |
| | 671 | + } |
| | 672 | + |
| | 673 | + // For all moving obstacles, update any attached web strands |
| | 674 | + if (this.bobAmount > 0 || this.type === 'beetle') { |
| | 675 | + this.updateAttachedStrands() |
| | 676 | + } |
| | 677 | + } |
| | 678 | + |
| | 679 | + updateAttachedStrands() { |
| | 680 | + // Update web strands that are connected to this obstacle |
| | 681 | + for (let strand of webStrands) { |
| | 682 | + // Check if strand starts at this obstacle |
| | 683 | + if (dist(strand.start.x, strand.start.y, this.x, this.y) < this.radius + 10) { |
| | 684 | + strand.start.x = this.x |
| | 685 | + strand.start.y = this.y |
| | 686 | + if (strand.path && strand.path.length > 0) { |
| | 687 | + strand.path[0].x = this.x |
| | 688 | + strand.path[0].y = this.y |
| | 689 | + } |
| | 690 | + } |
| | 691 | + |
| | 692 | + // Check if strand ends at this obstacle |
| | 693 | + if (strand.end && dist(strand.end.x, strand.end.y, this.x, this.y) < this.radius + 10) { |
| | 694 | + strand.end.x = this.x |
| | 695 | + strand.end.y = this.y |
| | 696 | + if (strand.path && strand.path.length > 0) { |
| | 697 | + strand.path[strand.path.length - 1].x = this.x |
| | 698 | + strand.path[strand.path.length - 1].y = this.y |
| | 699 | + } |
| | 700 | + } |
| | 701 | + } |
| | 702 | + } |
| | 703 | + |
| | 704 | + breakAttachedStrands() { |
| | 705 | + // Break any strands attached to this beetle that has drifted too far |
| | 706 | + for (let strand of webStrands) { |
| | 707 | + let attachedToStart = dist(strand.start.x, strand.start.y, this.x, this.y) < this.radius + 10 |
| | 708 | + let attachedToEnd = strand.end && dist(strand.end.x, strand.end.y, this.x, this.y) < this.radius + 10 |
| | 709 | + |
| | 710 | + if (attachedToStart || attachedToEnd) { |
| | 711 | + // Mark strand as broken |
| | 712 | + strand.broken = true |
| | 713 | + |
| | 714 | + // Create dramatic snap particles |
| | 715 | + let snapX = attachedToStart ? strand.start.x : strand.end.x |
| | 716 | + let snapY = attachedToStart ? strand.start.y : strand.end.y |
| | 717 | + |
| | 718 | + // Red/pink particles for the snap |
| | 719 | + for (let i = 0; i < 8; i++) { |
| | 720 | + let p = new Particle(snapX, snapY) |
| | 721 | + p.color = color(255, random(100, 200), random(100, 150)) |
| | 722 | + p.vel = createVector(random(-5, 5), random(-5, 2)) |
| | 723 | + p.size = random(4, 8) |
| | 724 | + particles.push(p) |
| | 725 | + } |
| | 726 | + |
| | 727 | + // White strand particles |
| | 728 | + for (let i = 0; i < 4; i++) { |
| | 729 | + let p = new Particle(snapX, snapY) |
| | 730 | + p.color = color(255, 255, 255) |
| | 731 | + p.vel = createVector(random(-3, 3), random(-3, 0)) |
| | 732 | + p.size = 3 |
| | 733 | + particles.push(p) |
| | 734 | + } |
| | 735 | + |
| | 736 | + // Reset beetle drift after breaking strands |
| | 737 | + this.initialX = this.x |
| | 738 | + this.initialY = this.y |
| | 739 | + this.driftDistance = 0 |
| | 740 | + } |
| 577 | } | 741 | } |
| 578 | } | 742 | } |
| 579 | | 743 | |
| 580 | display () { | 744 | display () { |
| 581 | push() | 745 | push() |
| 582 | translate(this.x, this.y) | 746 | translate(this.x, this.y) |
| 583 | - rotate(this.rotation) | 747 | + |
| 584 | - | 748 | + if (this.type === 'balloon') { |
| 585 | - if (this.type === 'branch') { | 749 | + // Balloon with ant in basket! |
| 586 | - if (gamePhase === 'NIGHT') { | 750 | + push() |
| 587 | - stroke(40, 20, 0) | 751 | + |
| 588 | - fill(50, 25, 5) | 752 | + // String first (behind balloon) |
| 589 | - } else { | 753 | + stroke(80, 60, 40) |
| 590 | - stroke(101, 67, 33) | 754 | + strokeWeight(1) |
| 591 | - fill(139, 90, 43) | 755 | + noFill() |
| | 756 | + beginShape() |
| | 757 | + for (let i = 0; i <= 10; i++) { |
| | 758 | + let t = i / 10 |
| | 759 | + let stringX = sin(t * PI * 2 + this.stringWave) * 3 |
| | 760 | + let stringY = t * 40 + this.radius |
| | 761 | + curveVertex(stringX, stringY) |
| 592 | } | 762 | } |
| 593 | - strokeWeight(3) | 763 | + endShape() |
| 594 | - | 764 | + |
| | 765 | + // Balloon shadow |
| | 766 | + noStroke() |
| | 767 | + fill(0, 0, 0, 30) |
| | 768 | + ellipse(5, 5, this.radius * 2.2, this.radius * 2.5) |
| | 769 | + |
| | 770 | + // Main balloon |
| | 771 | + noStroke() |
| | 772 | + fill(red(this.balloonColor), green(this.balloonColor), blue(this.balloonColor), 150) |
| | 773 | + ellipse(0, 0, this.radius * 2.2, this.radius * 2.5) |
| | 774 | + fill(red(this.balloonColor) + 30, green(this.balloonColor) + 30, blue(this.balloonColor) + 30, 200) |
| | 775 | + ellipse(-this.radius * 0.3, -this.radius * 0.3, this.radius * 1.2, this.radius * 1.4) |
| | 776 | + // Highlight |
| | 777 | + fill(255, 255, 255, 120) |
| | 778 | + ellipse(-this.radius * 0.4, -this.radius * 0.5, this.radius * 0.5, this.radius * 0.6) |
| | 779 | + |
| | 780 | + // Basket |
| | 781 | + translate(0, this.radius + 10) |
| | 782 | + fill(139, 90, 43) |
| | 783 | + stroke(100, 60, 20) |
| | 784 | + strokeWeight(1) |
| | 785 | + // Trapezoid basket |
| | 786 | + beginShape() |
| | 787 | + vertex(-8, 0) |
| | 788 | + vertex(8, 0) |
| | 789 | + vertex(6, 10) |
| | 790 | + vertex(-6, 10) |
| | 791 | + endShape(CLOSE) |
| | 792 | + // Basket weave pattern |
| | 793 | + stroke(100, 60, 20, 100) |
| | 794 | + for (let i = -6; i < 6; i += 3) { |
| | 795 | + line(i, 2, i, 8) |
| | 796 | + } |
| | 797 | + for (let i = 2; i < 8; i += 3) { |
| | 798 | + line(-6, i, 6, i) |
| | 799 | + } |
| | 800 | + |
| | 801 | + // Ant in basket |
| | 802 | + translate(0, 5) |
| | 803 | + fill(20) |
| | 804 | + noStroke() |
| | 805 | + // Ant body |
| | 806 | + ellipse(0, 0, 6, 4) // Head |
| | 807 | + ellipse(0, 3, 5, 6) // Thorax |
| | 808 | + ellipse(0, 7, 7, 9) // Abdomen |
| | 809 | + // Ant legs (animated) |
| | 810 | + stroke(20) |
| | 811 | + strokeWeight(0.5) |
| | 812 | + for (let i = 0; i < 3; i++) { |
| | 813 | + let legAngle = this.antLegPhase + i * 0.5 |
| | 814 | + let legSpread = 4 + sin(legAngle) * 2 |
| | 815 | + line(-2, 3 + i * 2, -legSpread, 3 + i * 2) |
| | 816 | + line(2, 3 + i * 2, legSpread, 3 + i * 2) |
| | 817 | + } |
| | 818 | + // Antennae |
| | 819 | + line(-1, -1, -3, -3) |
| | 820 | + line(1, -1, 3, -3) |
| | 821 | + |
| | 822 | + pop() |
| | 823 | + |
| | 824 | + } else if (this.type === 'beetle') { |
| | 825 | + // Big beetle! |
| 595 | push() | 826 | push() |
| 596 | - strokeWeight(this.radius / 3) | 827 | + rotate(this.rotation) |
| 597 | - line(-this.radius, 0, this.radius, 0) | 828 | + |
| 598 | - | 829 | + // Shadow |
| | 830 | + noStroke() |
| | 831 | + fill(0, 0, 0, 40) |
| | 832 | + ellipse(3, 3, this.radius * 1.8, this.radius * 2.2) |
| | 833 | + |
| | 834 | + // Wings (if flying at night) |
| | 835 | + if (gamePhase === 'NIGHT') { |
| | 836 | + push() |
| | 837 | + fill(255, 255, 255, 100 + sin(this.wingPhase) * 50) |
| | 838 | + noStroke() |
| | 839 | + let wingSpread = sin(this.wingPhase) * 15 |
| | 840 | + ellipse(-wingSpread, 0, 20, 12) |
| | 841 | + ellipse(wingSpread, 0, 20, 12) |
| | 842 | + pop() |
| | 843 | + } |
| | 844 | + |
| | 845 | + // Main beetle body |
| | 846 | + fill(red(this.beetleColor), green(this.beetleColor), blue(this.beetleColor)) |
| | 847 | + stroke(0) |
| 599 | strokeWeight(2) | 848 | strokeWeight(2) |
| 600 | - line(-this.radius / 2, 0, -this.radius / 2 - 10, -10) | 849 | + ellipse(0, 0, this.radius * 1.6, this.radius * 2) |
| 601 | - line(this.radius / 3, 0, this.radius / 3 + 8, -8) | 850 | + |
| 602 | - line(0, 0, 5, -15) | 851 | + // Shell split line |
| 603 | - | 852 | + stroke(0) |
| 604 | - stroke(80, 50, 20, 100) | | |
| 605 | strokeWeight(1) | 853 | strokeWeight(1) |
| 606 | - for (let i = -this.radius; i < this.radius; i += 5) { | 854 | + line(0, -this.radius, 0, this.radius) |
| 607 | - line(i, -2, i + 2, 2) | 855 | + |
| | 856 | + // Head |
| | 857 | + fill(10) |
| | 858 | + ellipse(0, -this.radius * 0.8, this.radius * 0.8, this.radius * 0.6) |
| | 859 | + |
| | 860 | + // Spots/pattern |
| | 861 | + noStroke() |
| | 862 | + fill(0, 0, 0, 80) |
| | 863 | + ellipse(-this.radius * 0.3, 0, this.radius * 0.4) |
| | 864 | + ellipse(this.radius * 0.3, -this.radius * 0.2, this.radius * 0.3) |
| | 865 | + ellipse(this.radius * 0.2, this.radius * 0.4, this.radius * 0.35) |
| | 866 | + ellipse(-this.radius * 0.25, this.radius * 0.3, this.radius * 0.25) |
| | 867 | + |
| | 868 | + // Legs |
| | 869 | + stroke(0) |
| | 870 | + strokeWeight(2) |
| | 871 | + for (let i = 0; i < 3; i++) { |
| | 872 | + let legY = -this.radius * 0.3 + i * this.radius * 0.3 |
| | 873 | + let legMove = sin(this.wingPhase * 2 + i) * 2 |
| | 874 | + line(-this.radius * 0.8, legY, -this.radius * 1.2 + legMove, legY + 5) |
| | 875 | + line(this.radius * 0.8, legY, this.radius * 1.2 - legMove, legY + 5) |
| 608 | } | 876 | } |
| 609 | - pop() | 877 | + |
| 610 | - | 878 | + // Antennae |
| | 879 | + strokeWeight(1) |
| | 880 | + line(-3, -this.radius * 1.1, -8, -this.radius * 1.4) |
| | 881 | + line(3, -this.radius * 1.1, 8, -this.radius * 1.4) |
| | 882 | + |
| | 883 | + // Eyes |
| | 884 | + fill(255, 0, 0) |
| 611 | noStroke() | 885 | noStroke() |
| 612 | - fill(255, 255, 255, 30) | 886 | + ellipse(-5, -this.radius * 0.7, 4) |
| 613 | - ellipse(0, 0, this.radius * 2) | 887 | + ellipse(5, -this.radius * 0.7, 4) |
| | 888 | + |
| | 889 | + pop() |
| | 890 | + |
| 614 | } else if (this.type === 'leaf') { | 891 | } else if (this.type === 'leaf') { |
| | 892 | + // Original leaf code |
| | 893 | + rotate(this.rotation) |
| | 894 | + |
| 615 | if (gamePhase === 'NIGHT') { | 895 | if (gamePhase === 'NIGHT') { |
| 616 | fill(20, 40, 20) | 896 | fill(20, 40, 20) |
| 617 | stroke(10, 20, 10) | 897 | stroke(10, 20, 10) |
@@ -646,6 +926,39 @@ class Obstacle { |
| 646 | line(0, 0, this.radius / 2, -this.radius / 2) | 926 | line(0, 0, this.radius / 2, -this.radius / 2) |
| 647 | line(0, 0, -this.radius / 2, this.radius / 2) | 927 | line(0, 0, -this.radius / 2, this.radius / 2) |
| 648 | line(0, 0, this.radius / 2, this.radius / 2) | 928 | line(0, 0, this.radius / 2, this.radius / 2) |
| | 929 | + |
| | 930 | + } else if (this.type === 'branch') { |
| | 931 | + // Keep old branch code for backwards compatibility |
| | 932 | + rotate(this.rotation) |
| | 933 | + |
| | 934 | + if (gamePhase === 'NIGHT') { |
| | 935 | + stroke(40, 20, 0) |
| | 936 | + fill(50, 25, 5) |
| | 937 | + } else { |
| | 938 | + stroke(101, 67, 33) |
| | 939 | + fill(139, 90, 43) |
| | 940 | + } |
| | 941 | + strokeWeight(3) |
| | 942 | + |
| | 943 | + push() |
| | 944 | + strokeWeight(this.radius / 3) |
| | 945 | + line(-this.radius, 0, this.radius, 0) |
| | 946 | + |
| | 947 | + strokeWeight(2) |
| | 948 | + line(-this.radius / 2, 0, -this.radius / 2 - 10, -10) |
| | 949 | + line(this.radius / 3, 0, this.radius / 3 + 8, -8) |
| | 950 | + line(0, 0, 5, -15) |
| | 951 | + |
| | 952 | + stroke(80, 50, 20, 100) |
| | 953 | + strokeWeight(1) |
| | 954 | + for (let i = -this.radius; i < this.radius; i += 5) { |
| | 955 | + line(i, -2, i + 2, 2) |
| | 956 | + } |
| | 957 | + pop() |
| | 958 | + |
| | 959 | + noStroke() |
| | 960 | + fill(255, 255, 255, 30) |
| | 961 | + ellipse(0, 0, this.radius * 2) |
| 649 | } | 962 | } |
| 650 | | 963 | |
| 651 | pop() | 964 | pop() |
@@ -734,4 +1047,4 @@ class Particle { |
| 734 | isDead () { | 1047 | isDead () { |
| 735 | return this.lifetime <= 0 | 1048 | return this.lifetime <= 0 |
| 736 | } | 1049 | } |
| 737 | -} | 1050 | +} |