@@ -333,92 +333,104 @@ class Spider { |
| 333 | 333 | this.land() |
| 334 | 334 | } |
| 335 | 335 | |
| 336 | | - land() { |
| 337 | | - this.vel.mult(0); |
| 338 | | - this.isAirborne = false; |
| 339 | | - this.canJump = true; |
| 340 | | - |
| 341 | | - // FIX: Check if we're actually landing on something valid |
| 342 | | - let landedOnSomething = false; |
| 343 | | - |
| 344 | | - // Check if on ground |
| 345 | | - if (this.pos.y >= height - this.radius - 5) { |
| 346 | | - landedOnSomething = true; |
| 347 | | - } |
| 348 | | - |
| 349 | | - // Check if on an obstacle |
| 350 | | - for (let obstacle of obstacles) { |
| 351 | | - if (this.checkObstacleCollision(obstacle)) { |
| 352 | | - landedOnSomething = true; |
| 353 | | - break; |
| 354 | | - } |
| 355 | | - } |
| 356 | | - |
| 357 | | - // Check if on a web strand |
| 358 | | - for (let strand of webStrands) { |
| 359 | | - if (strand !== currentStrand && !strand.broken && this.checkStrandCollision(strand)) { |
| 360 | | - landedOnSomething = true; |
| 361 | | - break; |
| 362 | | - } |
| 363 | | - } |
| 364 | | - |
| 365 | | - // Check if on home branch |
| 366 | | - if (window.homeBranch) { |
| 367 | | - let branch = window.homeBranch; |
| 368 | | - let branchStart = Math.min(branch.startX, branch.endX); |
| 369 | | - let branchEnd = Math.max(branch.startX, branch.endX); |
| 370 | | - |
| 371 | | - if (this.pos.x >= branchStart - 10 && this.pos.x <= branchEnd + 10) { |
| 372 | | - let t = (this.pos.x - branchStart) / (branchEnd - branchStart); |
| 373 | | - t = constrain(t, 0, 1); |
| 374 | | - let branchTopThickness = lerp(branch.thickness * 0.9, branch.thickness * 0.35, t); |
| 375 | | - let branchSurfaceY = branch.y - branchTopThickness; |
| 376 | | - let angleCorrection = (this.pos.x - branchStart) * branch.angle; |
| 377 | | - branchSurfaceY += angleCorrection; |
| 378 | | - |
| 379 | | - if (abs(this.pos.y - branchSurfaceY) < this.radius + 10) { |
| 380 | | - landedOnSomething = true; |
| 381 | | - } |
| 382 | | - } |
| 336 | + land () { |
| 337 | + this.vel.mult(0) |
| 338 | + this.isAirborne = false |
| 339 | + this.canJump = true |
| 340 | + |
| 341 | + // FIX: Check if we're actually landing on something valid |
| 342 | + let landedOnSomething = false |
| 343 | + |
| 344 | + // Check if on ground |
| 345 | + if (this.pos.y >= height - this.radius - 5) { |
| 346 | + landedOnSomething = true |
| 347 | + } |
| 348 | + |
| 349 | + // Check if on an obstacle |
| 350 | + for (let obstacle of obstacles) { |
| 351 | + if (this.checkObstacleCollision(obstacle)) { |
| 352 | + landedOnSomething = true |
| 353 | + break |
| 354 | + } |
| 355 | + } |
| 356 | + |
| 357 | + // Check if on a web strand |
| 358 | + for (let strand of webStrands) { |
| 359 | + if ( |
| 360 | + strand !== currentStrand && |
| 361 | + !strand.broken && |
| 362 | + this.checkStrandCollision(strand) |
| 363 | + ) { |
| 364 | + landedOnSomething = true |
| 365 | + break |
| 366 | + } |
| 367 | + } |
| 368 | + |
| 369 | + // Check if on home branch |
| 370 | + if (window.homeBranch) { |
| 371 | + let branch = window.homeBranch |
| 372 | + let branchStart = Math.min(branch.startX, branch.endX) |
| 373 | + let branchEnd = Math.max(branch.startX, branch.endX) |
| 374 | + |
| 375 | + if (this.pos.x >= branchStart - 10 && this.pos.x <= branchEnd + 10) { |
| 376 | + let t = (this.pos.x - branchStart) / (branchEnd - branchStart) |
| 377 | + t = constrain(t, 0, 1) |
| 378 | + let branchTopThickness = lerp( |
| 379 | + branch.thickness * 0.9, |
| 380 | + branch.thickness * 0.35, |
| 381 | + t |
| 382 | + ) |
| 383 | + let branchSurfaceY = branch.y - branchTopThickness |
| 384 | + let angleCorrection = (this.pos.x - branchStart) * branch.angle |
| 385 | + branchSurfaceY += angleCorrection |
| 386 | + |
| 387 | + if (abs(this.pos.y - branchSurfaceY) < this.radius + 10) { |
| 388 | + landedOnSomething = true |
| 383 | 389 | } |
| 384 | | - |
| 385 | | - // FIX: If we're deploying web but didn't land on anything valid, destroy the web |
| 386 | | - if (currentStrand && isDeployingWeb && (spacePressed || touchHolding)) { |
| 387 | | - if (landedOnSomething) { |
| 388 | | - // Valid landing - finalize the web |
| 389 | | - currentStrand.end = this.pos.copy(); |
| 390 | | - if (!currentStrand.path || currentStrand.path.length === 0) { |
| 391 | | - currentStrand.path = [this.pos.copy()]; |
| 392 | | - } else { |
| 393 | | - currentStrand.path.push(this.pos.copy()); |
| 394 | | - } |
| 395 | | - webNodes.push(new WebNode(this.pos.x, this.pos.y)); |
| 396 | | - } else { |
| 397 | | - // Invalid landing in mid-air - destroy the web! |
| 398 | | - if (webStrands.length > 0 && webStrands[webStrands.length - 1] === currentStrand) { |
| 399 | | - webStrands.pop(); // Remove the invalid strand |
| 400 | | - |
| 401 | | - // Create poof particles |
| 402 | | - for (let i = 0; i < 8; i++) { |
| 403 | | - let p = new Particle(this.pos.x, this.pos.y); |
| 404 | | - p.color = color(255, 255, 255, 150); |
| 405 | | - p.vel = createVector(random(-3, 3), random(-3, 3)); |
| 406 | | - p.size = 4; |
| 407 | | - particles.push(p); |
| 408 | | - } |
| 409 | | - |
| 410 | | - // Notification |
| 411 | | - if (notifications.length < 3) { |
| 412 | | - notifications.push(new Notification("Web needs anchor point!", color(255, 150, 150))); |
| 413 | | - } |
| 414 | | - } |
| 415 | | - } |
| 390 | + } |
| 391 | + } |
| 392 | + |
| 393 | + // FIX: If we're deploying web but didn't land on anything valid, destroy the web |
| 394 | + if (currentStrand && isDeployingWeb && (spacePressed || touchHolding)) { |
| 395 | + if (landedOnSomething) { |
| 396 | + // Valid landing - finalize the web |
| 397 | + currentStrand.end = this.pos.copy() |
| 398 | + if (!currentStrand.path || currentStrand.path.length === 0) { |
| 399 | + currentStrand.path = [this.pos.copy()] |
| 400 | + } else { |
| 401 | + currentStrand.path.push(this.pos.copy()) |
| 416 | 402 | } |
| 403 | + webNodes.push(new WebNode(this.pos.x, this.pos.y)) |
| 404 | + } else { |
| 405 | + // Invalid landing in mid-air - destroy the web! |
| 406 | + if ( |
| 407 | + webStrands.length > 0 && |
| 408 | + webStrands[webStrands.length - 1] === currentStrand |
| 409 | + ) { |
| 410 | + webStrands.pop() // Remove the invalid strand |
| 417 | 411 | |
| 418 | | - currentStrand = null; |
| 419 | | - isDeployingWeb = false; |
| 412 | + // Create poof particles |
| 413 | + for (let i = 0; i < 8; i++) { |
| 414 | + let p = new Particle(this.pos.x, this.pos.y) |
| 415 | + p.color = color(255, 255, 255, 150) |
| 416 | + p.vel = createVector(random(-3, 3), random(-3, 3)) |
| 417 | + p.size = 4 |
| 418 | + particles.push(p) |
| 419 | + } |
| 420 | + |
| 421 | + // Notification |
| 422 | + if (notifications.length < 3) { |
| 423 | + notifications.push( |
| 424 | + new Notification('Web needs anchor point!', color(255, 150, 150)) |
| 425 | + ) |
| 426 | + } |
| 427 | + } |
| 428 | + } |
| 420 | 429 | } |
| 421 | 430 | |
| 431 | + currentStrand = null |
| 432 | + isDeployingWeb = false |
| 433 | + } |
| 422 | 434 | |
| 423 | 435 | display () { |
| 424 | 436 | push() |
@@ -763,8 +775,7 @@ class Obstacle { |
| 763 | 775 | color(255, 200, 100) // Yellow |
| 764 | 776 | ] |
| 765 | 777 | this.balloonColor = random(this.balloonColors) |
| 766 | | - this.stringWave = 0 |
| 767 | | - this.antLegPhase = random(TWO_PI) |
| 778 | + // Remove complex properties - we don't need them for simple balloon |
| 768 | 779 | } else if (this.type === 'beetle') { |
| 769 | 780 | this.bobAmount = 4 |
| 770 | 781 | this.driftSpeed = random(0.15, 0.35) |
@@ -785,9 +796,6 @@ class Obstacle { |
| 785 | 796 | if (i === 0 || i === numPoints / 2) r = radius * 1.3 |
| 786 | 797 | this.leafPoints.push({ angle: angle, radius: r }) |
| 787 | 798 | } |
| 788 | | - } else if (this.type === 'branch') { |
| 789 | | - // Keep for backwards compatibility |
| 790 | | - this.bobAmount = 0 |
| 791 | 799 | } |
| 792 | 800 | } |
| 793 | 801 | |
@@ -847,13 +855,8 @@ class Obstacle { |
| 847 | 855 | if (this.driftDistance > 100) { |
| 848 | 856 | this.breakAttachedStrands() |
| 849 | 857 | } |
| 850 | | - } |
| 851 | 858 | |
| 852 | | - // Update animation phases |
| 853 | | - if (this.type === 'balloon') { |
| 854 | | - this.stringWave = sin(frameCount * 0.05 + this.bobOffset) * 0.1 |
| 855 | | - this.antLegPhase += 0.1 |
| 856 | | - } else if (this.type === 'beetle') { |
| 859 | + // Update wing animation |
| 857 | 860 | this.wingPhase += 0.15 |
| 858 | 861 | } |
| 859 | 862 | |
@@ -981,212 +984,265 @@ class Obstacle { |
| 981 | 984 | translate(this.x, this.y) |
| 982 | 985 | |
| 983 | 986 | if (this.type === 'balloon') { |
| 984 | | - // Hot air balloon with canvas texture! |
| 987 | + // ============================================ |
| 988 | + // HOT AIR BALLOON WITH CANVAS TEXTURE |
| 989 | + // ============================================ |
| 985 | 990 | push() |
| 986 | 991 | |
| 987 | | - // String/rope first (behind balloon) |
| 988 | | - stroke(80, 60, 40) |
| 989 | | - strokeWeight(1.5) |
| 990 | | - noFill() |
| 991 | | - beginShape() |
| 992 | | - for (let i = 0; i <= 10; i++) { |
| 993 | | - let t = i / 10 |
| 994 | | - let stringX = sin(t * PI * 2 + this.stringWave) * 3 |
| 995 | | - let stringY = t * 40 + this.radius |
| 996 | | - curveVertex(stringX, stringY) |
| 997 | | - } |
| 998 | | - endShape() |
| 999 | | - |
| 1000 | 992 | // Balloon shadow |
| 1001 | 993 | noStroke() |
| 1002 | 994 | fill(0, 0, 0, 30) |
| 1003 | | - ellipse(5, 5, this.radius * 2.2, this.radius * 2.5) |
| 995 | + ellipse(5, 5, this.radius * 2.1) |
| 1004 | 996 | |
| 1005 | | - // Main balloon with canvas panels |
| 1006 | | - push() |
| 1007 | | - // Draw vertical panels for that classic hot air balloon look |
| 997 | + // Main balloon with canvas panel texture |
| 998 | + // Draw vertical panels like a real hot air balloon |
| 1008 | 999 | let numPanels = 8 |
| 1009 | 1000 | for (let i = 0; i < numPanels; i++) { |
| 1010 | | - let angle1 = (TWO_PI / numPanels) * i |
| 1011 | | - let angle2 = (TWO_PI / numPanels) * (i + 1) |
| 1001 | + push() |
| 1002 | + |
| 1003 | + // Rotate for each panel |
| 1004 | + rotate((TWO_PI / numPanels) * i) |
| 1012 | 1005 | |
| 1013 | | - // Alternate panel colors for striped effect |
| 1006 | + // Alternate panel colors for classic hot air balloon look |
| 1014 | 1007 | if (i % 2 === 0) { |
| 1015 | 1008 | fill( |
| 1016 | 1009 | red(this.balloonColor), |
| 1017 | 1010 | green(this.balloonColor), |
| 1018 | | - blue(this.balloonColor), |
| 1019 | | - 200 |
| 1011 | + blue(this.balloonColor) |
| 1020 | 1012 | ) |
| 1021 | 1013 | } else { |
| 1014 | + // Slightly darker alternate panels |
| 1022 | 1015 | fill( |
| 1023 | | - red(this.balloonColor) - 30, |
| 1024 | | - green(this.balloonColor) - 30, |
| 1025 | | - blue(this.balloonColor) - 30, |
| 1026 | | - 200 |
| 1016 | + red(this.balloonColor) * 0.9, |
| 1017 | + green(this.balloonColor) * 0.9, |
| 1018 | + blue(this.balloonColor) * 0.9 |
| 1027 | 1019 | ) |
| 1028 | 1020 | } |
| 1029 | 1021 | |
| 1030 | | - // Draw tapered panel (wider at middle, narrow at top/bottom) |
| 1031 | | - beginShape() |
| 1032 | | - // Top point |
| 1033 | | - vertex(0, -this.radius * 1.2) |
| 1034 | | - // Upper curve |
| 1035 | | - bezierVertex( |
| 1036 | | - cos(angle1) * this.radius * 0.3, |
| 1037 | | - -this.radius * 0.9, |
| 1038 | | - cos(angle1) * this.radius * 0.8, |
| 1039 | | - -this.radius * 0.3, |
| 1040 | | - cos(angle1) * this.radius * 1.1, |
| 1041 | | - 0 |
| 1042 | | - ) |
| 1043 | | - // Lower curve to bottom |
| 1044 | | - bezierVertex( |
| 1045 | | - cos(angle1) * this.radius * 0.9, |
| 1046 | | - this.radius * 0.5, |
| 1047 | | - cos(angle1) * this.radius * 0.4, |
| 1048 | | - this.radius * 0.9, |
| 1022 | + // Draw panel as pie slice |
| 1023 | + noStroke() |
| 1024 | + arc( |
| 1049 | 1025 | 0, |
| 1050 | | - this.radius * 1.1 |
| 1051 | | - ) |
| 1052 | | - // Back up the other side |
| 1053 | | - bezierVertex( |
| 1054 | | - cos(angle2) * this.radius * 0.4, |
| 1055 | | - this.radius * 0.9, |
| 1056 | | - cos(angle2) * this.radius * 0.9, |
| 1057 | | - this.radius * 0.5, |
| 1058 | | - cos(angle2) * this.radius * 1.1, |
| 1059 | | - 0 |
| 1060 | | - ) |
| 1061 | | - bezierVertex( |
| 1062 | | - cos(angle2) * this.radius * 0.8, |
| 1063 | | - -this.radius * 0.3, |
| 1064 | | - cos(angle2) * this.radius * 0.3, |
| 1065 | | - -this.radius * 0.9, |
| 1066 | 1026 | 0, |
| 1067 | | - -this.radius * 1.2 |
| 1027 | + this.radius * 2, |
| 1028 | + this.radius * 2, |
| 1029 | + -PI / numPanels, |
| 1030 | + PI / numPanels, |
| 1031 | + PIE |
| 1068 | 1032 | ) |
| 1069 | | - endShape(CLOSE) |
| 1033 | + |
| 1034 | + pop() |
| 1070 | 1035 | } |
| 1071 | 1036 | |
| 1072 | | - // Panel seams/ropes |
| 1073 | | - stroke(60, 40, 20, 100) |
| 1074 | | - strokeWeight(0.5) |
| 1037 | + // Add panel seams (the ropes/stitching between panels) |
| 1038 | + stroke(60, 40, 20, 110) |
| 1039 | + strokeWeight(1) |
| 1075 | 1040 | for (let i = 0; i < numPanels; i++) { |
| 1076 | 1041 | let angle = (TWO_PI / numPanels) * i |
| 1077 | | - // Vertical seam lines |
| 1078 | | - beginShape() |
| 1079 | | - noFill() |
| 1080 | | - vertex(0, -this.radius * 1.2) |
| 1081 | | - bezierVertex( |
| 1082 | | - cos(angle) * this.radius * 0.3, |
| 1083 | | - -this.radius * 0.9, |
| 1084 | | - cos(angle) * this.radius * 0.8, |
| 1085 | | - -this.radius * 0.3, |
| 1086 | | - cos(angle) * this.radius * 1.1, |
| 1087 | | - 0 |
| 1088 | | - ) |
| 1089 | | - bezierVertex( |
| 1090 | | - cos(angle) * this.radius * 0.9, |
| 1091 | | - this.radius * 0.5, |
| 1092 | | - cos(angle) * this.radius * 0.4, |
| 1093 | | - this.radius * 0.9, |
| 1094 | | - 0, |
| 1095 | | - this.radius * 1.1 |
| 1096 | | - ) |
| 1097 | | - endShape() |
| 1042 | + let x1 = cos(angle) * this.radius * 0.2 |
| 1043 | + let y1 = sin(angle) * this.radius * 0.2 |
| 1044 | + let x2 = cos(angle) * this.radius * 0.95 |
| 1045 | + let y2 = sin(angle) * this.radius * 0.95 |
| 1046 | + line(x1, y1, x2, y2) |
| 1098 | 1047 | } |
| 1099 | 1048 | |
| 1100 | | - // Highlight on balloon |
| 1049 | + // Add circular reinforcement bands |
| 1050 | + noFill() |
| 1051 | + stroke(80, 50, 30, 80) |
| 1052 | + strokeWeight(1.5) |
| 1053 | + ellipse(0, 0, this.radius * 1.4) |
| 1054 | + ellipse(0, 0, this.radius * 0.8) |
| 1055 | + |
| 1056 | + // Matte fabric shading (subtle, non-glossy) |
| 1101 | 1057 | noStroke() |
| 1102 | | - fill(255, 255, 255, 80) |
| 1103 | | - ellipse( |
| 1104 | | - -this.radius * 0.3, |
| 1105 | | - -this.radius * 0.5, |
| 1106 | | - this.radius * 0.6, |
| 1107 | | - this.radius * 0.7 |
| 1108 | | - ) |
| 1109 | | - pop() |
| 1058 | + // Soft radial shading toward top-left to imply ambient light without specular shine |
| 1059 | + for (let r = this.radius * 1.2; r > this.radius * 0.2; r -= this.radius * 0.15) { |
| 1060 | + fill(255, 255, 255, 8) // very low alpha |
| 1061 | + ellipse(-this.radius * 0.25, -this.radius * 0.35, r * 0.25, r * 0.18) |
| 1062 | + } |
| 1063 | + // Global matte overlay to reduce plastic look |
| 1064 | + noStroke() |
| 1065 | + fill(230, 210, 190, 18) |
| 1066 | + ellipse(0, 0, this.radius * 2, this.radius * 2) |
| 1110 | 1067 | |
| 1111 | | - // FLAME EFFECT! |
| 1068 | + // Bottom opening of balloon (where flame goes) |
| 1069 | + fill(40, 20, 10) |
| 1070 | + ellipse(0, this.radius * 0.9, this.radius * 0.4, this.radius * 0.15) |
| 1071 | + |
| 1072 | + // Support ropes from balloon to basket |
| 1073 | + stroke(80, 60, 40) |
| 1074 | + strokeWeight(2) |
| 1075 | + // Four support ropes |
| 1076 | + line(-this.radius * 0.3, this.radius * 0.85, -8, this.radius + 20) |
| 1077 | + line(this.radius * 0.3, this.radius * 0.85, 8, this.radius + 20) |
| 1078 | + line(-this.radius * 0.15, this.radius * 0.9, -4, this.radius + 20) |
| 1079 | + line(this.radius * 0.15, this.radius * 0.9, 4, this.radius + 20) |
| 1080 | + |
| 1081 | + // FLAME EFFECT (between balloon and basket) |
| 1112 | 1082 | push() |
| 1113 | | - translate(0, this.radius - 5) |
| 1083 | + translate(0, this.radius + 10) |
| 1084 | + |
| 1114 | 1085 | // Flame glow |
| 1115 | 1086 | noStroke() |
| 1116 | | - fill(255, 200, 0, 40 + sin(frameCount * 0.3) * 20) |
| 1117 | | - ellipse(0, 0, 25, 25) |
| 1118 | | - fill(255, 150, 0, 60 + sin(frameCount * 0.4) * 30) |
| 1119 | | - ellipse(0, 0, 15, 18) |
| 1120 | | - // Flame itself |
| 1121 | | - fill(255, 200, 0) |
| 1087 | + fill(255, 200, 0, 30 + sin(frameCount * 0.2) * 20) |
| 1088 | + ellipse(0, 0, 30, 30) |
| 1089 | + fill(255, 150, 0, 50 + sin(frameCount * 0.3) * 30) |
| 1090 | + ellipse(0, 0, 20, 25) |
| 1091 | + |
| 1092 | + // Animated flame |
| 1122 | 1093 | push() |
| 1123 | | - let flameHeight = 8 + sin(frameCount * 0.5) * 3 |
| 1124 | | - translate(0, -2) |
| 1094 | + let flameHeight = 12 + sin(frameCount * 0.4) * 4 |
| 1095 | + let flameWave = sin(frameCount * 0.3) * 2 |
| 1096 | + |
| 1097 | + // Outer flame (orange) |
| 1098 | + fill(255, 150, 0) |
| 1125 | 1099 | beginShape() |
| 1126 | | - vertex(-3, 0) |
| 1100 | + vertex(-5, 5) |
| 1101 | + bezierVertex( |
| 1102 | + -5 + flameWave, |
| 1103 | + -flameHeight * 0.5, |
| 1104 | + -2 + flameWave, |
| 1105 | + -flameHeight * 0.8, |
| 1106 | + flameWave, |
| 1107 | + -flameHeight |
| 1108 | + ) |
| 1127 | 1109 | bezierVertex( |
| 1128 | | - -3, |
| 1129 | | - -flameHeight * 0.7, |
| 1130 | | - -1, |
| 1131 | | - -flameHeight, |
| 1132 | | - 0, |
| 1133 | | - -flameHeight * 1.2 |
| 1110 | + 2 + flameWave, |
| 1111 | + -flameHeight * 0.8, |
| 1112 | + 5 + flameWave, |
| 1113 | + -flameHeight * 0.5, |
| 1114 | + 5, |
| 1115 | + 5 |
| 1134 | 1116 | ) |
| 1135 | | - bezierVertex(1, -flameHeight, 3, -flameHeight * 0.7, 3, 0) |
| 1136 | 1117 | endShape(CLOSE) |
| 1137 | | - fill(255, 255, 200) |
| 1138 | | - ellipse(0, -flameHeight * 0.5, 3, 4) |
| 1118 | + |
| 1119 | + // Inner flame (yellow/white) |
| 1120 | + fill(255, 255, 150) |
| 1121 | + beginShape() |
| 1122 | + vertex(-2, 5) |
| 1123 | + bezierVertex( |
| 1124 | + -2 + flameWave * 0.5, |
| 1125 | + -flameHeight * 0.3, |
| 1126 | + -1 + flameWave * 0.5, |
| 1127 | + -flameHeight * 0.5, |
| 1128 | + flameWave * 0.5, |
| 1129 | + -flameHeight * 0.7 |
| 1130 | + ) |
| 1131 | + bezierVertex( |
| 1132 | + 1 + flameWave * 0.5, |
| 1133 | + -flameHeight * 0.5, |
| 1134 | + 2 + flameWave * 0.5, |
| 1135 | + -flameHeight * 0.3, |
| 1136 | + 2, |
| 1137 | + 5 |
| 1138 | + ) |
| 1139 | + endShape(CLOSE) |
| 1140 | + |
| 1141 | + // Flame tip (bright white) |
| 1142 | + fill(255, 255, 255) |
| 1143 | + ellipse(flameWave * 0.5, -flameHeight * 0.5, 3, 5) |
| 1139 | 1144 | pop() |
| 1145 | + |
| 1140 | 1146 | pop() |
| 1141 | 1147 | |
| 1142 | | - // Basket |
| 1148 | + // BIGGER, MORE DETAILED BASKET |
| 1143 | 1149 | push() |
| 1144 | | - translate(0, this.radius + 10) |
| 1150 | + translate(0, this.radius + 25) |
| 1151 | + |
| 1152 | + // Basket shadow |
| 1153 | + noStroke() |
| 1154 | + fill(0, 0, 0, 20) |
| 1155 | + rect(-11, 2, 22, 15, 2) |
| 1156 | + |
| 1157 | + // Main basket - bigger to see ant better |
| 1145 | 1158 | fill(101, 67, 33) |
| 1146 | 1159 | stroke(80, 50, 20) |
| 1147 | | - strokeWeight(1) |
| 1148 | | - // Woven basket shape |
| 1149 | | - beginShape() |
| 1150 | | - vertex(-8, 0) |
| 1151 | | - vertex(8, 0) |
| 1152 | | - vertex(6, 10) |
| 1153 | | - vertex(-6, 10) |
| 1154 | | - endShape(CLOSE) |
| 1155 | | - // Basket weave pattern |
| 1160 | + strokeWeight(1.5) |
| 1161 | + rect(-10, 0, 20, 14, 2) // Bigger basket |
| 1162 | + |
| 1163 | + // Woven basket texture |
| 1156 | 1164 | stroke(80, 50, 20, 150) |
| 1157 | | - for (let i = -6; i < 6; i += 2) { |
| 1158 | | - line(i, 1, i, 9) |
| 1165 | + strokeWeight(1) |
| 1166 | + // Vertical weaves |
| 1167 | + for (let i = -8; i < 8; i += 3) { |
| 1168 | + line(i, 1, i, 13) |
| 1159 | 1169 | } |
| 1160 | | - for (let i = 2; i < 9; i += 2) { |
| 1161 | | - line(-6, i, 6, i) |
| 1170 | + // Horizontal weaves |
| 1171 | + for (let i = 3; i < 12; i += 3) { |
| 1172 | + line(-9, i, 9, i) |
| 1162 | 1173 | } |
| 1163 | | - // Basket rim |
| 1174 | + |
| 1175 | + // Basket rim (thicker, more pronounced) |
| 1164 | 1176 | stroke(60, 40, 20) |
| 1165 | | - strokeWeight(1.5) |
| 1166 | | - line(-8, 0, 8, 0) |
| 1177 | + strokeWeight(2) |
| 1178 | + line(-10, 0, 10, 0) |
| 1179 | + |
| 1180 | + // Corner reinforcements |
| 1181 | + fill(80, 50, 20) |
| 1182 | + noStroke() |
| 1183 | + ellipse(-9, 0, 3) |
| 1184 | + ellipse(9, 0, 3) |
| 1185 | + |
| 1167 | 1186 | pop() |
| 1168 | 1187 | |
| 1169 | | - // Ant in basket (peeking over edge) |
| 1188 | + // DETAILED ANT PILOT (bigger, more visible) |
| 1170 | 1189 | push() |
| 1171 | | - translate(0, this.radius + 12) |
| 1190 | + translate(0, this.radius + 28) |
| 1191 | + |
| 1192 | + // Ant body |
| 1172 | 1193 | fill(20) |
| 1173 | 1194 | noStroke() |
| 1174 | | - // Just ant head and antennae visible |
| 1175 | | - ellipse(0, -2, 6, 4) // Head peeking up |
| 1195 | + ellipse(0, 0, 8, 5) // Thorax |
| 1196 | + ellipse(0, -3, 6, 5) // Head |
| 1197 | + ellipse(0, 3, 7, 6) // Abdomen |
| 1198 | + |
| 1199 | + // Ant eyes |
| 1200 | + fill(255, 100, 100) |
| 1201 | + ellipse(-2, -3, 2) |
| 1202 | + ellipse(2, -3, 2) |
| 1203 | + |
| 1176 | 1204 | // Antennae |
| 1177 | 1205 | stroke(20) |
| 1178 | | - strokeWeight(0.5) |
| 1179 | | - line(-1, -3, -3, -6) |
| 1180 | | - line(1, -3, 3, -6) |
| 1181 | | - // Tiny ant arms gripping basket edge |
| 1182 | 1206 | strokeWeight(1) |
| 1183 | | - line(-3, 0, -4, 2) |
| 1184 | | - line(3, 0, 4, 2) |
| 1207 | + line(-1, -5, -3, -8) |
| 1208 | + line(1, -5, 3, -8) |
| 1209 | + |
| 1210 | + // Little ant arms holding basket edge |
| 1211 | + strokeWeight(1.5) |
| 1212 | + line(-3, 0, -6, -3) |
| 1213 | + line(3, 0, 6, -3) |
| 1214 | + |
| 1215 | + // Ant legs visible over basket edge |
| 1216 | + line(-2, 2, -4, 5) |
| 1217 | + line(2, 2, 4, 5) |
| 1218 | + |
| 1219 | + // Optional: Tiny pilot goggles |
| 1220 | + stroke(100, 50, 0) |
| 1221 | + strokeWeight(1) |
| 1222 | + noFill() |
| 1223 | + ellipse(-2, -3, 3) |
| 1224 | + ellipse(2, -3, 3) |
| 1225 | + line(-0.5, -3, 0.5, -3) |
| 1226 | + |
| 1227 | + pop() |
| 1228 | + |
| 1229 | + // Sandbags hanging from basket (optional detail) |
| 1230 | + push() |
| 1231 | + translate(0, this.radius + 25) |
| 1232 | + fill(80, 60, 40) |
| 1233 | + noStroke() |
| 1234 | + ellipse(-12, 10, 4, 5) |
| 1235 | + ellipse(12, 10, 4, 5) |
| 1236 | + // Sandbag ropes |
| 1237 | + stroke(60, 40, 20) |
| 1238 | + strokeWeight(0.5) |
| 1239 | + line(-10, 7, -12, 10) |
| 1240 | + line(10, 7, 12, 10) |
| 1185 | 1241 | pop() |
| 1186 | 1242 | |
| 1187 | 1243 | pop() |
| 1188 | 1244 | } else if (this.type === 'beetle') { |
| 1189 | | - // Big floating beetle! |
| 1245 | + // Big floating beetle! (KEEP EXISTING CODE) |
| 1190 | 1246 | push() |
| 1191 | 1247 | rotate(this.rotation) |
| 1192 | 1248 | |
@@ -1264,11 +1320,9 @@ class Obstacle { |
| 1264 | 1320 | ellipse(this.radius * 0.2, this.radius * 0.4, this.radius * 0.35) |
| 1265 | 1321 | ellipse(-this.radius * 0.25, this.radius * 0.3, this.radius * 0.25) |
| 1266 | 1322 | |
| 1267 | | - // No legs - they're flying! |
| 1268 | | - // Just small leg stubs tucked under the body |
| 1323 | + // Tiny tucked legs |
| 1269 | 1324 | stroke(0) |
| 1270 | 1325 | strokeWeight(1) |
| 1271 | | - // Tiny tucked legs |
| 1272 | 1326 | line( |
| 1273 | 1327 | -this.radius * 0.5, |
| 1274 | 1328 | -this.radius * 0.2, |
@@ -1299,7 +1353,7 @@ class Obstacle { |
| 1299 | 1353 | line(-3, -this.radius * 1.1, -8, -this.radius * 1.4) |
| 1300 | 1354 | line(3, -this.radius * 1.1, 8, -this.radius * 1.4) |
| 1301 | 1355 | |
| 1302 | | - // Eyes (bigger and more prominent) |
| 1356 | + // Eyes |
| 1303 | 1357 | fill(255, 0, 0) |
| 1304 | 1358 | noStroke() |
| 1305 | 1359 | ellipse(-5, -this.radius * 0.7, 5) |
@@ -1311,7 +1365,7 @@ class Obstacle { |
| 1311 | 1365 | |
| 1312 | 1366 | pop() |
| 1313 | 1367 | } else if (this.type === 'leaf') { |
| 1314 | | - // Original leaf code |
| 1368 | + // Original leaf code (KEEP EXISTING) |
| 1315 | 1369 | rotate(this.rotation) |
| 1316 | 1370 | |
| 1317 | 1371 | if (gamePhase === 'NIGHT') { |
@@ -1348,38 +1402,6 @@ class Obstacle { |
| 1348 | 1402 | line(0, 0, this.radius / 2, -this.radius / 2) |
| 1349 | 1403 | line(0, 0, -this.radius / 2, this.radius / 2) |
| 1350 | 1404 | line(0, 0, this.radius / 2, this.radius / 2) |
| 1351 | | - } else if (this.type === 'branch') { |
| 1352 | | - // Keep old branch code for backwards compatibility |
| 1353 | | - rotate(this.rotation) |
| 1354 | | - |
| 1355 | | - if (gamePhase === 'NIGHT') { |
| 1356 | | - stroke(40, 20, 0) |
| 1357 | | - fill(50, 25, 5) |
| 1358 | | - } else { |
| 1359 | | - stroke(101, 67, 33) |
| 1360 | | - fill(139, 90, 43) |
| 1361 | | - } |
| 1362 | | - strokeWeight(3) |
| 1363 | | - |
| 1364 | | - push() |
| 1365 | | - strokeWeight(this.radius / 3) |
| 1366 | | - line(-this.radius, 0, this.radius, 0) |
| 1367 | | - |
| 1368 | | - strokeWeight(2) |
| 1369 | | - line(-this.radius / 2, 0, -this.radius / 2 - 10, -10) |
| 1370 | | - line(this.radius / 3, 0, this.radius / 3 + 8, -8) |
| 1371 | | - line(0, 0, 5, -15) |
| 1372 | | - |
| 1373 | | - stroke(80, 50, 20, 100) |
| 1374 | | - strokeWeight(1) |
| 1375 | | - for (let i = -this.radius; i < this.radius; i += 5) { |
| 1376 | | - line(i, -2, i + 2, 2) |
| 1377 | | - } |
| 1378 | | - pop() |
| 1379 | | - |
| 1380 | | - noStroke() |
| 1381 | | - fill(255, 255, 255, 30) |
| 1382 | | - ellipse(0, 0, this.radius * 2) |
| 1383 | 1405 | } |
| 1384 | 1406 | |
| 1385 | 1407 | pop() |