Code edit (1 edits merged)
Please save this source code
User prompt
Parking Maze Challenge
Initial prompt
I want a game with cars and to park this car but it also has obstacles other cars to be able to pass the level You will have to avoid these obstacles without crashing into others and this has 50 levels
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
currentLevel: 1,
highestLevel: 1
});
/****
* Classes
****/
var Car = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.maxSpeed = 5;
self.rotationSpeed = 0;
self.maxRotationSpeed = 0.05;
self.friction = 0.95;
self.collided = false;
self.accelerate = function (amount) {
self.speed += amount;
if (self.speed > self.maxSpeed) {
self.speed = self.maxSpeed;
}
if (self.speed < -self.maxSpeed) {
self.speed = -self.maxSpeed;
}
};
self.rotate = function (amount) {
self.rotationSpeed += amount;
if (self.rotationSpeed > self.maxRotationSpeed) {
self.rotationSpeed = self.maxRotationSpeed;
}
if (self.rotationSpeed < -self.maxRotationSpeed) {
self.rotationSpeed = -self.maxRotationSpeed;
}
};
self.update = function () {
if (self.collided) {
return;
}
// Apply rotation
self.rotation += self.rotationSpeed;
self.rotationSpeed *= self.friction;
// Apply movement in direction of rotation
var dx = Math.sin(self.rotation) * self.speed;
var dy = -Math.cos(self.rotation) * self.speed;
self.x += dx;
self.y += dy;
// Apply friction
self.speed *= self.friction;
// Keep car within bounds
if (self.x < 100) {
self.x = 100;
}
if (self.x > 2048 - 100) {
self.x = 2048 - 100;
}
if (self.y < 100) {
self.y = 100;
}
if (self.y > 2732 - 100) {
self.y = 2732 - 100;
}
};
self.checkCollision = function (object) {
return self.intersects(object);
};
self.handleCollision = function () {
if (!self.collided) {
self.collided = true;
LK.getSound('crash').play();
LK.effects.flashObject(self, 0xff0000, 500);
tween(self, {
alpha: 0.5
}, {
duration: 300
});
// Reset player after a delay
LK.setTimeout(function () {
self.resetPosition();
}, 1000);
}
};
self.resetPosition = function () {
self.x = currentLevel.playerStartX;
self.y = currentLevel.playerStartY;
self.rotation = currentLevel.playerStartRotation || 0;
self.speed = 0;
self.rotationSpeed = 0;
self.collided = false;
tween(self, {
alpha: 1
}, {
duration: 300
});
};
return self;
});
var MovingObstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('movingObstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.direction = {
x: 1,
y: 0
};
self.waypoints = [];
self.currentWaypoint = 0;
self.setWaypoints = function (points) {
self.waypoints = points;
if (self.waypoints.length > 0) {
self.x = self.waypoints[0].x;
self.y = self.waypoints[0].y;
}
};
self.update = function () {
if (self.waypoints.length < 2) {
return;
}
var target = self.waypoints[self.currentWaypoint];
var dx = target.x - self.x;
var dy = target.y - self.y;
var distToTarget = Math.sqrt(dx * dx + dy * dy);
if (distToTarget < self.speed) {
// Reached waypoint, move to next
self.currentWaypoint = (self.currentWaypoint + 1) % self.waypoints.length;
} else {
// Move towards waypoint
self.x += dx / distToTarget * self.speed;
self.y += dy / distToTarget * self.speed;
}
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var ParkingSpot = Container.expand(function () {
var self = Container.call(this);
var spotGraphics = self.attachAsset('parkingSpot', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
self.isOccupied = false;
self.blinkInterval = null;
self.highlight = function () {
if (self.blinkInterval) {
LK.clearInterval(self.blinkInterval);
}
var blinkState = false;
self.blinkInterval = LK.setInterval(function () {
spotGraphics.alpha = blinkState ? 0.7 : 0.3;
blinkState = !blinkState;
}, 300);
};
self.stopHighlight = function () {
if (self.blinkInterval) {
LK.clearInterval(self.blinkInterval);
self.blinkInterval = null;
}
spotGraphics.alpha = 0.5;
};
self.checkParking = function (car) {
if (!car.collided && self.intersects(car)) {
// Check if car is mostly within the parking spot and has a similar rotation
var dx = Math.abs(car.x - self.x);
var dy = Math.abs(car.y - self.y);
var angleDiff = Math.abs((car.rotation % (Math.PI * 2) + Math.PI * 2) % (Math.PI * 2) - (self.rotation % (Math.PI * 2) + Math.PI * 2) % (Math.PI * 2));
if (angleDiff > Math.PI) {
angleDiff = Math.PI * 2 - angleDiff;
}
if (dx < 30 && dy < 30 && angleDiff < 0.3) {
self.isOccupied = true;
return true;
}
}
return false;
};
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
var wallGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x333333
});
/****
* Game Code
****/
// Game variables
var car;
var parkingSpot;
var obstacles = [];
var walls = [];
var movingObstacles = [];
var currentLevel = {
num: 1
};
var isLevelComplete = false;
var isGameOver = false;
var touchControls = {
active: false,
startX: 0,
startY: 0
};
// Load the current level from storage
var loadedLevel = storage.currentLevel || 1;
var highestLevel = storage.highestLevel || 1;
// Setup UI elements
var levelText = new Text2('Level ' + loadedLevel, {
size: 80,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelText);
var instructionText = new Text2('Park in the green spot!', {
size: 50,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
instructionText.y = 100;
LK.gui.top.addChild(instructionText);
// Control UI
var leftBtn = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
x: 150,
y: 2732 - 150,
tint: 0x0088ff,
alpha: 0.7
});
var rightBtn = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
x: 300,
y: 2732 - 150,
tint: 0x0088ff,
alpha: 0.7
});
var upBtn = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 - 150,
y: 2732 - 300,
tint: 0x0088ff,
alpha: 0.7
});
var downBtn = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 - 150,
y: 2732 - 150,
tint: 0x0088ff,
alpha: 0.7
});
game.addChild(leftBtn);
game.addChild(rightBtn);
game.addChild(upBtn);
game.addChild(downBtn);
// Define key press states
var keyState = {
up: false,
down: false,
left: false,
right: false
};
// Level definitions
function defineLevel(levelNum) {
var level = {
num: levelNum,
playerStartX: 1024,
playerStartY: 2200,
playerStartRotation: 0,
parkingSpotX: 1024,
parkingSpotY: 500,
parkingSpotRotation: Math.PI,
obstacles: [],
walls: [],
movingObstacles: []
};
// Add level-specific configurations
switch (levelNum) {
case 1:
// Simple first level - just park
instructionText.setText('Park in the green spot!');
break;
case 2:
// Add some static obstacles
level.obstacles = [{
x: 1024,
y: 1200,
width: 300,
height: 100
}];
break;
case 3:
// Moving obstacle
level.movingObstacles = [{
x: 1024,
y: 1500,
waypoints: [{
x: 700,
y: 1500
}, {
x: 1350,
y: 1500
}]
}];
break;
case 4:
// More complex layout
level.obstacles = [{
x: 800,
y: 1200,
width: 100,
height: 400
}, {
x: 1250,
y: 1500,
width: 100,
height: 400
}];
level.parkingSpotX = 800;
break;
case 5:
// Maze-like level
level.walls = [{
x: 600,
y: 1300,
rotation: 0
}, {
x: 800,
y: 1000,
rotation: Math.PI / 2
}, {
x: 1200,
y: 1000,
rotation: Math.PI / 2
}, {
x: 1400,
y: 1300,
rotation: 0
}, {
x: 1000,
y: 1700,
rotation: Math.PI / 2
}];
break;
default:
// For levels beyond 5, generate procedurally more complex layouts
var obstacleCount = Math.min(10, Math.floor(levelNum / 2) + 2);
for (var i = 0; i < obstacleCount; i++) {
var x = 300 + Math.random() * (2048 - 600);
var y = 300 + Math.random() * (2732 - 1000);
// Don't place obstacles near the start or parking spot
if (distance(x, y, level.playerStartX, level.playerStartY) > 300 && distance(x, y, level.parkingSpotX, level.parkingSpotY) > 300) {
level.obstacles.push({
x: x,
y: y,
width: 100,
height: 100
});
}
}
// Add some moving obstacles for higher levels
if (levelNum > 7) {
var movingCount = Math.min(3, Math.floor((levelNum - 7) / 5) + 1);
for (var j = 0; j < movingCount; j++) {
var startX = 300 + Math.random() * (2048 - 600);
var startY = 300 + Math.random() * (2732 - 1000);
var endX = 300 + Math.random() * (2048 - 600);
var endY = 300 + Math.random() * (2732 - 1000);
level.movingObstacles.push({
x: startX,
y: startY,
waypoints: [{
x: startX,
y: startY
}, {
x: endX,
y: endY
}]
});
}
}
instructionText.setText('Level ' + levelNum + ': Navigate the maze!');
}
return level;
}
function distance(x1, y1, x2, y2) {
var dx = x2 - x1;
var dy = y2 - y1;
return Math.sqrt(dx * dx + dy * dy);
}
function loadLevel(levelNum) {
// Clear previous level objects
clearLevel();
// Get level definition
currentLevel = defineLevel(levelNum);
// Update level text
levelText.setText('Level ' + levelNum);
// Create car
car = new Car();
car.x = currentLevel.playerStartX;
car.y = currentLevel.playerStartY;
car.rotation = currentLevel.playerStartRotation;
game.addChild(car);
// Create parking spot
parkingSpot = new ParkingSpot();
parkingSpot.x = currentLevel.parkingSpotX;
parkingSpot.y = currentLevel.parkingSpotY;
parkingSpot.rotation = currentLevel.parkingSpotRotation || 0;
game.addChild(parkingSpot);
parkingSpot.highlight();
// Create obstacles
if (currentLevel.obstacles) {
for (var i = 0; i < currentLevel.obstacles.length; i++) {
var obsData = currentLevel.obstacles[i];
var obstacle = new Obstacle();
obstacle.x = obsData.x;
obstacle.y = obsData.y;
if (obsData.width && obsData.height) {
obstacle.scale.x = obsData.width / 100;
obstacle.scale.y = obsData.height / 100;
}
game.addChild(obstacle);
obstacles.push(obstacle);
}
}
// Create walls
if (currentLevel.walls) {
for (var j = 0; j < currentLevel.walls.length; j++) {
var wallData = currentLevel.walls[j];
var wall = new Wall();
wall.x = wallData.x;
wall.y = wallData.y;
wall.rotation = wallData.rotation || 0;
game.addChild(wall);
walls.push(wall);
}
}
// Create moving obstacles
if (currentLevel.movingObstacles) {
for (var k = 0; k < currentLevel.movingObstacles.length; k++) {
var mobData = currentLevel.movingObstacles[k];
var movingObstacle = new MovingObstacle();
movingObstacle.x = mobData.x;
movingObstacle.y = mobData.y;
if (mobData.waypoints) {
movingObstacle.setWaypoints(mobData.waypoints);
}
game.addChild(movingObstacle);
movingObstacles.push(movingObstacle);
}
}
// Reset game state
isLevelComplete = false;
isGameOver = false;
// Play background music
LK.playMusic('bgmusic');
}
function clearLevel() {
// Remove car
if (car) {
car.destroy();
car = null;
}
// Remove parking spot
if (parkingSpot) {
parkingSpot.stopHighlight();
parkingSpot.destroy();
parkingSpot = null;
}
// Remove obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].destroy();
}
obstacles = [];
// Remove walls
for (var j = 0; j < walls.length; j++) {
walls[j].destroy();
}
walls = [];
// Remove moving obstacles
for (var k = 0; k < movingObstacles.length; k++) {
movingObstacles[k].destroy();
}
movingObstacles = [];
}
function completeLevel() {
if (!isLevelComplete) {
isLevelComplete = true;
// Play success sound
LK.getSound('success').play();
// Flash screen green
LK.effects.flashScreen(0x00ff00, 500);
// Update progress
if (currentLevel.num >= highestLevel) {
highestLevel = currentLevel.num + 1;
storage.highestLevel = highestLevel;
}
// Save current level
storage.currentLevel = currentLevel.num + 1;
// Show level complete message
instructionText.setText("Level Complete!");
// Load next level after delay
LK.setTimeout(function () {
if (currentLevel.num >= 50) {
// Game complete!
instructionText.setText("Congratulations! You completed all levels!");
LK.showYouWin();
} else {
loadLevel(currentLevel.num + 1);
}
}, 2000);
}
}
// Handle control button events
leftBtn.interactive = true;
leftBtn.down = function () {
keyState.left = true;
};
leftBtn.up = function () {
keyState.left = false;
};
rightBtn.interactive = true;
rightBtn.down = function () {
keyState.right = true;
};
rightBtn.up = function () {
keyState.right = false;
};
upBtn.interactive = true;
upBtn.down = function () {
keyState.up = true;
};
upBtn.up = function () {
keyState.up = false;
};
downBtn.interactive = true;
downBtn.down = function () {
keyState.down = true;
};
downBtn.up = function () {
keyState.down = false;
};
// Handle touch input for the game area
game.down = function (x, y, obj) {
// Only respond to touches not on control buttons
if (obj !== leftBtn && obj !== rightBtn && obj !== upBtn && obj !== downBtn) {
touchControls.active = true;
touchControls.startX = x;
touchControls.startY = y;
}
};
game.up = function (x, y, obj) {
touchControls.active = false;
};
game.move = function (x, y, obj) {
if (touchControls.active) {
var dx = x - touchControls.startX;
var dy = y - touchControls.startY;
// Reset if drag is too large
if (Math.abs(dx) > 100 || Math.abs(dy) > 100) {
touchControls.startX = x;
touchControls.startY = y;
}
// Apply car control based on drag direction
if (dx < -10) {
car.rotate(-0.01);
} else if (dx > 10) {
car.rotate(0.01);
}
if (dy < -10) {
car.accelerate(0.1);
} else if (dy > 10) {
car.accelerate(-0.1);
}
}
};
// Game update loop
game.update = function () {
if (isLevelComplete || isGameOver || !car) {
return;
}
// Handle keyboard-style controls
if (keyState.left) {
car.rotate(-0.01);
}
if (keyState.right) {
car.rotate(0.01);
}
if (keyState.up) {
car.accelerate(0.1);
}
if (keyState.down) {
car.accelerate(-0.1);
}
// Update moving obstacles
for (var i = 0; i < movingObstacles.length; i++) {
movingObstacles[i].update();
// Check collision with car
if (car && !car.collided && car.checkCollision(movingObstacles[i])) {
car.handleCollision();
}
}
// Check collisions with static obstacles
for (var j = 0; j < obstacles.length; j++) {
if (car && !car.collided && car.checkCollision(obstacles[j])) {
car.handleCollision();
}
}
// Check collisions with walls
for (var k = 0; k < walls.length; k++) {
if (car && !car.collided && car.checkCollision(walls[k])) {
car.handleCollision();
}
}
// Check if car is in parking spot
if (parkingSpot && car && !car.collided && parkingSpot.checkParking(car)) {
completeLevel();
}
};
// Load the initial level
loadLevel(loadedLevel); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
currentLevel: 1,
highestLevel: 1
});
/****
* Classes
****/
var Car = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.maxSpeed = 5;
self.rotationSpeed = 0;
self.maxRotationSpeed = 0.05;
self.friction = 0.95;
self.collided = false;
self.accelerate = function (amount) {
self.speed += amount;
if (self.speed > self.maxSpeed) {
self.speed = self.maxSpeed;
}
if (self.speed < -self.maxSpeed) {
self.speed = -self.maxSpeed;
}
};
self.rotate = function (amount) {
self.rotationSpeed += amount;
if (self.rotationSpeed > self.maxRotationSpeed) {
self.rotationSpeed = self.maxRotationSpeed;
}
if (self.rotationSpeed < -self.maxRotationSpeed) {
self.rotationSpeed = -self.maxRotationSpeed;
}
};
self.update = function () {
if (self.collided) {
return;
}
// Apply rotation
self.rotation += self.rotationSpeed;
self.rotationSpeed *= self.friction;
// Apply movement in direction of rotation
var dx = Math.sin(self.rotation) * self.speed;
var dy = -Math.cos(self.rotation) * self.speed;
self.x += dx;
self.y += dy;
// Apply friction
self.speed *= self.friction;
// Keep car within bounds
if (self.x < 100) {
self.x = 100;
}
if (self.x > 2048 - 100) {
self.x = 2048 - 100;
}
if (self.y < 100) {
self.y = 100;
}
if (self.y > 2732 - 100) {
self.y = 2732 - 100;
}
};
self.checkCollision = function (object) {
return self.intersects(object);
};
self.handleCollision = function () {
if (!self.collided) {
self.collided = true;
LK.getSound('crash').play();
LK.effects.flashObject(self, 0xff0000, 500);
tween(self, {
alpha: 0.5
}, {
duration: 300
});
// Reset player after a delay
LK.setTimeout(function () {
self.resetPosition();
}, 1000);
}
};
self.resetPosition = function () {
self.x = currentLevel.playerStartX;
self.y = currentLevel.playerStartY;
self.rotation = currentLevel.playerStartRotation || 0;
self.speed = 0;
self.rotationSpeed = 0;
self.collided = false;
tween(self, {
alpha: 1
}, {
duration: 300
});
};
return self;
});
var MovingObstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('movingObstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.direction = {
x: 1,
y: 0
};
self.waypoints = [];
self.currentWaypoint = 0;
self.setWaypoints = function (points) {
self.waypoints = points;
if (self.waypoints.length > 0) {
self.x = self.waypoints[0].x;
self.y = self.waypoints[0].y;
}
};
self.update = function () {
if (self.waypoints.length < 2) {
return;
}
var target = self.waypoints[self.currentWaypoint];
var dx = target.x - self.x;
var dy = target.y - self.y;
var distToTarget = Math.sqrt(dx * dx + dy * dy);
if (distToTarget < self.speed) {
// Reached waypoint, move to next
self.currentWaypoint = (self.currentWaypoint + 1) % self.waypoints.length;
} else {
// Move towards waypoint
self.x += dx / distToTarget * self.speed;
self.y += dy / distToTarget * self.speed;
}
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var ParkingSpot = Container.expand(function () {
var self = Container.call(this);
var spotGraphics = self.attachAsset('parkingSpot', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
self.isOccupied = false;
self.blinkInterval = null;
self.highlight = function () {
if (self.blinkInterval) {
LK.clearInterval(self.blinkInterval);
}
var blinkState = false;
self.blinkInterval = LK.setInterval(function () {
spotGraphics.alpha = blinkState ? 0.7 : 0.3;
blinkState = !blinkState;
}, 300);
};
self.stopHighlight = function () {
if (self.blinkInterval) {
LK.clearInterval(self.blinkInterval);
self.blinkInterval = null;
}
spotGraphics.alpha = 0.5;
};
self.checkParking = function (car) {
if (!car.collided && self.intersects(car)) {
// Check if car is mostly within the parking spot and has a similar rotation
var dx = Math.abs(car.x - self.x);
var dy = Math.abs(car.y - self.y);
var angleDiff = Math.abs((car.rotation % (Math.PI * 2) + Math.PI * 2) % (Math.PI * 2) - (self.rotation % (Math.PI * 2) + Math.PI * 2) % (Math.PI * 2));
if (angleDiff > Math.PI) {
angleDiff = Math.PI * 2 - angleDiff;
}
if (dx < 30 && dy < 30 && angleDiff < 0.3) {
self.isOccupied = true;
return true;
}
}
return false;
};
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
var wallGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x333333
});
/****
* Game Code
****/
// Game variables
var car;
var parkingSpot;
var obstacles = [];
var walls = [];
var movingObstacles = [];
var currentLevel = {
num: 1
};
var isLevelComplete = false;
var isGameOver = false;
var touchControls = {
active: false,
startX: 0,
startY: 0
};
// Load the current level from storage
var loadedLevel = storage.currentLevel || 1;
var highestLevel = storage.highestLevel || 1;
// Setup UI elements
var levelText = new Text2('Level ' + loadedLevel, {
size: 80,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelText);
var instructionText = new Text2('Park in the green spot!', {
size: 50,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
instructionText.y = 100;
LK.gui.top.addChild(instructionText);
// Control UI
var leftBtn = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
x: 150,
y: 2732 - 150,
tint: 0x0088ff,
alpha: 0.7
});
var rightBtn = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
x: 300,
y: 2732 - 150,
tint: 0x0088ff,
alpha: 0.7
});
var upBtn = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 - 150,
y: 2732 - 300,
tint: 0x0088ff,
alpha: 0.7
});
var downBtn = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 - 150,
y: 2732 - 150,
tint: 0x0088ff,
alpha: 0.7
});
game.addChild(leftBtn);
game.addChild(rightBtn);
game.addChild(upBtn);
game.addChild(downBtn);
// Define key press states
var keyState = {
up: false,
down: false,
left: false,
right: false
};
// Level definitions
function defineLevel(levelNum) {
var level = {
num: levelNum,
playerStartX: 1024,
playerStartY: 2200,
playerStartRotation: 0,
parkingSpotX: 1024,
parkingSpotY: 500,
parkingSpotRotation: Math.PI,
obstacles: [],
walls: [],
movingObstacles: []
};
// Add level-specific configurations
switch (levelNum) {
case 1:
// Simple first level - just park
instructionText.setText('Park in the green spot!');
break;
case 2:
// Add some static obstacles
level.obstacles = [{
x: 1024,
y: 1200,
width: 300,
height: 100
}];
break;
case 3:
// Moving obstacle
level.movingObstacles = [{
x: 1024,
y: 1500,
waypoints: [{
x: 700,
y: 1500
}, {
x: 1350,
y: 1500
}]
}];
break;
case 4:
// More complex layout
level.obstacles = [{
x: 800,
y: 1200,
width: 100,
height: 400
}, {
x: 1250,
y: 1500,
width: 100,
height: 400
}];
level.parkingSpotX = 800;
break;
case 5:
// Maze-like level
level.walls = [{
x: 600,
y: 1300,
rotation: 0
}, {
x: 800,
y: 1000,
rotation: Math.PI / 2
}, {
x: 1200,
y: 1000,
rotation: Math.PI / 2
}, {
x: 1400,
y: 1300,
rotation: 0
}, {
x: 1000,
y: 1700,
rotation: Math.PI / 2
}];
break;
default:
// For levels beyond 5, generate procedurally more complex layouts
var obstacleCount = Math.min(10, Math.floor(levelNum / 2) + 2);
for (var i = 0; i < obstacleCount; i++) {
var x = 300 + Math.random() * (2048 - 600);
var y = 300 + Math.random() * (2732 - 1000);
// Don't place obstacles near the start or parking spot
if (distance(x, y, level.playerStartX, level.playerStartY) > 300 && distance(x, y, level.parkingSpotX, level.parkingSpotY) > 300) {
level.obstacles.push({
x: x,
y: y,
width: 100,
height: 100
});
}
}
// Add some moving obstacles for higher levels
if (levelNum > 7) {
var movingCount = Math.min(3, Math.floor((levelNum - 7) / 5) + 1);
for (var j = 0; j < movingCount; j++) {
var startX = 300 + Math.random() * (2048 - 600);
var startY = 300 + Math.random() * (2732 - 1000);
var endX = 300 + Math.random() * (2048 - 600);
var endY = 300 + Math.random() * (2732 - 1000);
level.movingObstacles.push({
x: startX,
y: startY,
waypoints: [{
x: startX,
y: startY
}, {
x: endX,
y: endY
}]
});
}
}
instructionText.setText('Level ' + levelNum + ': Navigate the maze!');
}
return level;
}
function distance(x1, y1, x2, y2) {
var dx = x2 - x1;
var dy = y2 - y1;
return Math.sqrt(dx * dx + dy * dy);
}
function loadLevel(levelNum) {
// Clear previous level objects
clearLevel();
// Get level definition
currentLevel = defineLevel(levelNum);
// Update level text
levelText.setText('Level ' + levelNum);
// Create car
car = new Car();
car.x = currentLevel.playerStartX;
car.y = currentLevel.playerStartY;
car.rotation = currentLevel.playerStartRotation;
game.addChild(car);
// Create parking spot
parkingSpot = new ParkingSpot();
parkingSpot.x = currentLevel.parkingSpotX;
parkingSpot.y = currentLevel.parkingSpotY;
parkingSpot.rotation = currentLevel.parkingSpotRotation || 0;
game.addChild(parkingSpot);
parkingSpot.highlight();
// Create obstacles
if (currentLevel.obstacles) {
for (var i = 0; i < currentLevel.obstacles.length; i++) {
var obsData = currentLevel.obstacles[i];
var obstacle = new Obstacle();
obstacle.x = obsData.x;
obstacle.y = obsData.y;
if (obsData.width && obsData.height) {
obstacle.scale.x = obsData.width / 100;
obstacle.scale.y = obsData.height / 100;
}
game.addChild(obstacle);
obstacles.push(obstacle);
}
}
// Create walls
if (currentLevel.walls) {
for (var j = 0; j < currentLevel.walls.length; j++) {
var wallData = currentLevel.walls[j];
var wall = new Wall();
wall.x = wallData.x;
wall.y = wallData.y;
wall.rotation = wallData.rotation || 0;
game.addChild(wall);
walls.push(wall);
}
}
// Create moving obstacles
if (currentLevel.movingObstacles) {
for (var k = 0; k < currentLevel.movingObstacles.length; k++) {
var mobData = currentLevel.movingObstacles[k];
var movingObstacle = new MovingObstacle();
movingObstacle.x = mobData.x;
movingObstacle.y = mobData.y;
if (mobData.waypoints) {
movingObstacle.setWaypoints(mobData.waypoints);
}
game.addChild(movingObstacle);
movingObstacles.push(movingObstacle);
}
}
// Reset game state
isLevelComplete = false;
isGameOver = false;
// Play background music
LK.playMusic('bgmusic');
}
function clearLevel() {
// Remove car
if (car) {
car.destroy();
car = null;
}
// Remove parking spot
if (parkingSpot) {
parkingSpot.stopHighlight();
parkingSpot.destroy();
parkingSpot = null;
}
// Remove obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].destroy();
}
obstacles = [];
// Remove walls
for (var j = 0; j < walls.length; j++) {
walls[j].destroy();
}
walls = [];
// Remove moving obstacles
for (var k = 0; k < movingObstacles.length; k++) {
movingObstacles[k].destroy();
}
movingObstacles = [];
}
function completeLevel() {
if (!isLevelComplete) {
isLevelComplete = true;
// Play success sound
LK.getSound('success').play();
// Flash screen green
LK.effects.flashScreen(0x00ff00, 500);
// Update progress
if (currentLevel.num >= highestLevel) {
highestLevel = currentLevel.num + 1;
storage.highestLevel = highestLevel;
}
// Save current level
storage.currentLevel = currentLevel.num + 1;
// Show level complete message
instructionText.setText("Level Complete!");
// Load next level after delay
LK.setTimeout(function () {
if (currentLevel.num >= 50) {
// Game complete!
instructionText.setText("Congratulations! You completed all levels!");
LK.showYouWin();
} else {
loadLevel(currentLevel.num + 1);
}
}, 2000);
}
}
// Handle control button events
leftBtn.interactive = true;
leftBtn.down = function () {
keyState.left = true;
};
leftBtn.up = function () {
keyState.left = false;
};
rightBtn.interactive = true;
rightBtn.down = function () {
keyState.right = true;
};
rightBtn.up = function () {
keyState.right = false;
};
upBtn.interactive = true;
upBtn.down = function () {
keyState.up = true;
};
upBtn.up = function () {
keyState.up = false;
};
downBtn.interactive = true;
downBtn.down = function () {
keyState.down = true;
};
downBtn.up = function () {
keyState.down = false;
};
// Handle touch input for the game area
game.down = function (x, y, obj) {
// Only respond to touches not on control buttons
if (obj !== leftBtn && obj !== rightBtn && obj !== upBtn && obj !== downBtn) {
touchControls.active = true;
touchControls.startX = x;
touchControls.startY = y;
}
};
game.up = function (x, y, obj) {
touchControls.active = false;
};
game.move = function (x, y, obj) {
if (touchControls.active) {
var dx = x - touchControls.startX;
var dy = y - touchControls.startY;
// Reset if drag is too large
if (Math.abs(dx) > 100 || Math.abs(dy) > 100) {
touchControls.startX = x;
touchControls.startY = y;
}
// Apply car control based on drag direction
if (dx < -10) {
car.rotate(-0.01);
} else if (dx > 10) {
car.rotate(0.01);
}
if (dy < -10) {
car.accelerate(0.1);
} else if (dy > 10) {
car.accelerate(-0.1);
}
}
};
// Game update loop
game.update = function () {
if (isLevelComplete || isGameOver || !car) {
return;
}
// Handle keyboard-style controls
if (keyState.left) {
car.rotate(-0.01);
}
if (keyState.right) {
car.rotate(0.01);
}
if (keyState.up) {
car.accelerate(0.1);
}
if (keyState.down) {
car.accelerate(-0.1);
}
// Update moving obstacles
for (var i = 0; i < movingObstacles.length; i++) {
movingObstacles[i].update();
// Check collision with car
if (car && !car.collided && car.checkCollision(movingObstacles[i])) {
car.handleCollision();
}
}
// Check collisions with static obstacles
for (var j = 0; j < obstacles.length; j++) {
if (car && !car.collided && car.checkCollision(obstacles[j])) {
car.handleCollision();
}
}
// Check collisions with walls
for (var k = 0; k < walls.length; k++) {
if (car && !car.collided && car.checkCollision(walls[k])) {
car.handleCollision();
}
}
// Check if car is in parking spot
if (parkingSpot && car && !car.collided && parkingSpot.checkParking(car)) {
completeLevel();
}
};
// Load the initial level
loadLevel(loadedLevel);