/**** * 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 }; }(); ;
/****
* 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
};
}();
;
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