User prompt
Add humans
User prompt
Make an new item called Pepto-Bismol (gives you +1 health)
User prompt
Add an new item called Painkiller (+1 healt
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'countriesVisitedTxt.style.fill = 0xCD7F32; // Bronze' Line Number: 926
User prompt
Add traveling to different countries
User prompt
Add drowning
User prompt
Can you use a different asset, the Atomic bomb has different looks and usage so
User prompt
Add a eurovision flashbang ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Now add chocolate (When it sppears, the swan follows it instead and consumes it.)
User prompt
Can you add a atomic bomb
Code edit (1 edits merged)
Please save this source code
User prompt
Goose Chase: Battle for Chips
Initial prompt
Make a completely functional but unplayable game where a goose eats chips but tries to beat the hell out of a angry swan.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var AtomicBomb = Container.expand(function () { var self = Container.call(this); // Create bomb body (blue sphere with electric glow) var bombBody = self.attachAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); bombBody.tint = 0x0066ff; // Electric blue color // Add energy core (bright white) var energyCore = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.4, scaleY: 0.4 }); energyCore.tint = 0xffffff; self.addChild(energyCore); // Add outer energy ring (cyan) var outerRing = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2 }); outerRing.tint = 0x00ffff; outerRing.alpha = 0.5; self.addChild(outerRing); self.explosionRadius = 500; self.isExploding = false; self.isCollected = false; self.freezeOnUse = true; // New property - bomb freezes enemies rather than pushing them // Bomb collection self.collect = function () { if (!self.isCollected) { self.isCollected = true; return true; } return false; }; // Explosion effect self.explode = function () { if (!self.isExploding) { self.isExploding = true; // Create explosion animation - now a freezing blast tween(self, { scaleX: 10, scaleY: 10, alpha: 0.8 }, { duration: 700, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { self.visible = false; } }); } }); return true; } return false; }; // Electric pulse animation for idle bomb function startElectricAnimation() { // Outer ring pulsing function pulseOuterRing() { tween(outerRing, { alpha: 0.2, scaleX: 1.4, scaleY: 1.4 }, { duration: 700, easing: tween.easeInOut, onFinish: function onFinish() { tween(outerRing, { alpha: 0.5, scaleX: 1.2, scaleY: 1.2 }, { duration: 700, easing: tween.easeInOut, onFinish: pulseOuterRing }); } }); } // Core pulsing tween(energyCore, { scaleX: 0.5, scaleY: 0.5, alpha: 0.9 }, { duration: 600, easing: tween.easeInOut, onFinish: function onFinish() { tween(energyCore, { scaleX: 0.4, scaleY: 0.4, alpha: 1 }, { duration: 600, easing: tween.easeInOut, onFinish: startElectricAnimation }); } }); // Start the outer ring animation too pulseOuterRing(); } // Start electric pulsing startElectricAnimation(); return self; }); var Bread = Container.expand(function () { var self = Container.call(this); // Create bread visual var breadBody = self.attachAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.3 }); breadBody.tint = 0xE8B96F; // Brown bread color // Create crust detail var crust = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.52, scaleY: 0.32 }); crust.tint = 0xC68642; // Darker crust color self.addChild(crust); self.isConsumed = false; self.timeLeft = 360; // 6 seconds at 60fps self.sinkingSpeed = 0.5; self.inWater = false; // Bread consumption self.consume = function () { if (!self.isConsumed) { self.isConsumed = true; // Consumption animation tween(self, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 300, onFinish: function onFinish() { self.visible = false; } }); return true; } return false; }; // Start sinking animation when bread hits water self.startSinking = function () { if (!self.inWater) { self.inWater = true; // Make bread rotate slowly while sinking tween(self, { rotation: Math.PI * 0.5 * (Math.random() > 0.5 ? 1 : -1) }, { duration: 3000, easing: tween.easeInOut }); } }; // Update function self.update = function () { self.timeLeft--; // Sink when in water if (self.inWater) { self.y += self.sinkingSpeed; // Fade out as it sinks if (self.timeLeft < 180) { self.alpha = Math.max(0, self.timeLeft / 180); } } // Pulse when about to disappear if (self.timeLeft < 60 && !self.inWater) { self.alpha = 0.5 + Math.sin(self.timeLeft * 0.2) * 0.5; } // Despawn when time runs out if (self.timeLeft <= 0 && !self.isConsumed) { self.consume(); } }; return self; }); var Chip = Container.expand(function () { var self = Container.call(this); var chipGraphic = self.attachAsset('chip', { anchorX: 0.5, anchorY: 0.5 }); self.isCollected = false; self.collect = function () { if (!self.isCollected) { self.isCollected = true; LK.getSound('eat').play(); tween(self, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 300, onFinish: function onFinish() { self.visible = false; } }); return true; } return false; }; return self; }); var Chocolate = Container.expand(function () { var self = Container.call(this); // Create chocolate graphic (brown rectangle) var chocolateBody = self.attachAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.7, scaleY: 0.5 }); // Set chocolate color to brown chocolateBody.tint = 0x4B2E20; // Add inner layer for chocolate texture var innerLayer = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.3 }); innerLayer.tint = 0x663C28; self.addChild(innerLayer); self.isConsumed = false; self.timeLeft = 300; // 5 seconds at 60fps // Swan consumes chocolate self.consume = function () { if (!self.isConsumed) { self.isConsumed = true; // Consumption animation tween(self, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 300, onFinish: function onFinish() { self.visible = false; } }); return true; } return false; }; self.update = function () { self.timeLeft--; // Pulse when about to disappear if (self.timeLeft < 60) { self.alpha = 0.5 + Math.sin(self.timeLeft * 0.2) * 0.5; } if (self.timeLeft <= 0 && !self.isConsumed) { self.consume(); } }; return self; }); var Country = Container.expand(function () { var self = Container.call(this); // Create country portal visual (rainbow-colored circle) var portalBody = self.attachAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2 }); portalBody.tint = 0x00AAFF; // Blue base color // Add interior of portal var portalInterior = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.9, scaleY: 0.9 }); portalInterior.tint = 0xFFFFFF; self.addChild(portalInterior); // Country name label self.nameText = new Text2('', { size: 40, fill: 0xFFFFFF }); self.nameText.anchor.set(0.5, 0.5); self.nameText.y = -80; self.addChild(self.nameText); // Properties self.countryName = ""; self.countryColor = 0x00AAFF; self.isActive = false; self.isVisited = false; self.travelCooldown = 0; self.visitBonus = 10; // Score bonus for first visit // Set country information self.setCountry = function (name, color) { self.countryName = name; self.countryColor = color; self.nameText.setText(name); portalBody.tint = color; // Return for method chaining return self; }; // Activate the portal self.activate = function () { if (!self.isActive) { self.isActive = true; // Start portal animation startPortalAnimation(); // Make visible with fade-in self.alpha = 0; tween(self, { alpha: 1 }, { duration: 800, easing: tween.easeOut }); } }; // Travel effect when goose enters the portal self.travel = function () { if (self.travelCooldown <= 0) { self.travelCooldown = 180; // 3 second cooldown // Create travel animation - portal expands tween(self, { scaleX: 3, scaleY: 3, alpha: 0.8 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1, alpha: 1 }, { duration: 500, easing: tween.easeOut }); } }); // First time visit bonus var scoreBonus = self.isVisited ? 5 : self.visitBonus; self.isVisited = true; return { success: true, countryName: self.countryName, scoreBonus: scoreBonus }; } return { success: false }; }; // Portal animation function startPortalAnimation() { // Rotating animation function spin() { tween(portalInterior, { rotation: portalInterior.rotation + Math.PI * 2 }, { duration: 5000, onFinish: spin }); } // Pulsing animation function pulse() { tween(portalBody, { scaleX: 1.3, scaleY: 1.3 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { tween(portalBody, { scaleX: 1.2, scaleY: 1.2 }, { duration: 1500, easing: tween.easeInOut, onFinish: pulse }); } }); } // Start both animations spin(); pulse(); } self.update = function () { if (self.travelCooldown > 0) { self.travelCooldown--; } }; return self; }); var Drowning = Container.expand(function () { var self = Container.call(this); // Create water bubbles effect var bubbles = []; var bubbleCount = 8; for (var i = 0; i < bubbleCount; i++) { var bubble = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.2 + Math.random() * 0.2, scaleY: 0.2 + Math.random() * 0.2, x: (Math.random() - 0.5) * 100, y: (Math.random() - 0.5) * 100 }); bubble.tint = 0x88CCFF; // Light blue for water bubbles bubble.alpha = 0.7; bubble.speedY = -1 - Math.random() * 2; bubble.speedX = (Math.random() - 0.5) * 1; self.addChild(bubble); bubbles.push(bubble); } self.isActive = false; self.duration = 180; // 3 seconds at 60fps self.timer = 0; self.warningLevel = 0; self.activate = function () { if (!self.isActive) { self.isActive = true; self.timer = 0; self.warningLevel = 0; self.alpha = 1; // Start bubble animation for (var i = 0; i < bubbles.length; i++) { animateBubble(bubbles[i]); } } }; self.deactivate = function () { if (self.isActive) { self.isActive = false; self.timer = 0; self.warningLevel = 0; // Fade out tween(self, { alpha: 0 }, { duration: 300, easing: tween.easeOut }); } }; function animateBubble(bubble) { // Random position around character bubble.x = (Math.random() - 0.5) * 100; bubble.y = (Math.random() - 0.5) * 100 + 50; bubble.alpha = 0; bubble.scale.x = bubble.scale.y = 0.1 + Math.random() * 0.2; // Animate bubble rising tween(bubble, { y: bubble.y - 100 - Math.random() * 50, alpha: 0.7, scaleX: bubble.scale.x * 1.5, scaleY: bubble.scale.y * 1.5 }, { duration: 1000 + Math.random() * 500, easing: tween.easeOut, onFinish: function onFinish() { tween(bubble, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { if (self.isActive) { animateBubble(bubble); } } }); } }); } self.update = function () { if (!self.isActive) return; self.timer++; // Update warning level var newWarningLevel = Math.min(3, Math.floor(self.timer / 60)); // Warning level changed - trigger visual feedback if (newWarningLevel > self.warningLevel) { self.warningLevel = newWarningLevel; // Pulse effect based on warning level tween(self, { alpha: 0.4 }, { duration: 200, onFinish: function onFinish() { tween(self, { alpha: 1 }, { duration: 200 }); } }); } // Check if drowning is complete if (self.timer >= self.duration) { return true; // Return true to signal drowning is complete } return false; // Not yet drowned }; return self; }); var EurovisionFlashbang = Container.expand(function () { var self = Container.call(this); // Create flashbang body (silver/white circle) var flashbangBody = self.attachAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); flashbangBody.tint = 0xE5E4E2; // Silver color // Add eurovision star symbol var starSymbol = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5 }); starSymbol.tint = 0xFFD700; // Gold color self.addChild(starSymbol); self.isCollected = false; self.isExploding = false; // Rainbow effect colors self.rainbowColors = [0xFF0000, // Red 0xFF7F00, // Orange 0xFFFF00, // Yellow 0x00FF00, // Green 0x0000FF, // Blue 0x4B0082, // Indigo 0x9400D3 // Violet ]; // Flashbang collection self.collect = function () { if (!self.isCollected) { self.isCollected = true; return true; } return false; }; // Explosion effect self.explode = function () { if (!self.isExploding) { self.isExploding = true; // Create explosion animation tween(self, { scaleX: 15, scaleY: 15, alpha: 0.9 }, { duration: 700, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { self.visible = false; } }); } }); return true; } return false; }; // Rainbow pulse animation function startRainbowAnimation() { var colorIndex = 0; function cycleColors() { flashbangBody.tint = self.rainbowColors[colorIndex]; colorIndex = (colorIndex + 1) % self.rainbowColors.length; tween(self, { scaleX: 1.1, scaleY: 1.1 }, { duration: 400, easing: tween.easeInOut, onFinish: function onFinish() { tween(self, { scaleX: 1.0, scaleY: 1.0 }, { duration: 400, easing: tween.easeInOut, onFinish: cycleColors }); } }); } cycleColors(); } // Start pulsing startRainbowAnimation(); return self; }); var Goose = Container.expand(function () { var self = Container.call(this); // Body var body = self.attachAsset('goose', { anchorX: 0.5, anchorY: 0.5 }); self.lastIsSwimming = false; // Wings var leftWing = LK.getAsset('gooseWing', { anchorX: 0, anchorY: 0.5, x: -80, y: 0, rotation: -0.3 }); var rightWing = LK.getAsset('gooseWing', { anchorX: 1, anchorY: 0.5, x: 80, y: 0, rotation: 0.3 }); // Beak var beak = LK.getAsset('gooseBeak', { anchorX: 0, anchorY: 0.5, x: 80, y: 0 }); self.addChild(leftWing); self.addChild(rightWing); self.addChild(beak); self.speed = 7; self.attackCooldown = 0; self.isAttacking = false; self.stunned = 0; self.attack = function () { if (self.attackCooldown <= 0 && !self.isAttacking && self.stunned <= 0) { self.isAttacking = true; LK.getSound('honk').play(); // Wing attack animation tween(leftWing, { rotation: -0.8, x: -100 }, { duration: 200, easing: tween.easeOut }); tween(rightWing, { rotation: 0.8, x: 100 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { // Return wings to normal tween(leftWing, { rotation: -0.3, x: -80 }, { duration: 300, easing: tween.easeInOut }); tween(rightWing, { rotation: 0.3, x: 80 }, { duration: 300, easing: tween.easeInOut, onFinish: function onFinish() { self.isAttacking = false; } }); self.attackCooldown = 60; // 1 second cooldown (60 frames) } }); return true; } return false; }; self.stun = function (duration) { self.stunned = duration; // Stun animation tween(self, { alpha: 0.6 }, { duration: 100, onFinish: function onFinish() { tween(self, { alpha: 1 }, { duration: 100 }); } }); }; self.update = function () { if (self.attackCooldown > 0) { self.attackCooldown--; } if (self.stunned > 0) { self.stunned--; } }; return self; }); var Human = Container.expand(function () { var self = Container.call(this); // Create human body var body = self.attachAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.9, scaleY: 1.5 }); body.tint = 0xFFD2B7; // Skin tone // Add clothes var clothes = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 1.0, y: 20 }); clothes.tint = Math.random() > 0.5 ? 0x3498DB : 0xE74C3C; // Random blue or red self.addChild(clothes); // Add head var head = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.6, y: -50 }); head.tint = 0xFFD2B7; // Same skin tone as body self.addChild(head); // Properties self.speed = 1 + Math.random() * 1.5; self.targetX = 0; self.targetY = 0; self.breadCount = 0; self.maxBread = 3; self.lastBreadThrow = 0; self.breadCooldown = 120 + Math.floor(Math.random() * 240); // 2-6 second cooldown self.isAngry = false; // Set target position self.setTarget = function (x, y) { self.targetX = x; self.targetY = y; }; // Make human throw bread self.throwBread = function (pondX, pondY) { if (self.breadCount > 0 && self.lastBreadThrow <= 0) { self.breadCount--; self.lastBreadThrow = self.breadCooldown; // Calculate throw position (toward pond center) var dx = pondX - self.x; var dy = pondY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); var throwDist = Math.min(dist * 0.7, 300); return { x: self.x + dx / dist * throwDist, y: self.y + dy / dist * throwDist }; } return null; }; // Make human angry at goose self.becomeAngry = function () { if (!self.isAngry) { self.isAngry = true; body.tint = 0xFFB2B7; // Slightly redder skin tone when angry // Angry animation tween(self, { scaleX: 1.2, scaleY: 1.2 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { scaleX: 1.0, scaleY: 1.0 }, { duration: 300, easing: tween.easeOut }); } }); return true; } return false; }; // Make human happy (feed birds) self.refillBread = function () { self.breadCount = self.maxBread; // Happy animation tween(head, { y: -60 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { tween(head, { y: -50 }, { duration: 300, easing: tween.easeInOut }); } }); }; // Update function self.update = function () { if (self.lastBreadThrow > 0) { self.lastBreadThrow--; } // Move toward target var dx = self.targetX - self.x; var dy = self.targetY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 10) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; // Flip based on movement direction if (dx < 0) { self.scale.x = -1; } else { self.scale.x = 1; } } // Calm down after some time if (self.isAngry && Math.random() < 0.001) { self.isAngry = false; body.tint = 0xFFD2B7; // Normal skin tone } }; return self; }); var Painkiller = Container.expand(function () { var self = Container.call(this); // Create painkiller item (white pill with red cross) var pillBody = self.attachAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.7, scaleY: 0.4 }); pillBody.tint = 0xFFFFFF; // White pill // Add red cross to indicate healing var redCross = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.4, scaleY: 0.1 }); redCross.tint = 0xFF0000; // Red self.addChild(redCross); // Add vertical line of cross var redCrossVert = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.1, scaleY: 0.4 }); redCrossVert.tint = 0xFF0000; // Red self.addChild(redCrossVert); self.isCollected = false; self.timeLeft = 360; // 6 seconds at 60fps // Painkiller collection self.collect = function () { if (!self.isCollected) { self.isCollected = true; // Collection animation tween(self, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 300, onFinish: function onFinish() { self.visible = false; } }); return true; } return false; }; // Update function to handle pill lifetime self.update = function () { self.timeLeft--; // Pulse when about to disappear if (self.timeLeft < 60) { self.alpha = 0.5 + Math.sin(self.timeLeft * 0.2) * 0.5; } if (self.timeLeft <= 0 && !self.isCollected) { self.collect(); } }; return self; }); var Pond = Container.expand(function () { var self = Container.call(this); var pondGraphic = self.attachAsset('pond', { anchorX: 0.5, anchorY: 0.5 }); return self; }); var Swan = Container.expand(function () { var self = Container.call(this); // Body var body = self.attachAsset('swan', { anchorX: 0.5, anchorY: 0.5 }); // Wings var leftWing = LK.getAsset('swanWing', { anchorX: 0, anchorY: 0.5, x: -90, y: 0, rotation: -0.3 }); var rightWing = LK.getAsset('swanWing', { anchorX: 1, anchorY: 0.5, x: 90, y: 0, rotation: 0.3 }); // Beak var beak = LK.getAsset('swanBeak', { anchorX: 0, anchorY: 0.5, x: 90, y: 0 }); self.addChild(leftWing); self.addChild(rightWing); self.addChild(beak); self.speed = 3; self.targetX = 0; self.targetY = 0; self.aggressionLevel = 1; self.attackCooldown = 0; self.isAttacking = false; self.stunned = 0; self.setTarget = function (x, y) { self.targetX = x; self.targetY = y; }; self.attack = function () { if (self.attackCooldown <= 0 && !self.isAttacking && self.stunned <= 0) { self.isAttacking = true; LK.getSound('swanAttack').play(); // Attack animation var originalX = self.x; var originalY = self.y; // Calculate direction toward goose var dx = self.targetX - self.x; var dy = self.targetY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); var normalizedX = dx / dist; var normalizedY = dy / dist; // Quick lunge animation tween(self, { x: self.x + normalizedX * 150, y: self.y + normalizedY * 150 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { // Return to original position tween(self, { x: originalX, y: originalY }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { self.isAttacking = false; } }); self.attackCooldown = Math.max(30, 120 - self.aggressionLevel * 10); // Cooldown decreases with aggression } }); return true; } return false; }; self.stun = function (duration) { self.stunned = duration; // Stun animation tween(self, { alpha: 0.6 }, { duration: 100, onFinish: function onFinish() { tween(self, { alpha: 1 }, { duration: 100 }); } }); }; self.increaseAggression = function () { self.aggressionLevel = Math.min(8, self.aggressionLevel + 0.25); self.speed = 3 + self.aggressionLevel * 0.4; }; self.update = function () { if (self.stunned > 0) { self.stunned--; return; } if (self.attackCooldown > 0) { self.attackCooldown--; } if (!self.isAttacking) { // Move toward target var dx = self.targetX - self.x; var dy = self.targetY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 10) { var speed = self.speed; self.x += dx / dist * speed; self.y += dy / dist * speed; // Rotate toward movement direction self.rotation = Math.atan2(dy, dx); } // Only try to attack if not targeting chocolate if (!swanTargetingChocolate && dist < 250 && Math.random() < 0.03 * self.aggressionLevel) { self.attack(); } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB // Sky blue background }); /**** * Game Code ****/ // Game variables var goose; var swan; var pond; var chips = []; var chipCount = 15; var dragNode = null; var lastIntersecting = false; var gameActive = true; var highScore = storage.highScore || 0; var atomicBomb = null; var bombTimer = 0; var hasBomb = false; var chocolate = null; var chocolateTimer = 0; var eurovisionFlashbang = null; var flashbangTimer = 0; var hasFlashbang = false; var drowning = null; var isInShallowWater = false; var lastPondDistance = 0; var swanNormalTarget = { x: 0, y: 0 }; var swanTargetingChocolate = false; var painkiller = null; var painkillerTimer = 0; var gooseHealth = 3; // Initial health var maxGooseHealth = 5; // Maximum health possible // Human-related variables var humans = []; var maxHumans = 3; var humanSpawnTimer = 180; var breadPieces = []; var gooseChasingHuman = null; var chasingTimeout = 0; // Country variables var countries = []; var availableCountries = [{ name: "France", color: 0x002654 }, { name: "Italy", color: 0x008C45 }, { name: "Germany", color: 0x000000 }, { name: "Spain", color: 0xAA151B }, { name: "Sweden", color: 0x006AA7 }, { name: "Greece", color: 0x0D5EAF }, { name: "Ireland", color: 0xFF883E }, { name: "Portugal", color: 0x006600 }]; var visitedCountries = {}; // Track visited countries var countryPortalTimer = 0; var maxActiveCountries = 2; // Maximum number of active portals at once var currentBackground = "default"; // Current background theme var travelEffectActive = false; // Initialize the game UI var scoreTxt = new Text2('0', { size: 80, fill: 0xFFFFFF }); scoreTxt.setText("Score: " + LK.getScore()); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var highScoreTxt = new Text2('0', { size: 50, fill: 0xFFFFFF }); highScoreTxt.setText("High Score: " + highScore); highScoreTxt.anchor.set(0.5, 0); highScoreTxt.y = 90; LK.gui.top.addChild(highScoreTxt); // Create visited countries display var countriesVisitedTxt = new Text2('0', { size: 45, fill: 0xFFFFFF }); countriesVisitedTxt.setText("Countries: 0"); countriesVisitedTxt.anchor.set(0.5, 0); countriesVisitedTxt.y = 150; LK.gui.top.addChild(countriesVisitedTxt); // Update countries visited text function updateCountriesVisited() { var count = Object.keys(visitedCountries).length; countriesVisitedTxt.setText("Countries: " + count); // Change text color based on countries visited if (count >= 5) { countriesVisitedTxt.style = { fill: 0xFFD700 }; // Gold } else if (count >= 3) { countriesVisitedTxt.style = { fill: 0xC0C0C0 }; // Silver } else if (count >= 1) { countriesVisitedTxt.style = { fill: 0xCD7F32 }; // Bronze } } // Health display var healthTxt = new Text2('Health: ♥♥♥', { size: 45, fill: 0xFF5555 }); healthTxt.anchor.set(0, 0); healthTxt.x = 20; healthTxt.y = 20; LK.gui.topLeft.addChild(healthTxt); // Update health display function updateHealthDisplay() { var hearts = ''; for (var i = 0; i < gooseHealth; i++) { hearts += '♥'; } healthTxt.setText('Health: ' + hearts); } // Create the pond (play area) pond = game.addChild(new Pond()); pond.x = 2048 / 2; pond.y = 2732 / 2; pond.innerRadius = 400; // Safe swimming area pond.outerRadius = 850; // Pond edge // Create the goose (player character) goose = game.addChild(new Goose()); goose.x = 2048 / 2; goose.y = 2732 / 2 + 600; // Create the swan (enemy) swan = game.addChild(new Swan()); swan.x = 2048 / 2; swan.y = 2732 / 2 - 600; // Create drowning effect drowning = game.addChild(new Drowning()); drowning.visible = false; drowning.alpha = 0; // Spawn chips around the pond function spawnChips() { for (var i = 0; i < chipCount; i++) { var chip = new Chip(); var angle = Math.random() * Math.PI * 2; var distance = Math.random() * 700 + 200; chip.x = pond.x + Math.cos(angle) * distance; chip.y = pond.y + Math.sin(angle) * distance; // Make sure chips are within pond boundaries var dx = chip.x - pond.x; var dy = chip.y - pond.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 850) { // Adjust to keep within pond chip.x = pond.x + dx / dist * 850; chip.y = pond.y + dy / dist * 850; } chips.push(chip); game.addChild(chip); } } // Spawn initial chips spawnChips(); // Spawn initial humans function spawnHuman() { if (humans.length < maxHumans) { var human = new Human(); // Position human around the pond edges var angle = Math.random() * Math.PI * 2; var distance = pond.outerRadius + 100 + Math.random() * 200; human.x = pond.x + Math.cos(angle) * distance; human.y = pond.y + Math.sin(angle) * distance; // Set initial target to another spot around the pond var targetAngle = angle + (Math.random() * Math.PI * 0.5 - Math.PI * 0.25); human.setTarget(pond.x + Math.cos(targetAngle) * distance, pond.y + Math.sin(targetAngle) * distance); // Fill bread supply human.refillBread(); humans.push(human); game.addChild(human); return human; } return null; } // Spawn initial humans for (var i = 0; i < 2; i++) { spawnHuman(); } // Play background music LK.playMusic('bgMusic', { loop: true }); // Handle movement function handleMove(x, y, obj) { if (dragNode && gameActive) { // Limit goose movement to within the pond boundaries var dx = x - pond.x; var dy = y - pond.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 850) { // Keep goose within the pond boundaries dragNode.x = pond.x + dx / dist * 850; dragNode.y = pond.y + dy / dist * 850; } else { dragNode.x = x; dragNode.y = y; } // Rotate toward movement direction var moveAngle = Math.atan2(y - dragNode.y, x - dragNode.x); dragNode.rotation = moveAngle; } } // Mouse/touch events game.move = handleMove; game.down = function (x, y, obj) { if (gameActive) { dragNode = goose; handleMove(x, y, obj); // Deactivate drowning when goose starts moving if (drowning.isActive) { drowning.deactivate(); } // Attack on tap/click goose.attack(); // Special effect when having atomic bomb if (hasBomb) { LK.effects.flashScreen(0xff0000, 500); } } }; game.up = function (x, y, obj) { dragNode = null; }; // Main game update loop game.update = function () { if (!gameActive) return; // Update game entities goose.update(); swan.update(); if (chocolate) { chocolate.update(); } if (painkiller) { painkiller.update(); } // Drowning mechanics - check how far goose is from pond center var dx = goose.x - pond.x; var dy = goose.y - pond.y; var distFromCenter = Math.sqrt(dx * dx + dy * dy); lastPondDistance = distFromCenter; // Different water zones if (distFromCenter > pond.outerRadius) { // Outside the pond - no drowning drowning.deactivate(); drowning.visible = false; isInShallowWater = false; } else if (distFromCenter > pond.innerRadius) { // In the shallow area - safe swimming isInShallowWater = true; drowning.deactivate(); drowning.visible = false; } else { // In the deep area - risk of drowning isInShallowWater = false; // Only start drowning if goose isn't moving if (dragNode !== goose) { if (!drowning.isActive) { drowning.activate(); drowning.visible = true; drowning.x = goose.x; drowning.y = goose.y; } else { // Update drowning position to follow goose drowning.x = goose.x; drowning.y = goose.y; // Check if drowning is complete if (drowning.update()) { // Goose drowned - game over LK.getSound('hit').play(); LK.effects.flashScreen(0x0066ff, 1000); // Update high score if needed if (LK.getScore() > highScore) { highScore = LK.getScore(); storage.highScore = highScore; highScoreTxt.setText("High Score: " + highScore); } // End the game gameActive = false; LK.showGameOver(); } } } else { // Goose is moving, deactivate drowning drowning.deactivate(); } } // Chocolate spawn logic chocolateTimer++; if (!chocolate && chocolateTimer > 480 && Math.random() < 0.008) { chocolate = new Chocolate(); var angle = Math.random() * Math.PI * 2; var distance = Math.random() * 600 + 150; chocolate.x = pond.x + Math.cos(angle) * distance; chocolate.y = pond.y + Math.sin(angle) * distance; game.addChild(chocolate); chocolateTimer = 0; // Store goose position as normal target swanNormalTarget = { x: goose.x, y: goose.y }; // Make swan target chocolate swanTargetingChocolate = true; } // Set swan target based on chocolate presence if (swanTargetingChocolate && chocolate && !chocolate.isConsumed) { swan.setTarget(chocolate.x, chocolate.y); } else { swan.setTarget(goose.x, goose.y); swanTargetingChocolate = false; } // Atomic bomb spawn logic bombTimer++; if (!atomicBomb && !hasBomb && bombTimer > 600 && Math.random() < 0.005) { atomicBomb = new AtomicBomb(); var angle = Math.random() * Math.PI * 2; var distance = Math.random() * 600 + 150; atomicBomb.x = pond.x + Math.cos(angle) * distance; atomicBomb.y = pond.y + Math.sin(angle) * distance; game.addChild(atomicBomb); bombTimer = 0; } // Check for goose collecting chips for (var i = chips.length - 1; i >= 0; i--) { if (!chips[i].isCollected && goose.intersects(chips[i])) { if (chips[i].collect()) { // Increase score LK.setScore(LK.getScore() + 1); scoreTxt.setText("Score: " + LK.getScore()); // Increase swan aggression swan.increaseAggression(); // Remove the chip from the array chips.splice(i, 1); // Spawn a new chip if needed if (chips.length < 5) { var chip = new Chip(); var angle = Math.random() * Math.PI * 2; var distance = Math.random() * 700 + 200; chip.x = pond.x + Math.cos(angle) * distance; chip.y = pond.y + Math.sin(angle) * distance; chips.push(chip); game.addChild(chip); } } } } // Check for goose attack hitting swan if (goose.isAttacking && goose.intersects(swan) && swan.stunned <= 0) { LK.getSound('hit').play(); swan.stun(60); // Stun for 1 second (60 frames) // Push swan away slightly var dx = swan.x - goose.x; var dy = swan.y - goose.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { tween(swan, { x: swan.x + dx / dist * 100, y: swan.y + dy / dist * 100 }, { duration: 300, easing: tween.easeOut }); } } // Check for swan attack hitting goose if (swan.isAttacking && swan.intersects(goose) && goose.stunned <= 0) { LK.getSound('hit').play(); goose.stun(30); // Stun for 0.5 seconds (30 frames) // Reduce health when hit gooseHealth--; updateHealthDisplay(); // Health loss animation var damageEffect = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, x: goose.x, y: goose.y, scaleX: 2, scaleY: 2, alpha: 0.5 }); damageEffect.tint = 0xFF0000; game.addChild(damageEffect); // Animate damage effect tween(damageEffect, { alpha: 0, scaleX: 3, scaleY: 3 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(damageEffect); } }); // Game over if health reaches zero or swan's aggression is very high if (gooseHealth <= 0 || swan.aggressionLevel > 7 && Math.random() < 0.2) { // Update high score if needed if (LK.getScore() > highScore) { highScore = LK.getScore(); storage.highScore = highScore; highScoreTxt.setText("High Score: " + highScore); } // Flash screen red LK.effects.flashScreen(0xff0000, 1000); // End the game gameActive = false; LK.showGameOver(); } } // Check for swan consuming chocolate if (chocolate && !chocolate.isConsumed && swan.intersects(chocolate)) { if (chocolate.consume()) { // Swan gets distracted by chocolate swan.stun(120); // Stun for 2 seconds (120 frames) swan.aggressionLevel = Math.max(1, swan.aggressionLevel - 1); // Reduce aggression // Play eating sound LK.getSound('eat').play(); // Reset chocolate chocolate = null; chocolateTimer = 0; swanTargetingChocolate = false; } } // Painkiller spawn logic painkillerTimer++; if (!painkiller && painkillerTimer > 420 && gooseHealth < maxGooseHealth && Math.random() < 0.006) { painkiller = new Painkiller(); var angle = Math.random() * Math.PI * 2; var distance = Math.random() * 600 + 200; painkiller.x = pond.x + Math.cos(angle) * distance; painkiller.y = pond.y + Math.sin(angle) * distance; game.addChild(painkiller); painkillerTimer = 0; } // Check for painkiller collection if (painkiller && !painkiller.isCollected && goose.intersects(painkiller)) { if (painkiller.collect()) { // Increase health gooseHealth = Math.min(maxGooseHealth, gooseHealth + 1); updateHealthDisplay(); // Health up animation var healthUpTxt = new Text2("+1 ♥", { size: 60, fill: 0xFF5555 }); healthUpTxt.anchor.set(0.5, 0.5); healthUpTxt.x = goose.x; healthUpTxt.y = goose.y - 80; game.addChild(healthUpTxt); // Animate health text tween(healthUpTxt, { y: healthUpTxt.y - 100, alpha: 0 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(healthUpTxt); } }); // Play sound LK.getSound('eat').play(); // Reset painkiller painkiller = null; painkillerTimer = 0; } } // Check for atomic bomb collection if (atomicBomb && !hasBomb && goose.intersects(atomicBomb) && atomicBomb.collect()) { // Pulse animation for the indicator var _pulseIndicator = function pulseIndicator() { tween(indicatorGlow, { alpha: 0.3, scaleX: 0.5, scaleY: 0.5 }, { duration: 600, easing: tween.easeInOut, onFinish: function onFinish() { tween(indicatorGlow, { alpha: 0.6, scaleX: 0.4, scaleY: 0.4 }, { duration: 600, easing: tween.easeInOut, onFinish: _pulseIndicator }); } }); }; hasBomb = true; atomicBomb.visible = false; // Create bomb indicator on goose with new blue design var bombIndicator = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -80, scaleX: 0.3, scaleY: 0.3 }); bombIndicator.tint = 0x0066ff; // Electric blue to match new bomb design // Add glow effect to indicator var indicatorGlow = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, scaleX: 0.4, scaleY: 0.4, alpha: 0.6 }); indicatorGlow.tint = 0x00ffff; // Cyan glow bombIndicator.addChild(indicatorGlow); _pulseIndicator(); goose.addChild(bombIndicator); LK.getSound('eat').play(); } // Use atomic bomb when attacking with bomb collected if (hasBomb && goose.isAttacking) { hasBomb = false; // Remove bomb indicator goose.removeChild(goose.children[goose.children.length - 1]); // Create explosion at goose position var explosion = new AtomicBomb(); explosion.x = goose.x; explosion.y = goose.y; game.addChild(explosion); explosion.explode(); // Flash screen blue for freezing effect LK.effects.flashScreen(0x0066ff, 800); // Stun swan for much longer period (freeze effect) swan.stun(300); // Freeze effect - swan turns blue temporarily swan.tint = 0x88ccff; // Immobilize swan rather than pushing it away LK.setTimeout(function () { // Restore swan color after freeze effect wears off tween(swan, { tint: 0xffffff }, { duration: 1000, easing: tween.easeInOut }); }, 4000); // Reset bomb variables atomicBomb = null; bombTimer = 0; } // Country portal spawn logic countryPortalTimer++; if (countryPortalTimer > 600 && Math.random() < 0.008 && countries.length < maxActiveCountries) { // Only spawn countries if we have unvisited countries or rarely for visited ones var availableForSpawn = availableCountries.filter(function (country) { return !visitedCountries[country.name] || Math.random() < 0.2; }); if (availableForSpawn.length > 0) { // Select random country var countryData = availableForSpawn[Math.floor(Math.random() * availableForSpawn.length)]; // Create country portal var portal = new Country(); portal.setCountry(countryData.name, countryData.color); // Position in a random location, biased toward pond edges var angle = Math.random() * Math.PI * 2; var distance = Math.random() * 300 + 500; // Between 500-800 units from center portal.x = pond.x + Math.cos(angle) * distance; portal.y = pond.y + Math.sin(angle) * distance; // Ensure within pond var dx = portal.x - pond.x; var dy = portal.y - pond.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 800) { portal.x = pond.x + dx / dist * 800; portal.y = pond.y + dy / dist * 800; } portal.activate(); countries.push(portal); game.addChild(portal); countryPortalTimer = 0; } } // Update countries for (var i = countries.length - 1; i >= 0; i--) { countries[i].update(); // Check if goose enters portal if (!travelEffectActive && goose.intersects(countries[i])) { var travelResult = countries[i].travel(); if (travelResult.success) { travelEffectActive = true; // Add score bonus LK.setScore(LK.getScore() + travelResult.scoreBonus); scoreTxt.setText("Score: " + LK.getScore()); // Mark country as visited visitedCountries[travelResult.countryName] = true; updateCountriesVisited(); // Travel effect var countryName = travelResult.countryName; var countryColor = countries[i].countryColor; // Flash screen with country color LK.effects.flashScreen(countryColor, 800); // Display travel message var travelText = new Text2("Traveling to " + countryName + "!", { size: 100, fill: countryColor }); travelText.anchor.set(0.5, 0.5); travelText.x = 2048 / 2; travelText.y = 2732 / 2; travelText.alpha = 0; game.addChild(travelText); // Animate travel text tween(travelText, { alpha: 1, scaleX: 1.2, scaleY: 1.2 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { tween(travelText, { alpha: 0, y: travelText.y - 100 }, { duration: 800, delay: 1000, easing: tween.easeIn, onFinish: function onFinish() { game.removeChild(travelText); } }); } }); // Change background tint temporarily to represent country var originalTint = pond.children[0].tint; tween(pond.children[0], { tint: countryColor }, { duration: 1000, onFinish: function onFinish() { LK.setTimeout(function () { tween(pond.children[0], { tint: originalTint }, { duration: 1000, onFinish: function onFinish() { travelEffectActive = false; } }); }, 3000); } }); // Stun swan briefly during travel transition swan.stun(120); } } // Remove expired portals if (countries[i].travelCooldown <= 0 && Math.random() < 0.002) { // Fade out and remove tween(countries[i], { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 500, onFinish: function (index) { return function () { game.removeChild(countries[index]); countries.splice(index, 1); }; }(i) }); } } // Eurovision flashbang spawn logic flashbangTimer++; if (!eurovisionFlashbang && !hasFlashbang && flashbangTimer > 900 && Math.random() < 0.003) { eurovisionFlashbang = new EurovisionFlashbang(); var angle = Math.random() * Math.PI * 2; var distance = Math.random() * 650 + 100; eurovisionFlashbang.x = pond.x + Math.cos(angle) * distance; eurovisionFlashbang.y = pond.y + Math.sin(angle) * distance; game.addChild(eurovisionFlashbang); flashbangTimer = 0; } // Check for eurovision flashbang collection if (eurovisionFlashbang && !hasFlashbang && goose.intersects(eurovisionFlashbang) && eurovisionFlashbang.collect()) { hasFlashbang = true; eurovisionFlashbang.visible = false; // Create flashbang indicator on goose (sparkling effect) var flashbangIndicator = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -80, scaleX: 0.3, scaleY: 0.3 }); flashbangIndicator.tint = 0xFFD700; // Gold color goose.addChild(flashbangIndicator); LK.getSound('eat').play(); } // Use eurovision flashbang when attacking with flashbang collected if (hasFlashbang && goose.isAttacking) { var _flashNextColor = function flashNextColor() { if (flashCount < colors.length) { LK.effects.flashScreen(colors[flashCount], 300); flashCount++; LK.setTimeout(_flashNextColor, 300); } }; hasFlashbang = false; // Remove flashbang indicator goose.removeChild(goose.children[goose.children.length - 1]); // Create explosion at goose position var explosion = new EurovisionFlashbang(); explosion.x = goose.x; explosion.y = goose.y; game.addChild(explosion); explosion.explode(); // Apply Eurovision flashbang effect // Create rainbow flashing effect that stuns all characters var colors = [0xFF0000, 0xFF7F00, 0xFFFF00, 0x00FF00, 0x0000FF, 0x4B0082, 0x9400D3]; var flashCount = 0; _flashNextColor(); // Stun swan for very long period swan.stun(360); // Make swan confused (move in random direction) var randomAngle = Math.random() * Math.PI * 2; var randomDistance = 400; tween(swan, { x: swan.x + Math.cos(randomAngle) * randomDistance, y: swan.y + Math.sin(randomAngle) * randomDistance }, { duration: 1000, easing: tween.elasticOut }); // Reset flashbang variables eurovisionFlashbang = null; flashbangTimer = 0; } // Human spawn logic humanSpawnTimer--; if (humanSpawnTimer <= 0 && humans.length < maxHumans) { spawnHuman(); humanSpawnTimer = 300 + Math.floor(Math.random() * 300); } // Update humans and bread for (var i = humans.length - 1; i >= 0; i--) { var human = humans[i]; human.update(); // Humans throw bread randomly if (Math.random() < 0.005 && human.breadCount > 0) { var breadPosition = human.throwBread(pond.x, pond.y); if (breadPosition) { var bread = new Bread(); bread.x = breadPosition.x; bread.y = breadPosition.y; // Check if bread landed in water var dx = bread.x - pond.x; var dy = bread.y - pond.y; var distFromCenter = Math.sqrt(dx * dx + dy * dy); if (distFromCenter < pond.outerRadius) { bread.startSinking(); } breadPieces.push(bread); game.addChild(bread); } } // Human movement around pond if (Math.random() < 0.01 && gooseChasingHuman !== human) { var newAngle = Math.random() * Math.PI * 2; var newDistance = pond.outerRadius + 100 + Math.random() * 200; human.setTarget(pond.x + Math.cos(newAngle) * newDistance, pond.y + Math.sin(newAngle) * newDistance); } // Goose scares human if (goose.intersects(human) && !human.isAngry) { // Human reacts to goose if (human.becomeAngry()) { // Human runs away from goose var runAngle = Math.atan2(human.y - goose.y, human.x - goose.x); var runDistance = pond.outerRadius + 300; human.setTarget(pond.x + Math.cos(runAngle) * runDistance, pond.y + Math.sin(runAngle) * runDistance); // Running animation human.speed = 4; // Chance to drop bread in panic if (human.breadCount > 0 && Math.random() < 0.5) { var breadPosition = human.throwBread(human.x + Math.random() * 100 - 50, human.y + Math.random() * 100 - 50); if (breadPosition) { var bread = new Bread(); bread.x = breadPosition.x; bread.y = breadPosition.y; breadPieces.push(bread); game.addChild(bread); } } // Add score for scaring human LK.setScore(LK.getScore() + 2); scoreTxt.setText("Score: " + LK.getScore()); // Show point popup var pointsTxt = new Text2("+2", { size: 60, fill: 0xFFFFFF }); pointsTxt.anchor.set(0.5, 0.5); pointsTxt.x = human.x; pointsTxt.y = human.y - 80; game.addChild(pointsTxt); // Animate points popup tween(pointsTxt, { y: pointsTxt.y - 80, alpha: 0 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(pointsTxt); } }); // Set human as target for goose chase effect gooseChasingHuman = human; chasingTimeout = 180; // 3 seconds timeout } } // Remove humans that have run too far var distanceFromPond = Math.sqrt(Math.pow(human.x - pond.x, 2) + Math.pow(human.y - pond.y, 2)); if (distanceFromPond > pond.outerRadius + 800) { // Human left the scene, remove them tween(human, { alpha: 0 }, { duration: 500, onFinish: function (index) { return function () { game.removeChild(humans[index]); humans.splice(index, 1); }; }(i) }); } } // Update chasing timeout if (gooseChasingHuman !== null) { chasingTimeout--; if (chasingTimeout <= 0) { gooseChasingHuman = null; } } // Update bread pieces for (var i = breadPieces.length - 1; i >= 0; i--) { var bread = breadPieces[i]; bread.update(); // Check for bread collection by birds if (!bread.isConsumed) { // Goose can collect bread for points if (goose.intersects(bread)) { if (bread.consume()) { // Add score LK.setScore(LK.getScore() + 1); scoreTxt.setText("Score: " + LK.getScore()); // Remove from array breadPieces.splice(i, 1); // Play eat sound LK.getSound('eat').play(); } } // Swan can collect bread too, calming it temporarily else if (swan.intersects(bread)) { if (bread.consume()) { // Calm swan temporarily swan.aggressionLevel = Math.max(1, swan.aggressionLevel - 0.5); swan.stun(60); // 1 second stun // Remove from array breadPieces.splice(i, 1); // Play eat sound LK.getSound('eat').play(); } } // Remove bread that's no longer visible else if (bread.alpha <= 0) { breadPieces.splice(i, 1); game.removeChild(bread); } } } // Check for win condition: collect 50 chips if (LK.getScore() >= 50) { // Update high score if (LK.getScore() > highScore) { highScore = LK.getScore(); storage.highScore = highScore; highScoreTxt.setText("High Score: " + highScore); } // End the game with a win gameActive = false; LK.showYouWin(); } };
===================================================================
--- original.js
+++ change.js
@@ -125,8 +125,85 @@
// Start electric pulsing
startElectricAnimation();
return self;
});
+var Bread = Container.expand(function () {
+ var self = Container.call(this);
+ // Create bread visual
+ var breadBody = self.attachAsset('centerCircle', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.5,
+ scaleY: 0.3
+ });
+ breadBody.tint = 0xE8B96F; // Brown bread color
+ // Create crust detail
+ var crust = LK.getAsset('centerCircle', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.52,
+ scaleY: 0.32
+ });
+ crust.tint = 0xC68642; // Darker crust color
+ self.addChild(crust);
+ self.isConsumed = false;
+ self.timeLeft = 360; // 6 seconds at 60fps
+ self.sinkingSpeed = 0.5;
+ self.inWater = false;
+ // Bread consumption
+ self.consume = function () {
+ if (!self.isConsumed) {
+ self.isConsumed = true;
+ // Consumption animation
+ tween(self, {
+ alpha: 0,
+ scaleX: 0.1,
+ scaleY: 0.1
+ }, {
+ duration: 300,
+ onFinish: function onFinish() {
+ self.visible = false;
+ }
+ });
+ return true;
+ }
+ return false;
+ };
+ // Start sinking animation when bread hits water
+ self.startSinking = function () {
+ if (!self.inWater) {
+ self.inWater = true;
+ // Make bread rotate slowly while sinking
+ tween(self, {
+ rotation: Math.PI * 0.5 * (Math.random() > 0.5 ? 1 : -1)
+ }, {
+ duration: 3000,
+ easing: tween.easeInOut
+ });
+ }
+ };
+ // Update function
+ self.update = function () {
+ self.timeLeft--;
+ // Sink when in water
+ if (self.inWater) {
+ self.y += self.sinkingSpeed;
+ // Fade out as it sinks
+ if (self.timeLeft < 180) {
+ self.alpha = Math.max(0, self.timeLeft / 180);
+ }
+ }
+ // Pulse when about to disappear
+ if (self.timeLeft < 60 && !self.inWater) {
+ self.alpha = 0.5 + Math.sin(self.timeLeft * 0.2) * 0.5;
+ }
+ // Despawn when time runs out
+ if (self.timeLeft <= 0 && !self.isConsumed) {
+ self.consume();
+ }
+ };
+ return self;
+});
var Chip = Container.expand(function () {
var self = Container.call(this);
var chipGraphic = self.attachAsset('chip', {
anchorX: 0.5,
@@ -660,31 +737,172 @@
}
};
return self;
});
-var PeptoBismol = Container.expand(function () {
+var Human = Container.expand(function () {
var self = Container.call(this);
- // Create Pepto-Bismol graphic (pink medicine bottle)
- var bottleBody = self.attachAsset('centerCircle', {
+ // Create human body
+ var body = self.attachAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
+ scaleX: 0.9,
+ scaleY: 1.5
+ });
+ body.tint = 0xFFD2B7; // Skin tone
+ // Add clothes
+ var clothes = LK.getAsset('centerCircle', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 1.0,
+ scaleY: 1.0,
+ y: 20
+ });
+ clothes.tint = Math.random() > 0.5 ? 0x3498DB : 0xE74C3C; // Random blue or red
+ self.addChild(clothes);
+ // Add head
+ var head = LK.getAsset('centerCircle', {
+ anchorX: 0.5,
+ anchorY: 0.5,
scaleX: 0.6,
- scaleY: 0.8
+ scaleY: 0.6,
+ y: -50
});
- bottleBody.tint = 0xFF69B4; // Hot pink color
- // Add label to bottle
- var bottleCap = LK.getAsset('centerCircle', {
+ head.tint = 0xFFD2B7; // Same skin tone as body
+ self.addChild(head);
+ // Properties
+ self.speed = 1 + Math.random() * 1.5;
+ self.targetX = 0;
+ self.targetY = 0;
+ self.breadCount = 0;
+ self.maxBread = 3;
+ self.lastBreadThrow = 0;
+ self.breadCooldown = 120 + Math.floor(Math.random() * 240); // 2-6 second cooldown
+ self.isAngry = false;
+ // Set target position
+ self.setTarget = function (x, y) {
+ self.targetX = x;
+ self.targetY = y;
+ };
+ // Make human throw bread
+ self.throwBread = function (pondX, pondY) {
+ if (self.breadCount > 0 && self.lastBreadThrow <= 0) {
+ self.breadCount--;
+ self.lastBreadThrow = self.breadCooldown;
+ // Calculate throw position (toward pond center)
+ var dx = pondX - self.x;
+ var dy = pondY - self.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ var throwDist = Math.min(dist * 0.7, 300);
+ return {
+ x: self.x + dx / dist * throwDist,
+ y: self.y + dy / dist * throwDist
+ };
+ }
+ return null;
+ };
+ // Make human angry at goose
+ self.becomeAngry = function () {
+ if (!self.isAngry) {
+ self.isAngry = true;
+ body.tint = 0xFFB2B7; // Slightly redder skin tone when angry
+ // Angry animation
+ tween(self, {
+ scaleX: 1.2,
+ scaleY: 1.2
+ }, {
+ duration: 300,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(self, {
+ scaleX: 1.0,
+ scaleY: 1.0
+ }, {
+ duration: 300,
+ easing: tween.easeOut
+ });
+ }
+ });
+ return true;
+ }
+ return false;
+ };
+ // Make human happy (feed birds)
+ self.refillBread = function () {
+ self.breadCount = self.maxBread;
+ // Happy animation
+ tween(head, {
+ y: -60
+ }, {
+ duration: 300,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(head, {
+ y: -50
+ }, {
+ duration: 300,
+ easing: tween.easeInOut
+ });
+ }
+ });
+ };
+ // Update function
+ self.update = function () {
+ if (self.lastBreadThrow > 0) {
+ self.lastBreadThrow--;
+ }
+ // Move toward target
+ var dx = self.targetX - self.x;
+ var dy = self.targetY - self.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist > 10) {
+ self.x += dx / dist * self.speed;
+ self.y += dy / dist * self.speed;
+ // Flip based on movement direction
+ if (dx < 0) {
+ self.scale.x = -1;
+ } else {
+ self.scale.x = 1;
+ }
+ }
+ // Calm down after some time
+ if (self.isAngry && Math.random() < 0.001) {
+ self.isAngry = false;
+ body.tint = 0xFFD2B7; // Normal skin tone
+ }
+ };
+ return self;
+});
+var Painkiller = Container.expand(function () {
+ var self = Container.call(this);
+ // Create painkiller item (white pill with red cross)
+ var pillBody = self.attachAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
+ scaleX: 0.7,
+ scaleY: 0.4
+ });
+ pillBody.tint = 0xFFFFFF; // White pill
+ // Add red cross to indicate healing
+ var redCross = LK.getAsset('centerCircle', {
+ anchorX: 0.5,
+ anchorY: 0.5,
scaleX: 0.4,
- scaleY: 0.2,
- y: -30
+ scaleY: 0.1
});
- bottleCap.tint = 0xFFFFFF; // White cap
- self.addChild(bottleCap);
+ redCross.tint = 0xFF0000; // Red
+ self.addChild(redCross);
+ // Add vertical line of cross
+ var redCrossVert = LK.getAsset('centerCircle', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.1,
+ scaleY: 0.4
+ });
+ redCrossVert.tint = 0xFF0000; // Red
+ self.addChild(redCrossVert);
self.isCollected = false;
self.timeLeft = 360; // 6 seconds at 60fps
- // Pepto collection
+ // Painkiller collection
self.collect = function () {
if (!self.isCollected) {
self.isCollected = true;
// Collection animation
@@ -701,8 +919,9 @@
return true;
}
return false;
};
+ // Update function to handle pill lifetime
self.update = function () {
self.timeLeft--;
// Pulse when about to disappear
if (self.timeLeft < 60) {
@@ -711,30 +930,8 @@
if (self.timeLeft <= 0 && !self.isCollected) {
self.collect();
}
};
- // Healing pulsing animation
- function startPulseAnimation() {
- tween(bottleBody, {
- scaleX: 0.65,
- scaleY: 0.85
- }, {
- duration: 800,
- easing: tween.easeInOut,
- onFinish: function onFinish() {
- tween(bottleBody, {
- scaleX: 0.6,
- scaleY: 0.8
- }, {
- duration: 800,
- easing: tween.easeInOut,
- onFinish: startPulseAnimation
- });
- }
- });
- }
- // Start pulsing
- startPulseAnimation();
return self;
});
var Pond = Container.expand(function () {
var self = Container.call(this);
@@ -910,12 +1107,19 @@
x: 0,
y: 0
};
var swanTargetingChocolate = false;
-var gooseHealth = 3; // Starting health
-var maxGooseHealth = 5; // Maximum health
-var peptoBismol = null;
-var peptoBismolTimer = 0;
+var painkiller = null;
+var painkillerTimer = 0;
+var gooseHealth = 3; // Initial health
+var maxGooseHealth = 5; // Maximum health possible
+// Human-related variables
+var humans = [];
+var maxHumans = 3;
+var humanSpawnTimer = 180;
+var breadPieces = [];
+var gooseChasingHuman = null;
+var chasingTimeout = 0;
// Country variables
var countries = [];
var availableCountries = [{
name: "France",
@@ -971,34 +1175,8 @@
countriesVisitedTxt.setText("Countries: 0");
countriesVisitedTxt.anchor.set(0.5, 0);
countriesVisitedTxt.y = 150;
LK.gui.top.addChild(countriesVisitedTxt);
-// Create health display
-var healthTxt = new Text2('Health: 3/5', {
- size: 45,
- fill: 0xFF69B4
-});
-healthTxt.anchor.set(0.5, 0);
-healthTxt.y = 210;
-LK.gui.top.addChild(healthTxt);
-// Update health display function
-function updateHealthDisplay() {
- healthTxt.setText("Health: " + gooseHealth + "/" + maxGooseHealth);
- // Change color based on health
- if (gooseHealth <= 1) {
- healthTxt.style = {
- fill: 0xFF0000 // Red when critical
- };
- } else if (gooseHealth <= 2) {
- healthTxt.style = {
- fill: 0xFFA500 // Orange when low
- };
- } else {
- healthTxt.style = {
- fill: 0xFF69B4 // Pink when healthy
- };
- }
-}
// Update countries visited text
function updateCountriesVisited() {
var count = Object.keys(visitedCountries).length;
countriesVisitedTxt.setText("Countries: " + count);
@@ -1016,8 +1194,25 @@
fill: 0xCD7F32
}; // Bronze
}
}
+// Health display
+var healthTxt = new Text2('Health: ♥♥♥', {
+ size: 45,
+ fill: 0xFF5555
+});
+healthTxt.anchor.set(0, 0);
+healthTxt.x = 20;
+healthTxt.y = 20;
+LK.gui.topLeft.addChild(healthTxt);
+// Update health display
+function updateHealthDisplay() {
+ var hearts = '';
+ for (var i = 0; i < gooseHealth; i++) {
+ hearts += '♥';
+ }
+ healthTxt.setText('Health: ' + hearts);
+}
// Create the pond (play area)
pond = game.addChild(new Pond());
pond.x = 2048 / 2;
pond.y = 2732 / 2;
@@ -1057,10 +1252,32 @@
}
}
// Spawn initial chips
spawnChips();
-// Initialize health display
-updateHealthDisplay();
+// Spawn initial humans
+function spawnHuman() {
+ if (humans.length < maxHumans) {
+ var human = new Human();
+ // Position human around the pond edges
+ var angle = Math.random() * Math.PI * 2;
+ var distance = pond.outerRadius + 100 + Math.random() * 200;
+ human.x = pond.x + Math.cos(angle) * distance;
+ human.y = pond.y + Math.sin(angle) * distance;
+ // Set initial target to another spot around the pond
+ var targetAngle = angle + (Math.random() * Math.PI * 0.5 - Math.PI * 0.25);
+ human.setTarget(pond.x + Math.cos(targetAngle) * distance, pond.y + Math.sin(targetAngle) * distance);
+ // Fill bread supply
+ human.refillBread();
+ humans.push(human);
+ game.addChild(human);
+ return human;
+ }
+ return null;
+}
+// Spawn initial humans
+for (var i = 0; i < 2; i++) {
+ spawnHuman();
+}
// Play background music
LK.playMusic('bgMusic', {
loop: true
});
@@ -1113,8 +1330,11 @@
swan.update();
if (chocolate) {
chocolate.update();
}
+ if (painkiller) {
+ painkiller.update();
+ }
// Drowning mechanics - check how far goose is from pond center
var dx = goose.x - pond.x;
var dy = goose.y - pond.y;
var distFromCenter = Math.sqrt(dx * dx + dy * dy);
@@ -1246,26 +1466,37 @@
// Check for swan attack hitting goose
if (swan.isAttacking && swan.intersects(goose) && goose.stunned <= 0) {
LK.getSound('hit').play();
goose.stun(30); // Stun for 0.5 seconds (30 frames)
- // Lose health when hit by swan
- gooseHealth = Math.max(0, gooseHealth - 1);
+ // Reduce health when hit
+ gooseHealth--;
updateHealthDisplay();
- // Health pulse effect
- tween(goose, {
+ // Health loss animation
+ var damageEffect = LK.getAsset('centerCircle', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: goose.x,
+ y: goose.y,
+ scaleX: 2,
+ scaleY: 2,
alpha: 0.5
+ });
+ damageEffect.tint = 0xFF0000;
+ game.addChild(damageEffect);
+ // Animate damage effect
+ tween(damageEffect, {
+ alpha: 0,
+ scaleX: 3,
+ scaleY: 3
}, {
- duration: 200,
+ duration: 500,
+ easing: tween.easeOut,
onFinish: function onFinish() {
- tween(goose, {
- alpha: 1
- }, {
- duration: 200
- });
+ game.removeChild(damageEffect);
}
});
- // Game over if health reaches zero or swan's aggression is high enough
- if (gooseHealth <= 0 || swan.aggressionLevel > 7) {
+ // Game over if health reaches zero or swan's aggression is very high
+ if (gooseHealth <= 0 || swan.aggressionLevel > 7 && Math.random() < 0.2) {
// Update high score if needed
if (LK.getScore() > highScore) {
highScore = LK.getScore();
storage.highScore = highScore;
@@ -1291,63 +1522,50 @@
chocolateTimer = 0;
swanTargetingChocolate = false;
}
}
- // Pepto-Bismol spawn logic
- peptoBismolTimer++;
- if (!peptoBismol && peptoBismolTimer > 540 && gooseHealth < maxGooseHealth && Math.random() < 0.006) {
- peptoBismol = new PeptoBismol();
+ // Painkiller spawn logic
+ painkillerTimer++;
+ if (!painkiller && painkillerTimer > 420 && gooseHealth < maxGooseHealth && Math.random() < 0.006) {
+ painkiller = new Painkiller();
var angle = Math.random() * Math.PI * 2;
var distance = Math.random() * 600 + 200;
- peptoBismol.x = pond.x + Math.cos(angle) * distance;
- peptoBismol.y = pond.y + Math.sin(angle) * distance;
- game.addChild(peptoBismol);
- peptoBismolTimer = 0;
+ painkiller.x = pond.x + Math.cos(angle) * distance;
+ painkiller.y = pond.y + Math.sin(angle) * distance;
+ game.addChild(painkiller);
+ painkillerTimer = 0;
}
- // Update Pepto-Bismol if it exists
- if (peptoBismol) {
- peptoBismol.update();
- }
- // Check for goose collecting Pepto-Bismol
- if (peptoBismol && !peptoBismol.isCollected && goose.intersects(peptoBismol)) {
- if (peptoBismol.collect()) {
+ // Check for painkiller collection
+ if (painkiller && !painkiller.isCollected && goose.intersects(painkiller)) {
+ if (painkiller.collect()) {
// Increase health
gooseHealth = Math.min(maxGooseHealth, gooseHealth + 1);
updateHealthDisplay();
- // Health gained effect
+ // Health up animation
+ var healthUpTxt = new Text2("+1 ♥", {
+ size: 60,
+ fill: 0xFF5555
+ });
+ healthUpTxt.anchor.set(0.5, 0.5);
+ healthUpTxt.x = goose.x;
+ healthUpTxt.y = goose.y - 80;
+ game.addChild(healthUpTxt);
+ // Animate health text
+ tween(healthUpTxt, {
+ y: healthUpTxt.y - 100,
+ alpha: 0
+ }, {
+ duration: 1000,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ game.removeChild(healthUpTxt);
+ }
+ });
+ // Play sound
LK.getSound('eat').play();
- LK.effects.flashScreen(0xFF69B4, 500);
- // Create healing particles
- for (var i = 0; i < 5; i++) {
- var particle = LK.getAsset('centerCircle', {
- anchorX: 0.5,
- anchorY: 0.5,
- scaleX: 0.2,
- scaleY: 0.2,
- x: goose.x + (Math.random() - 0.5) * 50,
- y: goose.y + (Math.random() - 0.5) * 50
- });
- particle.tint = 0xFF69B4;
- game.addChild(particle);
- // Animate particle
- tween(particle, {
- alpha: 0,
- scaleX: 0,
- scaleY: 0,
- y: particle.y - 50
- }, {
- duration: 800,
- easing: tween.easeOut,
- onFinish: function (p) {
- return function () {
- game.removeChild(p);
- };
- }(particle)
- });
- }
- // Reset Pepto-Bismol
- peptoBismol = null;
- peptoBismolTimer = 0;
+ // Reset painkiller
+ painkiller = null;
+ painkillerTimer = 0;
}
}
// Check for atomic bomb collection
if (atomicBomb && !hasBomb && goose.intersects(atomicBomb) && atomicBomb.collect()) {
@@ -1622,8 +1840,152 @@
// Reset flashbang variables
eurovisionFlashbang = null;
flashbangTimer = 0;
}
+ // Human spawn logic
+ humanSpawnTimer--;
+ if (humanSpawnTimer <= 0 && humans.length < maxHumans) {
+ spawnHuman();
+ humanSpawnTimer = 300 + Math.floor(Math.random() * 300);
+ }
+ // Update humans and bread
+ for (var i = humans.length - 1; i >= 0; i--) {
+ var human = humans[i];
+ human.update();
+ // Humans throw bread randomly
+ if (Math.random() < 0.005 && human.breadCount > 0) {
+ var breadPosition = human.throwBread(pond.x, pond.y);
+ if (breadPosition) {
+ var bread = new Bread();
+ bread.x = breadPosition.x;
+ bread.y = breadPosition.y;
+ // Check if bread landed in water
+ var dx = bread.x - pond.x;
+ var dy = bread.y - pond.y;
+ var distFromCenter = Math.sqrt(dx * dx + dy * dy);
+ if (distFromCenter < pond.outerRadius) {
+ bread.startSinking();
+ }
+ breadPieces.push(bread);
+ game.addChild(bread);
+ }
+ }
+ // Human movement around pond
+ if (Math.random() < 0.01 && gooseChasingHuman !== human) {
+ var newAngle = Math.random() * Math.PI * 2;
+ var newDistance = pond.outerRadius + 100 + Math.random() * 200;
+ human.setTarget(pond.x + Math.cos(newAngle) * newDistance, pond.y + Math.sin(newAngle) * newDistance);
+ }
+ // Goose scares human
+ if (goose.intersects(human) && !human.isAngry) {
+ // Human reacts to goose
+ if (human.becomeAngry()) {
+ // Human runs away from goose
+ var runAngle = Math.atan2(human.y - goose.y, human.x - goose.x);
+ var runDistance = pond.outerRadius + 300;
+ human.setTarget(pond.x + Math.cos(runAngle) * runDistance, pond.y + Math.sin(runAngle) * runDistance);
+ // Running animation
+ human.speed = 4;
+ // Chance to drop bread in panic
+ if (human.breadCount > 0 && Math.random() < 0.5) {
+ var breadPosition = human.throwBread(human.x + Math.random() * 100 - 50, human.y + Math.random() * 100 - 50);
+ if (breadPosition) {
+ var bread = new Bread();
+ bread.x = breadPosition.x;
+ bread.y = breadPosition.y;
+ breadPieces.push(bread);
+ game.addChild(bread);
+ }
+ }
+ // Add score for scaring human
+ LK.setScore(LK.getScore() + 2);
+ scoreTxt.setText("Score: " + LK.getScore());
+ // Show point popup
+ var pointsTxt = new Text2("+2", {
+ size: 60,
+ fill: 0xFFFFFF
+ });
+ pointsTxt.anchor.set(0.5, 0.5);
+ pointsTxt.x = human.x;
+ pointsTxt.y = human.y - 80;
+ game.addChild(pointsTxt);
+ // Animate points popup
+ tween(pointsTxt, {
+ y: pointsTxt.y - 80,
+ alpha: 0
+ }, {
+ duration: 800,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ game.removeChild(pointsTxt);
+ }
+ });
+ // Set human as target for goose chase effect
+ gooseChasingHuman = human;
+ chasingTimeout = 180; // 3 seconds timeout
+ }
+ }
+ // Remove humans that have run too far
+ var distanceFromPond = Math.sqrt(Math.pow(human.x - pond.x, 2) + Math.pow(human.y - pond.y, 2));
+ if (distanceFromPond > pond.outerRadius + 800) {
+ // Human left the scene, remove them
+ tween(human, {
+ alpha: 0
+ }, {
+ duration: 500,
+ onFinish: function (index) {
+ return function () {
+ game.removeChild(humans[index]);
+ humans.splice(index, 1);
+ };
+ }(i)
+ });
+ }
+ }
+ // Update chasing timeout
+ if (gooseChasingHuman !== null) {
+ chasingTimeout--;
+ if (chasingTimeout <= 0) {
+ gooseChasingHuman = null;
+ }
+ }
+ // Update bread pieces
+ for (var i = breadPieces.length - 1; i >= 0; i--) {
+ var bread = breadPieces[i];
+ bread.update();
+ // Check for bread collection by birds
+ if (!bread.isConsumed) {
+ // Goose can collect bread for points
+ if (goose.intersects(bread)) {
+ if (bread.consume()) {
+ // Add score
+ LK.setScore(LK.getScore() + 1);
+ scoreTxt.setText("Score: " + LK.getScore());
+ // Remove from array
+ breadPieces.splice(i, 1);
+ // Play eat sound
+ LK.getSound('eat').play();
+ }
+ }
+ // Swan can collect bread too, calming it temporarily
+ else if (swan.intersects(bread)) {
+ if (bread.consume()) {
+ // Calm swan temporarily
+ swan.aggressionLevel = Math.max(1, swan.aggressionLevel - 0.5);
+ swan.stun(60); // 1 second stun
+ // Remove from array
+ breadPieces.splice(i, 1);
+ // Play eat sound
+ LK.getSound('eat').play();
+ }
+ }
+ // Remove bread that's no longer visible
+ else if (bread.alpha <= 0) {
+ breadPieces.splice(i, 1);
+ game.removeChild(bread);
+ }
+ }
+ }
// Check for win condition: collect 50 chips
if (LK.getScore() >= 50) {
// Update high score
if (LK.getScore() > highScore) {
A potato chip. In-Game asset. 2d. High contrast. No shadows
A pond. Top down view.. In-Game asset. 2d. High contrast. No shadows
Goose. In-Game asset. 2d. High contrast. No shadows
Atomic symbol. In-Game asset. 2d. High contrast. No shadows
A fuming swan with 16 cigarettes. In-Game asset. 2d. High contrast. No shadows