/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { cash: 0, highScore: 0 }); /**** * Classes ****/ var Building = Container.expand(function () { var self = Container.call(this); self.init = function () { self.graphic = self.attachAsset('building', { anchorX: 0.5, anchorY: 0.5 }); return self; }; return self; }); var Obstacle = Container.expand(function () { var self = Container.call(this); self.init = function (type) { self.graphic = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); self.width = self.graphic.width; self.height = self.graphic.height; return self; }; return self; }); var Road = Container.expand(function () { var self = Container.call(this); self.init = function () { self.graphic = self.attachAsset('road', { anchorX: 0.5, anchorY: 0.5 }); return self; }; return self; }); var SpeedMeter = Container.expand(function () { var self = Container.call(this); self.init = function () { self.background = self.attachAsset('speedMeter', { anchorX: 0, anchorY: 0.5 }); self.indicator = self.attachAsset('speedIndicator', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0 }); return self; }; self.update = function (speed, maxSpeed) { var percentage = speed / maxSpeed; var maxX = self.background.width - self.indicator.width; self.indicator.x = maxX * percentage; }; return self; }); var Vehicle = Container.expand(function () { var self = Container.call(this); self.speed = 0; self.maxSpeed = 10; self.acceleration = 10.2; self.braking = 0.3; self.friction = 0.05; self.handling = 0.03; self.angle = 0; self.stolen = false; self.type = 'civilian'; self.width = 100; self.height = 150; self.hitbox = { width: 100, height: 150 }; self.alive = true; self.init = function (type) { self.type = type; var color; if (type === 'player') { color = 0xff0000; self.maxSpeed = 15; } else if (type === 'police') { color = 0x0000ff; self.maxSpeed = 1; } else { // Random civilian car color var colors = [0xcccccc, 0xffcc00, 0x00cc00, 0xcc00cc, 0x00cccc]; color = colors[Math.floor(Math.random() * colors.length)]; } // Create the car graphic self.graphic = self.attachAsset(type, { anchorX: 0.5, anchorY: 0.5 }); return self; }; self.accelerate = function () { self.speed += self.acceleration; if (self.speed > self.maxSpeed) { self.speed = self.maxSpeed; } }; self.brake = function () { self.speed -= self.braking; if (self.speed < 0) { self.speed = 0; } }; self.turn = function (direction) { self.angle += direction * self.handling * self.speed / 2; }; self.update = function () { if (!self.alive) { return; } // Apply friction if (self.speed > 0) { self.speed -= self.friction; if (self.speed < 0) { self.speed = 0; } } // Update position based on speed and angle self.x += Math.sin(self.angle) * self.speed; self.y -= Math.cos(self.angle) * self.speed; // Update rotation to match angle self.rotation = self.angle; // Keep within game boundaries if (self.x < 0) { self.x = 0; } if (self.x > 2048) { self.x = 2048; } if (self.y < 0) { self.y = 0; } if (self.y > 2732) { self.y = 2732; } }; self.destroy = function () { self.alive = false; tween(self, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { Container.prototype.destroy.call(self); } }); }; return self; }); var WantedStar = Container.expand(function () { var self = Container.call(this); self.graphic = self.attachAsset('wantedStar', { anchorX: 0.5, anchorY: 0.5 }); self.show = function () { tween(self, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.elasticOut }); }; self.hide = function () { tween(self, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 300 }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Game state variables var gameActive = true; var player = null; var vehicles = []; var obstacles = []; var buildings = []; var roads = []; var wantedLevel = 0; var maxWantedLevel = 5; var cash = storage.cash || 0; var policeSpawnTimer = 0; var policeSpawnDelay = 300; var civilianSpawnTimer = 0; var civilianSpawnDelay = 180; var targetVehicle = null; var isDragging = false; var lastX = 0; var lastY = 0; var steerDirection = 0; // UI elements var cashText; var wantedStars = []; var speedMeter; // Initialize the game environment function initGame() { // Create street layout createCityLayout(); // Create the player player = new Vehicle(); player.init('player'); player.x = 2048 / 2; player.y = 2732 / 2; game.addChild(player); vehicles.push(player); // Create some initial vehicles for (var i = 0; i < 5; i++) { spawnCivilianVehicle(); } // Initialize UI initUI(); // Start playing background music LK.playMusic('gameMusic'); } function createCityLayout() { // Create a basic city grid with roads var roadWidth = 400; var blockSize = 600; // Horizontal roads for (var y = blockSize / 2; y < 2732; y += blockSize) { var road = new Road(); road.init(); road.x = 2048 / 2; road.y = y; road.rotation = Math.PI / 2; // Rotate to make it horizontal game.addChild(road); roads.push(road); } // Vertical roads for (var x = blockSize / 2; x < 2048; x += blockSize) { var road = new Road(); road.init(); road.x = x; road.y = 2732 / 2; game.addChild(road); roads.push(road); } // Create buildings in the grid spaces for (var x = blockSize / 2; x < 2048; x += blockSize) { for (var y = blockSize / 2; y < 2732; y += blockSize) { // Skip road intersections if (x % blockSize === blockSize / 2 && y % blockSize === blockSize / 2 || x % blockSize !== blockSize / 2 && y % blockSize !== blockSize / 2) { continue; } var building = new Building(); building.init(); building.x = x; building.y = y; game.addChild(building); buildings.push(building); obstacles.push(building); } } } function initUI() { // Create accelerate button var accelerateButton = new Container(); var buttonGraphic = accelerateButton.attachAsset('speedIndicator', { anchorX: 0.5, anchorY: 0.5 }); accelerateButton.x = 2048 / 2; accelerateButton.y = 2732 - 200; var buttonText = new Text2('Accelerate', { size: 40, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); accelerateButton.addChild(buttonText); accelerateButton.interactive = true; accelerateButton.on('down', function () { player.accelerate(); }); game.addChild(accelerateButton); cashText = new Text2('$' + cash, { size: 60, fill: 0x00FF00 }); cashText.anchor.set(0, 0); LK.gui.topRight.addChild(cashText); // Create wanted level stars for (var i = 0; i < maxWantedLevel; i++) { var star = new WantedStar(); star.x = -i * 60 - 30; star.y = 60; star.alpha = 0; star.scale.set(0.5); LK.gui.topRight.addChild(star); wantedStars.push(star); } // Create speed meter speedMeter = new SpeedMeter(); speedMeter.init(); speedMeter.x = 2048 / 2 - 200; speedMeter.y = 2732 - 100; game.addChild(speedMeter); } function updateWantedLevel(level) { if (level === wantedLevel) { return; } wantedLevel = level; if (wantedLevel > maxWantedLevel) { wantedLevel = maxWantedLevel; } for (var i = 0; i < wantedStars.length; i++) { if (i < wantedLevel) { wantedStars[i].show(); } else { wantedStars[i].hide(); } } // Adjust police spawn rate based on wanted level policeSpawnDelay = 300 - wantedLevel * 40; if (policeSpawnDelay < 60) { policeSpawnDelay = 60; } } function spawnPoliceVehicle() { var police = new Vehicle(); police.init('police'); // Spawn police at edge of screen var edge = Math.floor(Math.random() * 4); switch (edge) { case 0: // Top police.x = Math.random() * 2048; police.y = -100; police.angle = Math.PI / 2; break; case 1: // Right police.x = 2048 + 100; police.y = Math.random() * 2732; police.angle = Math.PI; break; case 2: // Bottom police.x = Math.random() * 2048; police.y = 2732 + 100; police.angle = -Math.PI / 2; break; case 3: // Left police.x = -100; police.y = Math.random() * 2732; police.angle = 0; break; } game.addChild(police); vehicles.push(police); // Play police siren sound LK.getSound('policeSiren').play(); return police; } function spawnCivilianVehicle() { var civilian = new Vehicle(); civilian.init('civilian'); // Random position on a road var onVertical = Math.random() > 0.5; if (onVertical) { var roadIndex = Math.floor(Math.random() * (roads.length / 2)); civilian.x = roads[roadIndex].x; civilian.y = Math.random() * 2732; civilian.angle = Math.random() > 0.5 ? Math.PI / 2 : -Math.PI / 2; } else { var roadIndex = Math.floor(Math.random() * (roads.length / 2)) + roads.length / 2; civilian.x = Math.random() * 2048; civilian.y = roads[roadIndex].y; civilian.angle = Math.random() > 0.5 ? 0 : Math.PI; } civilian.maxSpeed = 3 + Math.random() * 4; game.addChild(civilian); vehicles.push(civilian); return civilian; } function stealVehicle(target) { if (!target || target === player || target.type === 'player') { return; } // Remove the old player vehicle var oldPlayerIndex = vehicles.indexOf(player); if (oldPlayerIndex !== -1) { vehicles.splice(oldPlayerIndex, 1); } player.destroy(); // Replace target with player var targetIndex = vehicles.indexOf(target); if (targetIndex !== -1) { vehicles.splice(targetIndex, 1); } // Create new player with same position and angle player = new Vehicle(); player.init('player'); player.x = target.x; player.y = target.y; player.angle = target.angle; player.rotation = target.rotation; game.addChild(player); vehicles.push(player); // Destroy old vehicle target.destroy(); // Increase wanted level and cash updateWantedLevel(wantedLevel + 1); addCash(100); // Play sound LK.getSound('carTheft').play(); // Reset target targetVehicle = null; } function addCash(amount) { cash += amount; cashText.setText('$' + cash); storage.cash = cash; // Update score for leaderboards LK.setScore(cash); } function checkCollisions() { // Check player collision with other vehicles for (var i = 0; i < vehicles.length; i++) { var vehicle = vehicles[i]; if (vehicle === player || !vehicle.alive) { continue; } if (player.intersects(vehicle)) { // Handle collision var crashSpeed = player.speed; player.speed = Math.max(0, player.speed - 2); // Play crash sound if fast enough if (crashSpeed > 3) { LK.getSound('crash').play(); // If crashed into police, increase wanted level if (vehicle.type === 'police') { updateWantedLevel(wantedLevel + 1); } // Visual feedback LK.effects.flashObject(player, 0xFFFFFF, 300); } // Check if player is stopped near a vehicle - potential theft target if (player.speed < 1 && vehicle.type !== 'police') { targetVehicle = vehicle; } } } // Check player collision with obstacles for (var i = 0; i < obstacles.length; i++) { var obstacle = obstacles[i]; if (player.intersects(obstacle)) { // Reduce speed on obstacle collision var crashSpeed = player.speed; player.speed = Math.max(0, player.speed - 1); // Play crash sound if fast enough if (crashSpeed > 3) { LK.getSound('crash').play(); // Visual feedback LK.effects.flashObject(player, 0xFFFFFF, 300); } } } } function updateVehicles() { // Update player vehicle if (steerDirection !== 0) { player.turn(steerDirection); } // Update all vehicles for (var i = vehicles.length - 1; i >= 0; i--) { var vehicle = vehicles[i]; if (!vehicle.alive) { vehicles.splice(i, 1); continue; } // AI behavior for non-player vehicles if (vehicle !== player) { // Simple AI: accelerate forward, avoid obstacles with random turns vehicle.accelerate(); // Police AI: chase player if (vehicle.type === 'police') { // Calculate angle to player var dx = player.x - vehicle.x; var dy = player.y - vehicle.y; var targetAngle = Math.atan2(dx, -dy); // Find shortest turn direction var angleDiff = targetAngle - vehicle.angle; while (angleDiff > Math.PI) { angleDiff -= Math.PI * 2; } while (angleDiff < -Math.PI) { angleDiff += Math.PI * 2; } // Turn towards player if (angleDiff > 0.05) { vehicle.turn(0.5); } else if (angleDiff < -0.05) { vehicle.turn(-0.5); } } // Civilian AI: random movement along roads else { if (Math.random() < 0.02) { vehicle.turn((Math.random() - 0.5) * 0.1); } // Randomly brake sometimes if (Math.random() < 0.01) { vehicle.brake(); } } // Check for off-screen vehicles if (vehicle.x < -200 || vehicle.x > 2248 || vehicle.y < -200 || vehicle.y > 2932) { // Remove vehicle if it's far off-screen if (vehicle.type !== 'police' || Math.abs(vehicle.x - player.x) > 1000 || Math.abs(vehicle.y - player.y) > 1000) { vehicle.destroy(); } } } } } // Input handlers game.down = function (x, y, obj) { lastX = x; lastY = y; isDragging = true; // If player is stopped and near a vehicle, steal it if (player.speed < 1 && targetVehicle) { stealVehicle(targetVehicle); return; } // Always accelerate on touch down player.accelerate(); }; game.up = function (x, y, obj) { isDragging = false; steerDirection = 0; }; game.move = function (x, y, obj) { if (!isDragging) { return; } // Calculate steering based on horizontal drag var dx = x - lastX; // Set steering direction if (dx > 10) { steerDirection = 1; } else if (dx < -10) { steerDirection = -1; } else { steerDirection = 0; } // Update last position lastX = x; lastY = y; }; // Main game update loop game.update = function () { if (!gameActive) { return; } // Spawn police based on wanted level and timer policeSpawnTimer++; if (policeSpawnTimer >= policeSpawnDelay && wantedLevel > 0) { spawnPoliceVehicle(); policeSpawnTimer = 0; } // Spawn civilian vehicles civilianSpawnTimer++; if (civilianSpawnTimer >= civilianSpawnDelay) { spawnCivilianVehicle(); civilianSpawnTimer = 0; } // Update vehicle positions and AI updateVehicles(); // Check for collisions checkCollisions(); // Update UI elements speedMeter.update(player.speed, player.maxSpeed); // Engine sound if (player.speed > 0) { if (!engineSoundPlaying) { LK.getSound('carEngine').play(); engineSoundPlaying = true; } } else { engineSoundPlaying = false; } // Limit number of vehicles for performance while (vehicles.length > 20) { // Remove oldest civilian vehicles first for (var i = 0; i < vehicles.length; i++) { if (vehicles[i] !== player && vehicles[i].type === 'civilian') { vehicles[i].destroy(); vehicles.splice(i, 1); break; } } } // Game over condition: too many police collisions if (wantedLevel >= maxWantedLevel) { var policeCount = 0; for (var i = 0; i < vehicles.length; i++) { if (vehicles[i].type === 'police') { policeCount++; } } // If surrounded by too many police, game over if (policeCount >= 5) { // Save high score if (cash > storage.highScore) { storage.highScore = cash; } // Game over LK.showGameOver(); gameActive = false; } } }; // Initialize the game var engineSoundPlaying = false; initGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
cash: 0,
highScore: 0
});
/****
* Classes
****/
var Building = Container.expand(function () {
var self = Container.call(this);
self.init = function () {
self.graphic = self.attachAsset('building', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
self.init = function (type) {
self.graphic = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = self.graphic.width;
self.height = self.graphic.height;
return self;
};
return self;
});
var Road = Container.expand(function () {
var self = Container.call(this);
self.init = function () {
self.graphic = self.attachAsset('road', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
};
return self;
});
var SpeedMeter = Container.expand(function () {
var self = Container.call(this);
self.init = function () {
self.background = self.attachAsset('speedMeter', {
anchorX: 0,
anchorY: 0.5
});
self.indicator = self.attachAsset('speedIndicator', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0
});
return self;
};
self.update = function (speed, maxSpeed) {
var percentage = speed / maxSpeed;
var maxX = self.background.width - self.indicator.width;
self.indicator.x = maxX * percentage;
};
return self;
});
var Vehicle = Container.expand(function () {
var self = Container.call(this);
self.speed = 0;
self.maxSpeed = 10;
self.acceleration = 10.2;
self.braking = 0.3;
self.friction = 0.05;
self.handling = 0.03;
self.angle = 0;
self.stolen = false;
self.type = 'civilian';
self.width = 100;
self.height = 150;
self.hitbox = {
width: 100,
height: 150
};
self.alive = true;
self.init = function (type) {
self.type = type;
var color;
if (type === 'player') {
color = 0xff0000;
self.maxSpeed = 15;
} else if (type === 'police') {
color = 0x0000ff;
self.maxSpeed = 1;
} else {
// Random civilian car color
var colors = [0xcccccc, 0xffcc00, 0x00cc00, 0xcc00cc, 0x00cccc];
color = colors[Math.floor(Math.random() * colors.length)];
}
// Create the car graphic
self.graphic = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5
});
return self;
};
self.accelerate = function () {
self.speed += self.acceleration;
if (self.speed > self.maxSpeed) {
self.speed = self.maxSpeed;
}
};
self.brake = function () {
self.speed -= self.braking;
if (self.speed < 0) {
self.speed = 0;
}
};
self.turn = function (direction) {
self.angle += direction * self.handling * self.speed / 2;
};
self.update = function () {
if (!self.alive) {
return;
}
// Apply friction
if (self.speed > 0) {
self.speed -= self.friction;
if (self.speed < 0) {
self.speed = 0;
}
}
// Update position based on speed and angle
self.x += Math.sin(self.angle) * self.speed;
self.y -= Math.cos(self.angle) * self.speed;
// Update rotation to match angle
self.rotation = self.angle;
// Keep within game boundaries
if (self.x < 0) {
self.x = 0;
}
if (self.x > 2048) {
self.x = 2048;
}
if (self.y < 0) {
self.y = 0;
}
if (self.y > 2732) {
self.y = 2732;
}
};
self.destroy = function () {
self.alive = false;
tween(self, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
Container.prototype.destroy.call(self);
}
});
};
return self;
});
var WantedStar = Container.expand(function () {
var self = Container.call(this);
self.graphic = self.attachAsset('wantedStar', {
anchorX: 0.5,
anchorY: 0.5
});
self.show = function () {
tween(self, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.elasticOut
});
};
self.hide = function () {
tween(self, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 300
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game state variables
var gameActive = true;
var player = null;
var vehicles = [];
var obstacles = [];
var buildings = [];
var roads = [];
var wantedLevel = 0;
var maxWantedLevel = 5;
var cash = storage.cash || 0;
var policeSpawnTimer = 0;
var policeSpawnDelay = 300;
var civilianSpawnTimer = 0;
var civilianSpawnDelay = 180;
var targetVehicle = null;
var isDragging = false;
var lastX = 0;
var lastY = 0;
var steerDirection = 0;
// UI elements
var cashText;
var wantedStars = [];
var speedMeter;
// Initialize the game environment
function initGame() {
// Create street layout
createCityLayout();
// Create the player
player = new Vehicle();
player.init('player');
player.x = 2048 / 2;
player.y = 2732 / 2;
game.addChild(player);
vehicles.push(player);
// Create some initial vehicles
for (var i = 0; i < 5; i++) {
spawnCivilianVehicle();
}
// Initialize UI
initUI();
// Start playing background music
LK.playMusic('gameMusic');
}
function createCityLayout() {
// Create a basic city grid with roads
var roadWidth = 400;
var blockSize = 600;
// Horizontal roads
for (var y = blockSize / 2; y < 2732; y += blockSize) {
var road = new Road();
road.init();
road.x = 2048 / 2;
road.y = y;
road.rotation = Math.PI / 2; // Rotate to make it horizontal
game.addChild(road);
roads.push(road);
}
// Vertical roads
for (var x = blockSize / 2; x < 2048; x += blockSize) {
var road = new Road();
road.init();
road.x = x;
road.y = 2732 / 2;
game.addChild(road);
roads.push(road);
}
// Create buildings in the grid spaces
for (var x = blockSize / 2; x < 2048; x += blockSize) {
for (var y = blockSize / 2; y < 2732; y += blockSize) {
// Skip road intersections
if (x % blockSize === blockSize / 2 && y % blockSize === blockSize / 2 || x % blockSize !== blockSize / 2 && y % blockSize !== blockSize / 2) {
continue;
}
var building = new Building();
building.init();
building.x = x;
building.y = y;
game.addChild(building);
buildings.push(building);
obstacles.push(building);
}
}
}
function initUI() {
// Create accelerate button
var accelerateButton = new Container();
var buttonGraphic = accelerateButton.attachAsset('speedIndicator', {
anchorX: 0.5,
anchorY: 0.5
});
accelerateButton.x = 2048 / 2;
accelerateButton.y = 2732 - 200;
var buttonText = new Text2('Accelerate', {
size: 40,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
accelerateButton.addChild(buttonText);
accelerateButton.interactive = true;
accelerateButton.on('down', function () {
player.accelerate();
});
game.addChild(accelerateButton);
cashText = new Text2('$' + cash, {
size: 60,
fill: 0x00FF00
});
cashText.anchor.set(0, 0);
LK.gui.topRight.addChild(cashText);
// Create wanted level stars
for (var i = 0; i < maxWantedLevel; i++) {
var star = new WantedStar();
star.x = -i * 60 - 30;
star.y = 60;
star.alpha = 0;
star.scale.set(0.5);
LK.gui.topRight.addChild(star);
wantedStars.push(star);
}
// Create speed meter
speedMeter = new SpeedMeter();
speedMeter.init();
speedMeter.x = 2048 / 2 - 200;
speedMeter.y = 2732 - 100;
game.addChild(speedMeter);
}
function updateWantedLevel(level) {
if (level === wantedLevel) {
return;
}
wantedLevel = level;
if (wantedLevel > maxWantedLevel) {
wantedLevel = maxWantedLevel;
}
for (var i = 0; i < wantedStars.length; i++) {
if (i < wantedLevel) {
wantedStars[i].show();
} else {
wantedStars[i].hide();
}
}
// Adjust police spawn rate based on wanted level
policeSpawnDelay = 300 - wantedLevel * 40;
if (policeSpawnDelay < 60) {
policeSpawnDelay = 60;
}
}
function spawnPoliceVehicle() {
var police = new Vehicle();
police.init('police');
// Spawn police at edge of screen
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
// Top
police.x = Math.random() * 2048;
police.y = -100;
police.angle = Math.PI / 2;
break;
case 1:
// Right
police.x = 2048 + 100;
police.y = Math.random() * 2732;
police.angle = Math.PI;
break;
case 2:
// Bottom
police.x = Math.random() * 2048;
police.y = 2732 + 100;
police.angle = -Math.PI / 2;
break;
case 3:
// Left
police.x = -100;
police.y = Math.random() * 2732;
police.angle = 0;
break;
}
game.addChild(police);
vehicles.push(police);
// Play police siren sound
LK.getSound('policeSiren').play();
return police;
}
function spawnCivilianVehicle() {
var civilian = new Vehicle();
civilian.init('civilian');
// Random position on a road
var onVertical = Math.random() > 0.5;
if (onVertical) {
var roadIndex = Math.floor(Math.random() * (roads.length / 2));
civilian.x = roads[roadIndex].x;
civilian.y = Math.random() * 2732;
civilian.angle = Math.random() > 0.5 ? Math.PI / 2 : -Math.PI / 2;
} else {
var roadIndex = Math.floor(Math.random() * (roads.length / 2)) + roads.length / 2;
civilian.x = Math.random() * 2048;
civilian.y = roads[roadIndex].y;
civilian.angle = Math.random() > 0.5 ? 0 : Math.PI;
}
civilian.maxSpeed = 3 + Math.random() * 4;
game.addChild(civilian);
vehicles.push(civilian);
return civilian;
}
function stealVehicle(target) {
if (!target || target === player || target.type === 'player') {
return;
}
// Remove the old player vehicle
var oldPlayerIndex = vehicles.indexOf(player);
if (oldPlayerIndex !== -1) {
vehicles.splice(oldPlayerIndex, 1);
}
player.destroy();
// Replace target with player
var targetIndex = vehicles.indexOf(target);
if (targetIndex !== -1) {
vehicles.splice(targetIndex, 1);
}
// Create new player with same position and angle
player = new Vehicle();
player.init('player');
player.x = target.x;
player.y = target.y;
player.angle = target.angle;
player.rotation = target.rotation;
game.addChild(player);
vehicles.push(player);
// Destroy old vehicle
target.destroy();
// Increase wanted level and cash
updateWantedLevel(wantedLevel + 1);
addCash(100);
// Play sound
LK.getSound('carTheft').play();
// Reset target
targetVehicle = null;
}
function addCash(amount) {
cash += amount;
cashText.setText('$' + cash);
storage.cash = cash;
// Update score for leaderboards
LK.setScore(cash);
}
function checkCollisions() {
// Check player collision with other vehicles
for (var i = 0; i < vehicles.length; i++) {
var vehicle = vehicles[i];
if (vehicle === player || !vehicle.alive) {
continue;
}
if (player.intersects(vehicle)) {
// Handle collision
var crashSpeed = player.speed;
player.speed = Math.max(0, player.speed - 2);
// Play crash sound if fast enough
if (crashSpeed > 3) {
LK.getSound('crash').play();
// If crashed into police, increase wanted level
if (vehicle.type === 'police') {
updateWantedLevel(wantedLevel + 1);
}
// Visual feedback
LK.effects.flashObject(player, 0xFFFFFF, 300);
}
// Check if player is stopped near a vehicle - potential theft target
if (player.speed < 1 && vehicle.type !== 'police') {
targetVehicle = vehicle;
}
}
}
// Check player collision with obstacles
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
if (player.intersects(obstacle)) {
// Reduce speed on obstacle collision
var crashSpeed = player.speed;
player.speed = Math.max(0, player.speed - 1);
// Play crash sound if fast enough
if (crashSpeed > 3) {
LK.getSound('crash').play();
// Visual feedback
LK.effects.flashObject(player, 0xFFFFFF, 300);
}
}
}
}
function updateVehicles() {
// Update player vehicle
if (steerDirection !== 0) {
player.turn(steerDirection);
}
// Update all vehicles
for (var i = vehicles.length - 1; i >= 0; i--) {
var vehicle = vehicles[i];
if (!vehicle.alive) {
vehicles.splice(i, 1);
continue;
}
// AI behavior for non-player vehicles
if (vehicle !== player) {
// Simple AI: accelerate forward, avoid obstacles with random turns
vehicle.accelerate();
// Police AI: chase player
if (vehicle.type === 'police') {
// Calculate angle to player
var dx = player.x - vehicle.x;
var dy = player.y - vehicle.y;
var targetAngle = Math.atan2(dx, -dy);
// Find shortest turn direction
var angleDiff = targetAngle - vehicle.angle;
while (angleDiff > Math.PI) {
angleDiff -= Math.PI * 2;
}
while (angleDiff < -Math.PI) {
angleDiff += Math.PI * 2;
}
// Turn towards player
if (angleDiff > 0.05) {
vehicle.turn(0.5);
} else if (angleDiff < -0.05) {
vehicle.turn(-0.5);
}
}
// Civilian AI: random movement along roads
else {
if (Math.random() < 0.02) {
vehicle.turn((Math.random() - 0.5) * 0.1);
}
// Randomly brake sometimes
if (Math.random() < 0.01) {
vehicle.brake();
}
}
// Check for off-screen vehicles
if (vehicle.x < -200 || vehicle.x > 2248 || vehicle.y < -200 || vehicle.y > 2932) {
// Remove vehicle if it's far off-screen
if (vehicle.type !== 'police' || Math.abs(vehicle.x - player.x) > 1000 || Math.abs(vehicle.y - player.y) > 1000) {
vehicle.destroy();
}
}
}
}
}
// Input handlers
game.down = function (x, y, obj) {
lastX = x;
lastY = y;
isDragging = true;
// If player is stopped and near a vehicle, steal it
if (player.speed < 1 && targetVehicle) {
stealVehicle(targetVehicle);
return;
}
// Always accelerate on touch down
player.accelerate();
};
game.up = function (x, y, obj) {
isDragging = false;
steerDirection = 0;
};
game.move = function (x, y, obj) {
if (!isDragging) {
return;
}
// Calculate steering based on horizontal drag
var dx = x - lastX;
// Set steering direction
if (dx > 10) {
steerDirection = 1;
} else if (dx < -10) {
steerDirection = -1;
} else {
steerDirection = 0;
}
// Update last position
lastX = x;
lastY = y;
};
// Main game update loop
game.update = function () {
if (!gameActive) {
return;
}
// Spawn police based on wanted level and timer
policeSpawnTimer++;
if (policeSpawnTimer >= policeSpawnDelay && wantedLevel > 0) {
spawnPoliceVehicle();
policeSpawnTimer = 0;
}
// Spawn civilian vehicles
civilianSpawnTimer++;
if (civilianSpawnTimer >= civilianSpawnDelay) {
spawnCivilianVehicle();
civilianSpawnTimer = 0;
}
// Update vehicle positions and AI
updateVehicles();
// Check for collisions
checkCollisions();
// Update UI elements
speedMeter.update(player.speed, player.maxSpeed);
// Engine sound
if (player.speed > 0) {
if (!engineSoundPlaying) {
LK.getSound('carEngine').play();
engineSoundPlaying = true;
}
} else {
engineSoundPlaying = false;
}
// Limit number of vehicles for performance
while (vehicles.length > 20) {
// Remove oldest civilian vehicles first
for (var i = 0; i < vehicles.length; i++) {
if (vehicles[i] !== player && vehicles[i].type === 'civilian') {
vehicles[i].destroy();
vehicles.splice(i, 1);
break;
}
}
}
// Game over condition: too many police collisions
if (wantedLevel >= maxWantedLevel) {
var policeCount = 0;
for (var i = 0; i < vehicles.length; i++) {
if (vehicles[i].type === 'police') {
policeCount++;
}
}
// If surrounded by too many police, game over
if (policeCount >= 5) {
// Save high score
if (cash > storage.highScore) {
storage.highScore = cash;
}
// Game over
LK.showGameOver();
gameActive = false;
}
}
};
// Initialize the game
var engineSoundPlaying = false;
initGame();
red topdown look of luxury speedy car. Single Game Texture. In-Game asset. Blank background. High contrast. No shadows
blue top down look of police cars. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
top down view of building. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
sketchy old fashion pentagram luxury star. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
car gear top view. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows