/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0 }); /**** * Classes ****/ var Batarang = Container.expand(function () { var self = Container.call(this); var batarangGraphics = self.attachAsset('batarang', { anchorX: 0.5, anchorY: 0.5, width: 80, // Make batarang hit box smaller height: 40 // Make batarang hit box smaller }); self.active = true; self.speed = -40; // Negative speed to move upward (doubled for faster shots) self.update = function () { self.y += self.speed; batarangGraphics.rotation += 0.2; // Remove if off screen if (self.y < -50) { //{o} // Check if it's off the top of the screen self.active = false; } }; return self; }); var Batmobile = Container.expand(function () { var self = Container.call(this); self.batmobileGraphics = self.attachAsset('batmobile', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 10; self.jumpHeight = 0; self.isJumping = false; self.lane = 1; // 0 = left, 1 = center, 2 = right self.lanePositions = [600, 1024, 1448]; // x positions for the three lanes self.groundY = 2300; // ground position self.jumping = false; self.invincible = false; self.jump = function () { if (!self.jumping) { self.jumping = true; // Jump up tween(self, { y: self.groundY - 300 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { // Fall back down tween(self, { y: self.groundY }, { duration: 500, easing: tween.easeIn, onFinish: function onFinish() { self.jumping = false; } }); } }); } }; self.moveLeft = function () { if (self.lane > 0) { self.lane--; tween(self, { x: self.lanePositions[self.lane] }, { duration: 200, easing: tween.easeOut }); } }; self.moveRight = function () { if (self.lane < 2) { self.lane++; tween(self, { x: self.lanePositions[self.lane] }, { duration: 200, easing: tween.easeOut }); } }; self.makeInvincible = function (duration) { self.invincible = true; // Flash effect var flashCount = 0; var flashInterval = LK.setInterval(function () { batmobileGraphics.alpha = batmobileGraphics.alpha === 1 ? 0.3 : 1; flashCount++; if (flashCount >= 10) { LK.clearInterval(flashInterval); batmobileGraphics.alpha = 1; self.invincible = false; } }, duration / 10); }; self.shootBatarang = function () { if (gadgetCount >= 10) { // Shoot in all lanes when upgraded for (var i = 0; i < lanePositions.length; i++) { var batarang = new Batarang(); batarang.x = lanePositions[i]; batarang.y = self.y - 50; // Position in front of the Batmobile game.addChild(batarang); activeBatarangs.push(batarang); } LK.getSound('batarangThrow').play(); } else { // Normal shooting - just one batarang var batarang = new Batarang(); batarang.x = self.x; batarang.y = self.y - 50; // Position in front of the Batmobile game.addChild(batarang); activeBatarangs.push(batarang); LK.getSound('batarangThrow').play(); } }; return self; }); var Gadget = Container.expand(function () { var self = Container.call(this); var gadgetGraphics = self.attachAsset('gadget', { anchorX: 0.5, anchorY: 0.5 }); self.type = 'gadget'; self.active = true; // Add some floating animation tween(gadgetGraphics, { y: 10 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(gadgetGraphics, { y: -10 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { if (self.active) { self.update(); // Restart animation } } }); } }); self.update = function () { self.y += game.gameSpeed; // Remove if off screen if (self.y > 2732 + 50) { self.active = false; } // Spin the gadget gadgetGraphics.rotation += 0.05; }; return self; }); var Obstacle = Container.expand(function () { var self = Container.call(this); var obstacleGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); self.type = 'obstacle'; self.active = true; self.update = function () { self.y += game.gameSpeed; // Remove if off screen if (self.y > 2732 + 100) { self.active = false; } }; return self; }); var Road = Container.expand(function () { var self = Container.call(this); var roadGraphics = self.attachAsset('roadPiece', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { // Road moves with game speed self.y += game.gameSpeed; // Loop road if it goes off screen if (self.y > 2732 + 150) { self.y = -150; } }; return self; }); var Villain = Container.expand(function () { var self = Container.call(this); var villainGraphics = self.attachAsset('villain', { anchorX: 0.5, anchorY: 0.5 }); self.type = 'villain'; self.active = true; self.health = 1; self.update = function () { self.y += game.gameSpeed; // Remove if off screen if (self.y > 2732 + 150) { self.active = false; } }; self.hit = function () { self.health--; if (self.health <= 0) { self.active = false; LK.setScore(LK.getScore() + 100); LK.effects.flashObject(self, 0xff0000, 300); // Update high score if needed if (LK.getScore() > storage.highScore) { storage.highScore = LK.getScore(); highScoreTxt.setText('HIGH SCORE: ' + storage.highScore); } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Game configuration // Assets are automatically created and loaded during gameplay or via static code analysis // Initialize assets used in this game. Scale them according to what is needed for the game. var gameSpeed = 10; var spawnRate = 60; // Lower = more frequent spawns var difficultyTimer = 0; var difficultyInterval = 600; // Increase difficulty every 600 ticks (about 10 seconds) var gameOver = false; var canShoot = true; var shootCooldown = 15; // Cooldown in frames (reduced to make shooting easier) var currentCooldown = 0; var gadgetCount = 0; // Game elements var batmobile; var obstacles = []; var villains = []; var gadgets = []; var activeBatarangs = []; var roadPieces = []; var lanePositions = [600, 1024, 1448]; // x positions for the three lanes // UI Elements var scoreTxt; var gadgetTxt; var highScoreTxt; // Initialize the game function initGame() { // Reset variables gameSpeed = 10; game.gameSpeed = gameSpeed; // Add gameSpeed to game object for tweening gameOver = false; obstacles = []; villains = []; gadgets = []; activeBatarangs = []; difficultyTimer = 0; gadgetCount = 0; // Reset UI texts if (gadgetTxt) { gadgetTxt.setText('GADGETS: 0'); } // Reset score display if (scoreTxt) { scoreTxt.setText('SCORE: 0'); } // Set background color to dark blue (night sky) game.setBackgroundColor(0x111133); // Play background music LK.playMusic('batmanTheme', { fade: { start: 0, end: 0.7, duration: 1000 } }); // Create the road createRoad(); // Create the Batmobile batmobile = new Batmobile(); batmobile.x = lanePositions[1]; // Start in center lane batmobile.y = 2300; // Position near bottom of screen game.addChild(batmobile); // Create UI createUI(); // Reset score LK.setScore(0); } function createRoad() { // Create several road pieces to form a continuous road for (var i = 0; i < 3; i++) { var road = new Road(); road.x = 1024; // Center of screen horizontally road.y = i * 300 + 1366 - 300; // Positioned vertically, starting from above middle of screen game.addChild(road); roadPieces.push(road); } } function createUI() { // Remove existing UI elements if they exist if (scoreTxt) { LK.gui.removeChild(scoreTxt); } if (gadgetTxt) { LK.gui.removeChild(gadgetTxt); } if (highScoreTxt) { LK.gui.topRight.removeChild(highScoreTxt); } // Create score text scoreTxt = new Text2('SCORE: ' + LK.getScore(), { size: 70, fill: 0xFFFFFF }); scoreTxt.anchor.set(0, 0); scoreTxt.x = 150; // Position to the left of the high score scoreTxt.y = 120; // Position below the speed display LK.gui.topRight.addChild(scoreTxt); // Create gadget counter gadgetTxt = new Text2('GADGETS: 0', { size: 70, fill: 0xFFFFFF }); gadgetTxt.anchor.set(0, 0); gadgetTxt.x = 150; gadgetTxt.y = 190; // Position below the score display LK.gui.topRight.addChild(gadgetTxt); // High score only highScoreTxt = new Text2('HIGH SCORE: ' + storage.highScore, { size: 150, // Increase the size to 150 fill: 0xFFFFFF }); highScoreTxt.anchor.set(1, 0); highScoreTxt.x = 2048 - 50; // Position it near the right edge highScoreTxt.y = 50; // Position it near the top edge LK.gui.topRight.addChild(highScoreTxt); // Create speed display speedTxt = new Text2('SPEED: ' + gameSpeed, { size: 70, fill: 0xFFFFFF }); speedTxt.anchor.set(0, 0); speedTxt.x = 150; speedTxt.y = 50; LK.gui.topLeft.addChild(speedTxt); } function spawnObstacle() { var lane = Math.floor(Math.random() * 3); // Random lane var obstacle = new Obstacle(); obstacle.x = lanePositions[lane]; obstacle.y = -100; // Start just off-screen at the top game.addChild(obstacle); obstacles.push(obstacle); } function spawnVillain() { var lane = Math.floor(Math.random() * 3); // Random lane var villain = new Villain(); villain.x = lanePositions[lane]; villain.y = -100; // Start just off-screen at the top game.addChild(villain); villains.push(villain); } function spawnGadget() { var lane = Math.floor(Math.random() * 3); // Random lane var gadget = new Gadget(); gadget.x = lanePositions[lane]; gadget.y = -100; // Start just off-screen at the top game.addChild(gadget); gadgets.push(gadget); } function checkCollisions() { // Check Batmobile collision with obstacles for (var i = obstacles.length - 1; i >= 0; i--) { var obstacle = obstacles[i]; if (obstacle.active && batmobile.intersects(obstacle) && !batmobile.invincible) { // Collision with obstacle LK.getSound('crash').play(); LK.effects.flashScreen(0xff0000, 500); // Update high score if needed if (LK.getScore() > storage.highScore) { storage.highScore = LK.getScore(); highScoreTxt.setText('HIGH SCORE: ' + storage.highScore); } LK.showGameOver(); gameOver = true; return; } } // Check Batmobile collision with villains for (var i = villains.length - 1; i >= 0; i--) { var villain = villains[i]; if (villain.active && batmobile.intersects(villain) && !batmobile.invincible) { // Collision with villain LK.getSound('crash').play(); LK.effects.flashScreen(0xff0000, 500); // Update high score if needed if (LK.getScore() > storage.highScore) { storage.highScore = LK.getScore(); highScoreTxt.setText('HIGH SCORE: ' + storage.highScore); } LK.showGameOver(); gameOver = true; return; } } // Check Batmobile collection of gadgets for (var i = gadgets.length - 1; i >= 0; i--) { var gadget = gadgets[i]; if (gadget.active && batmobile.intersects(gadget)) { // Collect gadget gadget.active = false; LK.getSound('collect').play(); LK.setScore(LK.getScore() + 50); gadgetCount++; // Check if we've reached 10 gadgets for the upgrade if (gadgetCount === 10) { // Upgrade to purple Batmobile batmobile.removeChild(batmobile.children[0]); // Remove current Batmobile graphic var purpleBatmobileGraphics = batmobile.attachAsset('PurpleBatmobile', { anchorX: 0.5, anchorY: 0.5 }); // Flash effect to show upgrade LK.effects.flashScreen(0x800080, 500); // Purple flash } // Removed gadget text update // Flash gadget LK.effects.flashObject(gadget, 0xffff00, 300); gadgets.splice(i, 1); gadget.destroy(); } } // Check Batarang collision with villains for (var i = activeBatarangs.length - 1; i >= 0; i--) { var batarang = activeBatarangs[i]; if (batarang.active) { for (var j = villains.length - 1; j >= 0; j--) { var villain = villains[j]; if (villain.active && batarang.intersects(villain)) { // Hit villain with batarang villain.hit(); batarang.active = false; activeBatarangs.splice(i, 1); batarang.destroy(); if (!villain.active) { // Spawn a gadget at the villain's position var gadget = new Gadget(); gadget.x = villain.x; gadget.y = villain.y; game.addChild(gadget); gadgets.push(gadget); // Remove villain villains.splice(j, 1); villain.destroy(); } break; } } } } } function updateGameElements() { // Update obstacles for (var i = obstacles.length - 1; i >= 0; i--) { var obstacle = obstacles[i]; obstacle.update(); if (!obstacle.active) { obstacles.splice(i, 1); obstacle.destroy(); } } // Update villains for (var i = villains.length - 1; i >= 0; i--) { var villain = villains[i]; villain.update(); if (!villain.active) { villains.splice(i, 1); villain.destroy(); } } // Update gadgets for (var i = gadgets.length - 1; i >= 0; i--) { var gadget = gadgets[i]; gadget.update(); if (!gadget.active) { gadgets.splice(i, 1); gadget.destroy(); } } // Update batarangs for (var i = activeBatarangs.length - 1; i >= 0; i--) { var batarang = activeBatarangs[i]; batarang.update(); if (!batarang.active) { activeBatarangs.splice(i, 1); batarang.destroy(); } } } function increaseDifficulty() { difficultyTimer++; if (difficultyTimer >= difficultyInterval) { difficultyTimer = 0; // Increase game speed gradually using tween tween(game, { gameSpeed: gameSpeed + 3.0 // Double the speed increase from 1.5 to 3.0 }, { duration: 2000, // Reduce duration from 3000ms to 2000ms easing: tween.easeOut }); // Make spawns more frequent if (spawnRate > 30) { spawnRate -= 5; // Decrease spawn rate more aggressively } // Flash screen to indicate difficulty increase LK.effects.flashScreen(0x0000ff, 300); } } function updateUI() { // Update speed display if (speedTxt) { speedTxt.setText('SPEED: ' + Math.floor(game.gameSpeed)); } // Update gadget counter if (gadgetTxt) { gadgetTxt.setText('GADGETS: ' + gadgetCount + (gadgetCount >= 10 ? ' (UPGRADED)' : '')); } } function handleShoot() { if (currentCooldown > 0) { currentCooldown--; } else { canShoot = true; } } // Initialize the game when it starts initGame(); // Game update loop game.update = function () { if (gameOver) return; // Sync gameSpeed variable with game.gameSpeed property gameSpeed = game.gameSpeed; // Update UI updateUI(); // Handle shooting cooldown handleShoot(); // Update all game elements updateGameElements(); // Check for collisions checkCollisions(); // Increase difficulty over time increaseDifficulty(); // Randomly spawn obstacles, villains, and gadgets if (LK.ticks % spawnRate === 0) { // 70% chance for obstacle, 20% chance for villain, 10% chance for gadget var rand = Math.random(); if (rand < 0.7) { spawnObstacle(); } else if (rand < 0.9) { spawnVillain(); } else { spawnGadget(); } } }; // Handle touch inputs game.down = function (x, y, obj) { if (gameOver) return; // Determine which action to take based on touch position if (y < 1366) { // Upper half of screen - shoot batarangs (no longer requires gadgets) if (canShoot) { batmobile.shootBatarang(); canShoot = false; currentCooldown = shootCooldown; } } else { // Lower half of screen - movement if (x < 1024) { batmobile.moveLeft(); } else { batmobile.moveRight(); } } }; // Handle swipe up for jump var startY = 0; game.move = function (x, y, obj) { if (gameOver) return; if (obj && obj.event) { if (obj.event.type === "touchstart") { startY = y; } else if (obj.event.type === "touchmove") { var deltaY = startY - y; if (deltaY > 100) { // If swiped up more than 100px batmobile.jump(); startY = y; // Reset to prevent multiple jumps } } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var Batarang = Container.expand(function () {
var self = Container.call(this);
var batarangGraphics = self.attachAsset('batarang', {
anchorX: 0.5,
anchorY: 0.5,
width: 80,
// Make batarang hit box smaller
height: 40 // Make batarang hit box smaller
});
self.active = true;
self.speed = -40; // Negative speed to move upward (doubled for faster shots)
self.update = function () {
self.y += self.speed;
batarangGraphics.rotation += 0.2;
// Remove if off screen
if (self.y < -50) {
//{o} // Check if it's off the top of the screen
self.active = false;
}
};
return self;
});
var Batmobile = Container.expand(function () {
var self = Container.call(this);
self.batmobileGraphics = self.attachAsset('batmobile', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 10;
self.jumpHeight = 0;
self.isJumping = false;
self.lane = 1; // 0 = left, 1 = center, 2 = right
self.lanePositions = [600, 1024, 1448]; // x positions for the three lanes
self.groundY = 2300; // ground position
self.jumping = false;
self.invincible = false;
self.jump = function () {
if (!self.jumping) {
self.jumping = true;
// Jump up
tween(self, {
y: self.groundY - 300
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Fall back down
tween(self, {
y: self.groundY
}, {
duration: 500,
easing: tween.easeIn,
onFinish: function onFinish() {
self.jumping = false;
}
});
}
});
}
};
self.moveLeft = function () {
if (self.lane > 0) {
self.lane--;
tween(self, {
x: self.lanePositions[self.lane]
}, {
duration: 200,
easing: tween.easeOut
});
}
};
self.moveRight = function () {
if (self.lane < 2) {
self.lane++;
tween(self, {
x: self.lanePositions[self.lane]
}, {
duration: 200,
easing: tween.easeOut
});
}
};
self.makeInvincible = function (duration) {
self.invincible = true;
// Flash effect
var flashCount = 0;
var flashInterval = LK.setInterval(function () {
batmobileGraphics.alpha = batmobileGraphics.alpha === 1 ? 0.3 : 1;
flashCount++;
if (flashCount >= 10) {
LK.clearInterval(flashInterval);
batmobileGraphics.alpha = 1;
self.invincible = false;
}
}, duration / 10);
};
self.shootBatarang = function () {
if (gadgetCount >= 10) {
// Shoot in all lanes when upgraded
for (var i = 0; i < lanePositions.length; i++) {
var batarang = new Batarang();
batarang.x = lanePositions[i];
batarang.y = self.y - 50; // Position in front of the Batmobile
game.addChild(batarang);
activeBatarangs.push(batarang);
}
LK.getSound('batarangThrow').play();
} else {
// Normal shooting - just one batarang
var batarang = new Batarang();
batarang.x = self.x;
batarang.y = self.y - 50; // Position in front of the Batmobile
game.addChild(batarang);
activeBatarangs.push(batarang);
LK.getSound('batarangThrow').play();
}
};
return self;
});
var Gadget = Container.expand(function () {
var self = Container.call(this);
var gadgetGraphics = self.attachAsset('gadget', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'gadget';
self.active = true;
// Add some floating animation
tween(gadgetGraphics, {
y: 10
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(gadgetGraphics, {
y: -10
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.active) {
self.update(); // Restart animation
}
}
});
}
});
self.update = function () {
self.y += game.gameSpeed;
// Remove if off screen
if (self.y > 2732 + 50) {
self.active = false;
}
// Spin the gadget
gadgetGraphics.rotation += 0.05;
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'obstacle';
self.active = true;
self.update = function () {
self.y += game.gameSpeed;
// Remove if off screen
if (self.y > 2732 + 100) {
self.active = false;
}
};
return self;
});
var Road = Container.expand(function () {
var self = Container.call(this);
var roadGraphics = self.attachAsset('roadPiece', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
// Road moves with game speed
self.y += game.gameSpeed;
// Loop road if it goes off screen
if (self.y > 2732 + 150) {
self.y = -150;
}
};
return self;
});
var Villain = Container.expand(function () {
var self = Container.call(this);
var villainGraphics = self.attachAsset('villain', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'villain';
self.active = true;
self.health = 1;
self.update = function () {
self.y += game.gameSpeed;
// Remove if off screen
if (self.y > 2732 + 150) {
self.active = false;
}
};
self.hit = function () {
self.health--;
if (self.health <= 0) {
self.active = false;
LK.setScore(LK.getScore() + 100);
LK.effects.flashObject(self, 0xff0000, 300);
// Update high score if needed
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
highScoreTxt.setText('HIGH SCORE: ' + storage.highScore);
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game configuration
// Assets are automatically created and loaded during gameplay or via static code analysis
// Initialize assets used in this game. Scale them according to what is needed for the game.
var gameSpeed = 10;
var spawnRate = 60; // Lower = more frequent spawns
var difficultyTimer = 0;
var difficultyInterval = 600; // Increase difficulty every 600 ticks (about 10 seconds)
var gameOver = false;
var canShoot = true;
var shootCooldown = 15; // Cooldown in frames (reduced to make shooting easier)
var currentCooldown = 0;
var gadgetCount = 0;
// Game elements
var batmobile;
var obstacles = [];
var villains = [];
var gadgets = [];
var activeBatarangs = [];
var roadPieces = [];
var lanePositions = [600, 1024, 1448]; // x positions for the three lanes
// UI Elements
var scoreTxt;
var gadgetTxt;
var highScoreTxt;
// Initialize the game
function initGame() {
// Reset variables
gameSpeed = 10;
game.gameSpeed = gameSpeed; // Add gameSpeed to game object for tweening
gameOver = false;
obstacles = [];
villains = [];
gadgets = [];
activeBatarangs = [];
difficultyTimer = 0;
gadgetCount = 0;
// Reset UI texts
if (gadgetTxt) {
gadgetTxt.setText('GADGETS: 0');
}
// Reset score display
if (scoreTxt) {
scoreTxt.setText('SCORE: 0');
}
// Set background color to dark blue (night sky)
game.setBackgroundColor(0x111133);
// Play background music
LK.playMusic('batmanTheme', {
fade: {
start: 0,
end: 0.7,
duration: 1000
}
});
// Create the road
createRoad();
// Create the Batmobile
batmobile = new Batmobile();
batmobile.x = lanePositions[1]; // Start in center lane
batmobile.y = 2300; // Position near bottom of screen
game.addChild(batmobile);
// Create UI
createUI();
// Reset score
LK.setScore(0);
}
function createRoad() {
// Create several road pieces to form a continuous road
for (var i = 0; i < 3; i++) {
var road = new Road();
road.x = 1024; // Center of screen horizontally
road.y = i * 300 + 1366 - 300; // Positioned vertically, starting from above middle of screen
game.addChild(road);
roadPieces.push(road);
}
}
function createUI() {
// Remove existing UI elements if they exist
if (scoreTxt) {
LK.gui.removeChild(scoreTxt);
}
if (gadgetTxt) {
LK.gui.removeChild(gadgetTxt);
}
if (highScoreTxt) {
LK.gui.topRight.removeChild(highScoreTxt);
}
// Create score text
scoreTxt = new Text2('SCORE: ' + LK.getScore(), {
size: 70,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = 150; // Position to the left of the high score
scoreTxt.y = 120; // Position below the speed display
LK.gui.topRight.addChild(scoreTxt);
// Create gadget counter
gadgetTxt = new Text2('GADGETS: 0', {
size: 70,
fill: 0xFFFFFF
});
gadgetTxt.anchor.set(0, 0);
gadgetTxt.x = 150;
gadgetTxt.y = 190; // Position below the score display
LK.gui.topRight.addChild(gadgetTxt);
// High score only
highScoreTxt = new Text2('HIGH SCORE: ' + storage.highScore, {
size: 150,
// Increase the size to 150
fill: 0xFFFFFF
});
highScoreTxt.anchor.set(1, 0);
highScoreTxt.x = 2048 - 50; // Position it near the right edge
highScoreTxt.y = 50; // Position it near the top edge
LK.gui.topRight.addChild(highScoreTxt);
// Create speed display
speedTxt = new Text2('SPEED: ' + gameSpeed, {
size: 70,
fill: 0xFFFFFF
});
speedTxt.anchor.set(0, 0);
speedTxt.x = 150;
speedTxt.y = 50;
LK.gui.topLeft.addChild(speedTxt);
}
function spawnObstacle() {
var lane = Math.floor(Math.random() * 3); // Random lane
var obstacle = new Obstacle();
obstacle.x = lanePositions[lane];
obstacle.y = -100; // Start just off-screen at the top
game.addChild(obstacle);
obstacles.push(obstacle);
}
function spawnVillain() {
var lane = Math.floor(Math.random() * 3); // Random lane
var villain = new Villain();
villain.x = lanePositions[lane];
villain.y = -100; // Start just off-screen at the top
game.addChild(villain);
villains.push(villain);
}
function spawnGadget() {
var lane = Math.floor(Math.random() * 3); // Random lane
var gadget = new Gadget();
gadget.x = lanePositions[lane];
gadget.y = -100; // Start just off-screen at the top
game.addChild(gadget);
gadgets.push(gadget);
}
function checkCollisions() {
// Check Batmobile collision with obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
if (obstacle.active && batmobile.intersects(obstacle) && !batmobile.invincible) {
// Collision with obstacle
LK.getSound('crash').play();
LK.effects.flashScreen(0xff0000, 500);
// Update high score if needed
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
highScoreTxt.setText('HIGH SCORE: ' + storage.highScore);
}
LK.showGameOver();
gameOver = true;
return;
}
}
// Check Batmobile collision with villains
for (var i = villains.length - 1; i >= 0; i--) {
var villain = villains[i];
if (villain.active && batmobile.intersects(villain) && !batmobile.invincible) {
// Collision with villain
LK.getSound('crash').play();
LK.effects.flashScreen(0xff0000, 500);
// Update high score if needed
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
highScoreTxt.setText('HIGH SCORE: ' + storage.highScore);
}
LK.showGameOver();
gameOver = true;
return;
}
}
// Check Batmobile collection of gadgets
for (var i = gadgets.length - 1; i >= 0; i--) {
var gadget = gadgets[i];
if (gadget.active && batmobile.intersects(gadget)) {
// Collect gadget
gadget.active = false;
LK.getSound('collect').play();
LK.setScore(LK.getScore() + 50);
gadgetCount++;
// Check if we've reached 10 gadgets for the upgrade
if (gadgetCount === 10) {
// Upgrade to purple Batmobile
batmobile.removeChild(batmobile.children[0]); // Remove current Batmobile graphic
var purpleBatmobileGraphics = batmobile.attachAsset('PurpleBatmobile', {
anchorX: 0.5,
anchorY: 0.5
});
// Flash effect to show upgrade
LK.effects.flashScreen(0x800080, 500); // Purple flash
}
// Removed gadget text update
// Flash gadget
LK.effects.flashObject(gadget, 0xffff00, 300);
gadgets.splice(i, 1);
gadget.destroy();
}
}
// Check Batarang collision with villains
for (var i = activeBatarangs.length - 1; i >= 0; i--) {
var batarang = activeBatarangs[i];
if (batarang.active) {
for (var j = villains.length - 1; j >= 0; j--) {
var villain = villains[j];
if (villain.active && batarang.intersects(villain)) {
// Hit villain with batarang
villain.hit();
batarang.active = false;
activeBatarangs.splice(i, 1);
batarang.destroy();
if (!villain.active) {
// Spawn a gadget at the villain's position
var gadget = new Gadget();
gadget.x = villain.x;
gadget.y = villain.y;
game.addChild(gadget);
gadgets.push(gadget);
// Remove villain
villains.splice(j, 1);
villain.destroy();
}
break;
}
}
}
}
}
function updateGameElements() {
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
obstacle.update();
if (!obstacle.active) {
obstacles.splice(i, 1);
obstacle.destroy();
}
}
// Update villains
for (var i = villains.length - 1; i >= 0; i--) {
var villain = villains[i];
villain.update();
if (!villain.active) {
villains.splice(i, 1);
villain.destroy();
}
}
// Update gadgets
for (var i = gadgets.length - 1; i >= 0; i--) {
var gadget = gadgets[i];
gadget.update();
if (!gadget.active) {
gadgets.splice(i, 1);
gadget.destroy();
}
}
// Update batarangs
for (var i = activeBatarangs.length - 1; i >= 0; i--) {
var batarang = activeBatarangs[i];
batarang.update();
if (!batarang.active) {
activeBatarangs.splice(i, 1);
batarang.destroy();
}
}
}
function increaseDifficulty() {
difficultyTimer++;
if (difficultyTimer >= difficultyInterval) {
difficultyTimer = 0;
// Increase game speed gradually using tween
tween(game, {
gameSpeed: gameSpeed + 3.0 // Double the speed increase from 1.5 to 3.0
}, {
duration: 2000,
// Reduce duration from 3000ms to 2000ms
easing: tween.easeOut
});
// Make spawns more frequent
if (spawnRate > 30) {
spawnRate -= 5; // Decrease spawn rate more aggressively
}
// Flash screen to indicate difficulty increase
LK.effects.flashScreen(0x0000ff, 300);
}
}
function updateUI() {
// Update speed display
if (speedTxt) {
speedTxt.setText('SPEED: ' + Math.floor(game.gameSpeed));
}
// Update gadget counter
if (gadgetTxt) {
gadgetTxt.setText('GADGETS: ' + gadgetCount + (gadgetCount >= 10 ? ' (UPGRADED)' : ''));
}
}
function handleShoot() {
if (currentCooldown > 0) {
currentCooldown--;
} else {
canShoot = true;
}
}
// Initialize the game when it starts
initGame();
// Game update loop
game.update = function () {
if (gameOver) return;
// Sync gameSpeed variable with game.gameSpeed property
gameSpeed = game.gameSpeed;
// Update UI
updateUI();
// Handle shooting cooldown
handleShoot();
// Update all game elements
updateGameElements();
// Check for collisions
checkCollisions();
// Increase difficulty over time
increaseDifficulty();
// Randomly spawn obstacles, villains, and gadgets
if (LK.ticks % spawnRate === 0) {
// 70% chance for obstacle, 20% chance for villain, 10% chance for gadget
var rand = Math.random();
if (rand < 0.7) {
spawnObstacle();
} else if (rand < 0.9) {
spawnVillain();
} else {
spawnGadget();
}
}
};
// Handle touch inputs
game.down = function (x, y, obj) {
if (gameOver) return;
// Determine which action to take based on touch position
if (y < 1366) {
// Upper half of screen - shoot batarangs (no longer requires gadgets)
if (canShoot) {
batmobile.shootBatarang();
canShoot = false;
currentCooldown = shootCooldown;
}
} else {
// Lower half of screen - movement
if (x < 1024) {
batmobile.moveLeft();
} else {
batmobile.moveRight();
}
}
};
// Handle swipe up for jump
var startY = 0;
game.move = function (x, y, obj) {
if (gameOver) return;
if (obj && obj.event) {
if (obj.event.type === "touchstart") {
startY = y;
} else if (obj.event.type === "touchmove") {
var deltaY = startY - y;
if (deltaY > 100) {
// If swiped up more than 100px
batmobile.jump();
startY = y; // Reset to prevent multiple jumps
}
}
}
};