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);