User prompt
Make the baterangs go the other way
User prompt
Make the stuff come from the other direction
User prompt
Make the most obstacles and coins come from the other direction
User prompt
Fix error[L598]
User prompt
Fix it
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'if (obj.event.type === "touchstart") {' Line Number: 598
Code edit (1 edits merged)
Please save this source code
User prompt
Batman: Night Runner
Initial prompt
Make a endless runner Batmobile game where you go side to side
/****
* 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
}
}
}
};