/****
* 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