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