User prompt
add asset for larvae
User prompt
add a larvae bug that moves downwards. it has a direction assigned at creation, either moves from left end of screen to the right, or from the right end to the left.
User prompt
the animated bug should always use the same asset as the originally clicked bug
User prompt
add a new bug type (ladybird) that moves slowly downwards but zig-zags horizontally
User prompt
refactor so that we can have multiple enemy types (bug types)
User prompt
when snapping a photo, display a white rectangle of size 600x400, centered on the clicked position, fading out quickly as a flash โช๐ก Consider importing and using the following plugins: @upit/tween.v1
Code edit (3 edits merged)
Please save this source code
User prompt
play sound when heart is added
User prompt
when adding score, check if multiple of 50 and, if so add a heart (with sound). ensure maximum 3 hearts always.
User prompt
trees only start appearing after 5 photos (score)
User prompt
fix: i'm not seeing the hearts (lives) on the top right of screen
User prompt
replace the Lives placar on the hud by icon hearts at the top right
User prompt
Grant 3 seconds immunity after losing a life, blinking the jeep โช๐ก Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
3 lives
User prompt
add sounds for snapping a picture (when clicking a bug) and car crashing (on car collisions)
User prompt
play music "safariMusc"
User prompt
move car only horizontally
User prompt
Please fix the bug: 'game.swapChildren is not a function' in or related to this line: 'game.swapChildren(stripe, game.getChildAt(0));' Line Number: 205
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Import the tween plugin;
// BaseEnemy class to represent shared enemy functionality
var BaseEnemy = Container.expand(function () {
var self = Container.call(this);
// Properties to be set by inheriting classes
self.speed = 5;
self.assetName = 'bug';
self.scoreValue = 1;
// Initialize the graphics (to be called by child classes)
self.initGraphics = function () {
var bugGraphics = self.attachAsset(self.assetName, {
anchorX: 0.5,
anchorY: 0.5
});
return bugGraphics;
};
self.update = function () {
self.y += self.speed;
};
self.down = function (x, y, obj) {
// Play photo snap sound
LK.getSound('snapPhoto').play();
// Create flash effect at position
var flash = game.addChild(new FlashEffect());
flash.x = self.x;
flash.y = self.y;
flash.showFlash();
// Increment score
LK.setScore(LK.getScore() + self.scoreValue);
// Check if score is multiple of 50 to add a life
var currentScore = LK.getScore();
if (currentScore > 0 && currentScore % 50 === 0 && lives < 3) {
lives += 1;
// Play sound for life gain
LK.getSound('liveUp').play();
// Update hearts display
for (var h = 0; h < hearts.length; h++) {
hearts[h].setActive(h < lives);
}
}
// Update score text
scoreTxt.setText('Photos: ' + LK.getScore());
// Replace with AnimatedBug
var animatedBug = game.addChild(new AnimatedBug());
animatedBug.x = self.x;
animatedBug.y = self.y;
// Set the asset name to match the clicked bug
animatedBug.assetName = self.assetName;
// Re-initialize the graphics with the correct asset
animatedBug.initGraphics();
isTouching = false; // Prevent car from moving when touching a bug
self.destroy();
};
return self;
});
// LarvaeBug class that moves downwards with left-to-right or right-to-left direction
var LarvaeBug = BaseEnemy.expand(function () {
var self = BaseEnemy.call(this);
// Set larvae bug specific properties
self.assetName = 'larvae'; // Using the larvae asset
self.speed = 4; // Slightly slower than regular bugs
self.scoreValue = 1;
self.direction = Math.random() < 0.5 ? -1 : 1; // -1 for right to left, 1 for left to right
self.horizontalSpeed = 3;
// Initialize graphics
var bugGraphics = self.initGraphics();
// Override update method for directional movement
self.update = function () {
// Move downwards
self.y += self.speed;
// Move horizontally based on direction
self.x += self.horizontalSpeed * self.direction;
// If it reaches screen boundary, reverse direction
if (self.x <= 0 || self.x >= 2048) {
self.direction *= -1;
}
};
return self;
});
// LadyBug class to represent ladybird that moves slowly and zigzags horizontally
var LadyBug = BaseEnemy.expand(function () {
var self = BaseEnemy.call(this);
// Set ladybug specific properties
self.assetName = 'ladyBug';
self.speed = 3; // Move slower than regular bugs
self.scoreValue = 2; // Worth more points
self.zigzagAmplitude = 100; // Maximum horizontal movement
self.zigzagSpeed = 0.05; // Speed of horizontal oscillation
self.initialX = 0; // Store initial X position
self.timeOffset = Math.random() * Math.PI * 2; // Random offset for zigzag pattern
// Initialize graphics
var bugGraphics = self.initGraphics();
// Override update method for zigzag movement
self.update = function () {
// Store the initial X position on first update
if (self.initialX === 0) {
self.initialX = self.x;
}
// Move downward slowly
self.y += self.speed;
// Calculate the horizontal zigzag movement using sine function
var time = LK.ticks * self.zigzagSpeed + self.timeOffset;
self.x = self.initialX + Math.sin(time) * self.zigzagAmplitude;
};
return self;
});
// EnemyFactory to create different types of enemies
// FastBug class to represent the fast bug that scrolls down the screen
var FastBug = BaseEnemy.expand(function () {
var self = BaseEnemy.call(this);
// Set fast bug specific properties
self.assetName = 'fastBug';
self.speed = 10;
self.scoreValue = 1;
// Initialize graphics
var bugGraphics = self.initGraphics();
return self;
});
var Bug = BaseEnemy.expand(function () {
var self = BaseEnemy.call(this);
// Set bug specific properties
self.assetName = 'bug';
self.speed = 5;
self.scoreValue = 1;
// Initialize graphics
var bugGraphics = self.initGraphics();
return self;
});
//<Assets used in the game will automatically appear here>
// AnimatedBug class to represent the bug that flies to the top of the screen
var AnimatedBug = BaseEnemy.expand(function () {
var self = BaseEnemy.call(this);
// Set animated bug specific properties
self.assetName = 'bug';
self.speed = 10;
self.scoreValue = 0; // No score for animated bugs
// Initialize graphics
var bugGraphics = self.initGraphics();
// Override update method for flying animation
self.update = function () {
// Determine the direction to fly to (left or right)
var direction = Math.random() < 0.5 ? -1 : 1;
// Update the x and y position
self.x += self.speed * direction * 3;
self.y -= self.speed * 3;
// Destroy the bug when it flies off the screen
if (self.y < 0 || self.x < 0 || self.x > 2048) {
self.destroy();
}
};
// Override down method - animated bugs can't be clicked
self.down = function (x, y, obj) {
// Do nothing - animated bugs can't be clicked
};
return self;
});
// FlashEffect class for camera flash when taking a photo
var FlashEffect = Container.expand(function () {
var self = Container.call(this);
// Create white rectangle for the flash
var flashGraphics = self.attachAsset('flashRect', {
anchorX: 0.5,
anchorY: 0.5
});
// Create the flash animation
self.showFlash = function () {
// Start with full visibility
flashGraphics.alpha = 1;
// Fade out quickly
tween(flashGraphics, {
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
// GrassStripe class for representing the scrolling grass stripes
var GrassStripe = Container.expand(function () {
var self = Container.call(this);
self.isDark = false; // Track if this is a dark stripe
var stripeGraphics = self.attachAsset('grassStripe', {
anchorX: 0.5,
anchorY: 0.5
});
// Set speed of scrolling
self.speed = 5;
// Method to toggle between light and dark stripe
self.setDark = function (isDark) {
self.isDark = isDark;
if (isDark) {
stripeGraphics = self.attachAsset('grassStripeDark', {
anchorX: 0.5,
anchorY: 0.5
});
} else {
stripeGraphics = self.attachAsset('grassStripe', {
anchorX: 0.5,
anchorY: 0.5
});
}
};
self.update = function () {
self.y += self.speed;
// If stripe moves off screen, reset to top
if (self.y > 2732 + self.height / 2) {
self.y = -self.height / 2;
}
};
return self;
});
// Heart class to represent lives
var Heart = Container.expand(function () {
var self = Container.call(this);
var heartGraphics = self.attachAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
self.setActive = function (active) {
heartGraphics.alpha = active ? 1 : 0.3;
};
return self;
});
// Jeep class to represent the player's vehicle
var Jeep = Container.expand(function () {
var self = Container.call(this);
var jeepGraphics = self.attachAsset('jeep', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 10;
self.isImmune = false;
self.immunityTimer = 0;
self.setImmunity = function (immune) {
self.isImmune = immune;
if (immune) {
// Create blinking effect using tweens
var _blink = function blink() {
if (!self.isImmune) {
return;
}
tween(jeepGraphics, {
alpha: 0.3
}, {
duration: 150,
onFinish: function onFinish() {
if (!self.isImmune) {
return;
}
tween(jeepGraphics, {
alpha: 1
}, {
duration: 150,
onFinish: _blink
});
}
});
};
// Start blinking effect with alternating alpha values
self.immunityTimer = LK.setTimeout(function () {
self.isImmune = false;
// Reset alpha to fully opaque when immunity ends
jeepGraphics.alpha = 1;
// Stop any ongoing blink tweens
tween.stop(jeepGraphics, {
alpha: true
});
}, 3000);
_blink();
} else {
// Clear immunity timer if immunity is turned off early
if (self.immunityTimer) {
LK.clearTimeout(self.immunityTimer);
self.immunityTimer = 0;
}
jeepGraphics.alpha = 1;
}
};
self.update = function () {
var dx = targetPosition.x - self.x;
// Only update x position, ignore vertical movement
self.x += self.speed * (dx > 0 ? 1 : dx < 0 ? -1 : 0);
// Keep y position fixed
self.y = 2732 - 200; // Fixed position at bottom of screen
};
});
var Tree = Container.expand(function () {
var self = Container.call(this);
var treeGraphics = self.attachAsset('tree', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 5;
// Create a trunk hit box for collision detection
self.trunkWidth = 60; // width of trunk collision area
self.trunkHeight = 200; // height of trunk collision area
self.trunkOffsetY = 50; // offset from center of tree
// Check if point is within the trunk area
self.trunkIntersects = function (obj) {
// Calculate trunk boundaries
var trunkLeft = self.x - self.trunkWidth / 2;
var trunkRight = self.x + self.trunkWidth / 2;
var trunkTop = self.y + self.trunkOffsetY - self.trunkHeight / 2;
var trunkBottom = self.y + self.trunkOffsetY + self.trunkHeight / 2;
// Get object boundaries
var objLeft = obj.x - obj.width / 2;
var objRight = obj.x + obj.width / 2;
var objTop = obj.y - obj.height / 2;
var objBottom = obj.y + obj.height / 2;
// Check for intersection
return !(objRight < trunkLeft || objLeft > trunkRight || objBottom < trunkTop || objTop > trunkBottom);
};
self.update = function () {
self.y += self.speed;
};
});
/****
* Initialize Game
****/
// Helper function to swap children in display list
var game = new LK.Game({
backgroundColor: 0x006400 //Init game with darker green background
});
/****
* Game Code
****/
// Helper function to swap children in display list
// Initialize game variables
function swapChildren(parent, child1, child2) {
if (!parent || !child1 || !child2) {
return;
}
// Get the index of both children
var index1 = -1;
var index2 = -1;
for (var i = 0; i < parent.children.length; i++) {
if (parent.children[i] === child1) {
index1 = i;
}
if (parent.children[i] === child2) {
index2 = i;
}
}
// If both children are found, swap them
if (index1 !== -1 && index2 !== -1) {
// Remove both children (higher index first to not affect the lower index)
var temp;
if (index1 > index2) {
temp = parent.removeChildAt(index1);
parent.addChildAt(temp, index2);
} else {
temp = parent.removeChildAt(index2);
parent.addChildAt(temp, index1);
}
}
}
var jeep;
var scoreTxt;
var deathReasonTxt;
var deathReason = "";
var isTouching = false;
var grassStripes = [];
var lives = 3;
var hearts = [];
// Function to create scrolling grass stripes
function createGrassStripes() {
// Clear existing stripes if any
for (var i = 0; i < grassStripes.length; i++) {
if (grassStripes[i]) {
grassStripes[i].destroy();
}
}
grassStripes = [];
// Create new stripes to fill the screen
var stripeHeight = 200;
var numStripes = Math.ceil(2732 / stripeHeight) + 1; // +1 for seamless scrolling
for (var i = 0; i < numStripes; i++) {
var stripe = new GrassStripe();
stripe.x = 2048 / 2;
stripe.y = i * stripeHeight;
stripe.setDark(i % 2 === 0); // Alternate between light and dark
grassStripes.push(stripe);
game.addChild(stripe);
// Make sure stripes are added at the bottom of the display list (background)
swapChildren(game, stripe, game.getChildAt(0));
}
}
// Function to initialize game elements
function initGame() {
// Reset lives to 3
lives = 3;
// Initialize grass stripes
createGrassStripes();
// Create and position the Jeep
jeep = game.addChild(new Jeep());
jeep.x = 2048 / 2;
jeep.y = 2732 - 200;
targetPosition.x = jeep.x;
targetPosition.y = jeep.y;
// Initialize score display
scoreTxt = new Text2('Photos: 0', {
size: 100,
fill: 0xFFFFFF
});
// Initialize death reason display
deathReasonTxt = new Text2('', {
size: 80,
fill: 0xFFFFFF
});
// Initialize lives display with heart icons
hearts = [];
for (var i = 0; i < 3; i++) {
var heart = new Heart();
heart.x = -300 + i * 120; // Position hearts side by side with spacing, offset from right edge
heart.y = 100; // Position at top
heart.setActive(i < lives);
hearts.push(heart);
LK.gui.topRight.addChild(heart);
}
// Initialize bugs, fastBugs and trees arrays
bugs = [];
fastBugs = [];
trees = [];
scoreTxt.anchor.set(0.5, 0);
deathReasonTxt.anchor.set(0.5, 0);
deathReasonTxt.y = 120; // Position below score text
LK.gui.top.addChild(scoreTxt);
LK.gui.top.addChild(deathReasonTxt);
}
var targetPosition = {
x: 0,
y: 0
};
game.down = function (x, y, obj) {
// Check if the touch is on a bug, if so ignore and return
for (var i = 0; i < bugs.length; i++) {
if (x >= bugs[i].x - 100 && x <= bugs[i].x + 100 && y >= bugs[i].y - 100 && y <= bugs[i].y + 100) {
return;
}
}
// Check if the touch is on a fast bug, if so ignore and return
for (var i = 0; i < fastBugs.length; i++) {
if (x >= fastBugs[i].x - 100 && x <= fastBugs[i].x + 100 && y >= fastBugs[i].y - 100 && y <= fastBugs[i].y + 100) {
return;
}
}
// Set target position for the jeep movement (horizontal only)
targetPosition.x = x;
// Keep targetPosition.y fixed to maintain jeep's vertical position
targetPosition.y = 2732 - 200;
};
game.update = function () {
// Update grass stripes
for (var i = 0; i < grassStripes.length; i++) {
grassStripes[i].update();
}
jeep.update();
// Bug spawning logic using factory
if (LK.ticks % 60 == 0) {
var newBug = EnemyFactory.createEnemy('bug');
bugs.push(newBug);
game.addChild(newBug);
}
if (LK.ticks % 180 == 0) {
var newFastBug = EnemyFactory.createEnemy('fastBug');
fastBugs.push(newFastBug);
game.addChild(newFastBug);
}
if (LK.ticks % 240 == 0) {
var newLadyBug = EnemyFactory.createEnemy('ladyBug');
bugs.push(newLadyBug);
game.addChild(newLadyBug);
}
if (LK.ticks % 200 == 0) {
var newLarvaeBug = EnemyFactory.createEnemy('larvaeBug');
bugs.push(newLarvaeBug);
game.addChild(newLarvaeBug);
}
if (LK.ticks % 180 == 0 && LK.getScore() >= 5) {
var newTree = new Tree();
newTree.x = Math.random() * 2048;
newTree.y = 0;
trees.push(newTree);
game.addChild(newTree);
}
// Bug and tree movement and collision detection logic
for (var i = bugs.length - 1; i >= 0; i--) {
bugs[i].update();
// Only check collision if it's not an AnimatedBug
if (bugs[i].intersects(jeep) && !(bugs[i] instanceof AnimatedBug) && !jeep.isImmune) {
deathReason = "Hit by a bug!";
deathReasonTxt.setText(deathReason);
LK.getSound('carCrash').play();
lives -= 1;
// Update hearts display
for (var h = 0; h < hearts.length; h++) {
hearts[h].setActive(h < lives);
}
if (lives <= 0) {
LK.showGameOver();
} else {
// Give player immunity for 3 seconds
jeep.setImmunity(true);
// Remove the bug after collision
bugs[i].destroy();
bugs.splice(i, 1);
// Flash screen to indicate damage
LK.effects.flashScreen(0xff0000, 500);
continue;
}
}
if (bugs[i].y > 2732) {
bugs[i].destroy();
bugs.splice(i, 1);
}
}
for (var i = fastBugs.length - 1; i >= 0; i--) {
fastBugs[i].update();
// Only check collision if it's not an AnimatedBug
if (fastBugs[i].intersects(jeep) && !(fastBugs[i] instanceof AnimatedBug) && !jeep.isImmune) {
deathReason = "Hit by a fast bug!";
deathReasonTxt.setText(deathReason);
LK.getSound('carCrash').play();
lives -= 1;
// Update hearts display
for (var h = 0; h < hearts.length; h++) {
hearts[h].setActive(h < lives);
}
if (lives <= 0) {
LK.showGameOver();
} else {
// Give player immunity for 3 seconds
jeep.setImmunity(true);
// Remove the fast bug after collision
fastBugs[i].destroy();
fastBugs.splice(i, 1);
// Flash screen to indicate damage
LK.effects.flashScreen(0xff0000, 500);
continue;
}
}
if (fastBugs[i].y > 2732) {
fastBugs[i].destroy();
fastBugs.splice(i, 1);
}
}
for (var i = trees.length - 1; i >= 0; i--) {
trees[i].update();
if (trees[i].trunkIntersects(jeep) && !jeep.isImmune) {
deathReason = "Crashed into a tree!";
deathReasonTxt.setText(deathReason);
LK.getSound('carCrash').play();
lives -= 1;
// Update hearts display
for (var h = 0; h < hearts.length; h++) {
hearts[h].setActive(h < lives);
}
if (lives <= 0) {
LK.showGameOver();
} else {
// Give player immunity for 3 seconds
jeep.setImmunity(true);
// Remove the tree after collision
trees[i].destroy();
trees.splice(i, 1);
// Flash screen to indicate damage
LK.effects.flashScreen(0xff0000, 500);
continue;
}
}
if (trees[i].y > 2732) {
trees[i].destroy();
trees.splice(i, 1);
}
}
};
// Initialize the game
initGame();
// Play safari background music
LK.playMusic('safariMusc');
// EnemyFactory to create different types of enemies
var EnemyFactory = function () {
// Create a specific enemy type
function createEnemy(type) {
var enemy;
switch (type) {
case 'bug':
enemy = new Bug();
break;
case 'fastBug':
enemy = new FastBug();
break;
case 'ladyBug':
enemy = new LadyBug();
break;
case 'larvaeBug':
enemy = new LarvaeBug();
break;
// Add more enemy types here
default:
enemy = new Bug();
break;
}
// Set random position at top of screen
enemy.x = Math.random() * 2048;
enemy.y = 0;
return enemy;
}
return {
createEnemy: createEnemy
};
}();
; ===================================================================
--- original.js
+++ change.js
@@ -64,9 +64,9 @@
// LarvaeBug class that moves downwards with left-to-right or right-to-left direction
var LarvaeBug = BaseEnemy.expand(function () {
var self = BaseEnemy.call(this);
// Set larvae bug specific properties
- self.assetName = 'bug'; // Using the same asset for now
+ self.assetName = 'larvae'; // Using the larvae asset
self.speed = 4; // Slightly slower than regular bugs
self.scoreValue = 1;
self.direction = Math.random() < 0.5 ? -1 : 1; // -1 for right to left, 1 for left to right
self.horizontalSpeed = 3;
Giant insect, facing down, open wings, cartoony. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Jeep car cartoony, top down view. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
cartoony heart for game hud. In-Game asset. 2d. High contrast. No shadows
ladybug insect. In-Game asset. 2d. High contrast. No shadows
larvae bug. In-Game asset. 2d. High contrast. No shadows