/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Bus = Container.expand(function () { var self = Container.call(this); var busGraphics = self.attachAsset('bus', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3; self.maxSpeed = 5; self.acceleration = 0.1; self.deceleration = 0.2; self.moving = false; self.movingForward = true; self.passengers = 0; self.maxPassengers = 20; self.destinationScore = 0; self.heroScore = 0; self.efficiencyScore = 0; self.riskScore = 0; self.startMoving = function () { self.moving = true; }; self.stopMoving = function () { self.moving = false; }; self.accelerate = function () { if (self.speed < self.maxSpeed) { self.speed += self.acceleration; } if (self.speed > self.maxSpeed) { self.speed = self.maxSpeed; } }; self.decelerate = function () { if (self.speed > 0) { self.speed -= self.deceleration; } if (self.speed < 0) { self.speed = 0; } }; self.addPassenger = function () { if (self.passengers < self.maxPassengers) { self.passengers++; return true; } return false; }; self.honkHorn = function () { LK.getSound('busHorn').play(); }; self.update = function () { if (self.moving) { self.accelerate(); } else { self.decelerate(); } self.y += self.speed * (self.movingForward ? -1 : 1); }; return self; }); var ChoiceButton = Container.expand(function () { var self = Container.call(this); self.background = self.attachAsset('passengerStop', { anchorX: 0.5, anchorY: 0.5, width: 800, height: 120, color: 0x3498db }); self.label = new Text2("", { size: 50, fill: 0xFFFFFF }); self.label.anchor.set(0.5, 0.5); self.addChild(self.label); self.choiceData = null; self.setChoice = function (text, data) { self.label.setText(text); self.choiceData = data; }; self.down = function () { tween(self.background, { alpha: 0.7 }, { duration: 100, easing: tween.linear }); }; self.up = function () { tween(self.background, { alpha: 1 }, { duration: 100, easing: tween.linear, onFinish: function onFinish() { if (self.choiceData && typeof self.choiceData.action === 'function') { self.choiceData.action(); } } }); }; return self; }); var Obstacle = Container.expand(function () { var self = Container.call(this); var obstacleGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); self.active = true; self.disable = function () { self.active = false; tween(obstacleGraphics, { alpha: 0 }, { duration: 500, easing: tween.easeOut }); }; return self; }); var Passenger = Container.expand(function () { var self = Container.call(this); var passengerGraphics = self.attachAsset('passenger', { anchorX: 0.5, anchorY: 0.5 }); self.type = "standard"; // standard, elderly, emergency, etc. self.pointValue = 1; self.destinationStopId = ""; self.highlight = function () { tween(passengerGraphics, { alpha: 0.7 }, { duration: 300, easing: tween.easeInOut }); }; self.unhighlight = function () { tween(passengerGraphics, { alpha: 1 }, { duration: 300, easing: tween.easeInOut }); }; return self; }); var PassengerStop = Container.expand(function () { var self = Container.call(this); var stopGraphics = self.attachAsset('passengerStop', { anchorX: 0.5, anchorY: 0.5 }); self.id = ""; self.choices = []; self.passengersWaiting = 0; self.visited = false; self.active = false; self.activate = function () { self.active = true; tween(stopGraphics, { alpha: 0.5 }, { duration: 500, easing: tween.easeInOut }); }; self.deactivate = function () { self.active = false; tween(stopGraphics, { alpha: 1 }, { duration: 500, easing: tween.easeInOut }); }; self.reset = function () { self.visited = false; self.active = false; stopGraphics.alpha = 1; }; self.down = function (x, y, obj) { if (self.active && !self.visited) { showChoices(self); } }; return self; }); var Police = Container.expand(function () { var self = Container.call(this); var policeGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 2; self.update = function () { if (bus.moving) { // Police follows the bus vertically if (self.y < bus.y) { self.y += self.speed; } else { self.y -= self.speed; } // Police follows the bus horizontally if (self.x < bus.x) { self.x += self.speed; } else if (self.x > bus.x) { self.x -= self.speed; } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB // Sky blue }); /**** * Game Code ****/ function showPoliceEnding() { gameState = "ending"; // Stop music LK.stopMusic(); // Clear game clearGame(); // Create ending screen elements var titleText = new Text2("Caught by the Police!", { size: 100, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 700; game.addChild(titleText); var descText = new Text2("The police caught up with your bus.\nYour journey ends here.", { size: 50, fill: 0xFFFFFF }); descText.anchor.set(0.5, 0.5); descText.x = 1024; descText.y = 900; game.addChild(descText); // Create restart button var restartButton = game.addChild(LK.getAsset('passengerStop', { anchorX: 0.5, anchorY: 0.5, width: 400, height: 100, x: 1024, y: 1500, color: 0x27ae60 })); var restartText = new Text2("Try Again", { size: 60, fill: 0xFFFFFF }); restartText.anchor.set(0.5, 0.5); restartText.x = 1024; restartText.y = 1500; game.addChild(restartText); // Restart button interaction restartButton.interactive = true; restartButton.down = function () { tween(restartButton, { alpha: 0.7 }, { duration: 100, easing: tween.linear }); }; restartButton.up = function () { tween(restartButton, { alpha: 1 }, { duration: 100, easing: tween.linear, onFinish: function onFinish() { showTitleScreen(); } }); }; } // Game globals var bus; var police; var currentStop = 0; var stops = []; var passengers = []; var obstacles = []; var choiceButtons = []; var choicePanel; var gameStarted = false; var roadSegments = []; var roadY = 0; var scoreText; var passengerCountText; var destinationText; var gameState = "title"; // title, playing, ending // Game routes and choices data var routes = [{ id: "downtown", name: "Downtown Route", stops: [{ id: "central_station", name: "Central Station", x: 1024, y: 500, //{2Z} // Move the sixth stop closer // Move the first stop further down choices: [{ text: "Pick up business commuters (Efficiency +1)", effect: { efficiency: 1 }, nextStop: "financial_district" }, { text: "Take shortcut through alley (Risk +1)", effect: { risk: 1 }, nextStop: "market_street" }] }, { id: "financial_district", name: "Financial District", x: 700, y: -500, // Move the final stop closer //{28} // Move the second stop further down choices: [{ text: "Continue on schedule (Efficiency +1)", effect: { efficiency: 1 }, nextStop: "city_hall" }, { text: "Help lost tourist (Hero +1)", effect: { hero: 1 }, nextStop: "city_hall" }] }, { id: "market_street", name: "Market Street", x: 1350, y: 2000, //{2m} // Move the third stop closer //{2m} // Move the third stop further down choices: [{ text: "Take main road (Destination +1)", effect: { destination: 1 }, nextStop: "city_hall" }, { text: "Speed through yellow lights (Risk +1)", effect: { risk: 1 }, nextStop: "city_park" }] }, { id: "city_hall", name: "City Hall", x: 1024, y: 1500, //{2z} // Move the fourth stop closer //{2z} // Move the fourth stop further down choices: [{ text: "Follow standard route (Destination +1)", effect: { destination: 1 }, nextStop: "hospital" }, { text: "Wait for elderly passenger (Hero +1)", effect: { hero: 1 }, nextStop: "hospital" }] }, { id: "city_park", name: "City Park", x: 1500, y: 1000, //{2M} // Move the fifth stop closer //{2M} // Move the fifth stop further down choices: [{ text: "Return to main route (Destination +1)", effect: { destination: 1 }, nextStop: "hospital" }, { text: "Drive through park scenery (Risk +1)", effect: { risk: 1 }, nextStop: "university" }] }, { id: "hospital", name: "Hospital", x: 1024, y: 0, //{3c} // Move the seventh stop closer //{2Z} // Move the sixth stop further down choices: [{ text: "Complete route on time (Efficiency +1)", effect: { efficiency: 1 }, nextStop: "final_downtown" }, { text: "Help medical emergency (Hero +2)", effect: { hero: 2 }, nextStop: "final_downtown" }] }, { id: "university", name: "University", x: 1350, y: 3000, //{3c} // Move the seventh stop further down choices: [{ text: "Drive carefully with students (Destination +1)", effect: { destination: 1 }, nextStop: "final_downtown" }, { text: "Race the campus loop (Risk +2)", effect: { risk: 2 }, nextStop: "final_downtown" }] }, { id: "final_downtown", name: "Downtown Terminal", x: 1024, y: 2500, // Move the final stop further down choices: [{ text: "Complete Journey", effect: {}, nextStop: "end" }] }] }]; // Road generation function createRoad() { for (var i = 0; i < 25; i++) { // Increase the number of road segments to match the longer distance var roadSegment = game.addChild(LK.getAsset('road', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: roadY })); roadSegments.push(roadSegment); roadY -= 400; } } // Initialize game elements function initGame() { // Clear any existing elements clearGame(); // Set game state gameState = "playing"; // Create road roadY = 5000; // Increase the initial roadY to extend the distance between stops createRoad(); // Create bus bus = game.addChild(new Bus()); bus.x = 1024; bus.y = 2500; // Create police police = game.addChild(new Police()); police.x = 1024; police.y = 2700; // Initialize stops based on the downtown route var routeData = routes[0]; // Use downtown route for (var i = 0; i < routeData.stops.length; i++) { var stopData = routeData.stops[i]; var stop = game.addChild(new PassengerStop()); stop.id = stopData.id; stop.name = stopData.name; stop.x = stopData.x; stop.y = stopData.y; stop.choices = stopData.choices; stop.passengersWaiting = Math.floor(Math.random() * 5) + 1; stops.push(stop); } // Create choice panel (initially hidden) choicePanel = game.addChild(new Container()); choicePanel.visible = false; // Create choice buttons for (var i = 0; i < 2; i++) { var button = choicePanel.addChild(new ChoiceButton()); button.x = 1024; button.y = 1366 + i * 150; choiceButtons.push(button); } // Create UI text elements scoreText = new Text2("Score: 0", { size: 50, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); passengerCountText = new Text2("Passengers: 0/" + bus.maxPassengers, { size: 50, fill: 0xFFFFFF }); passengerCountText.anchor.set(1, 0); passengerCountText.x = -50; // Offset from right edge LK.gui.topRight.addChild(passengerCountText); destinationText = new Text2("", { size: 50, fill: 0xFFFFFF }); destinationText.anchor.set(0.5, 1); LK.gui.bottom.addChild(destinationText); // Start game gameStarted = true; currentStop = 0; // Play background music LK.playMusic('busMusic', { fade: { start: 0, end: 0.3, duration: 1000 } }); // Activate first stop if (stops.length > 0) { stops[0].activate(); updateDestinationText(stops[0].name); } // Start the bus moving immediately bus.startMoving(); } // Clean up all game elements function clearGame() { // Clear arrays stops = []; passengers = []; obstacles = []; roadSegments = []; choiceButtons = []; // Remove all children from game while (game.children.length > 0) { game.removeChild(game.children[0]); } // Reset states gameStarted = false; currentStop = 0; } // Show title screen function showTitleScreen() { gameState = "title"; // Clear game clearGame(); // Create title var titleText = new Text2("Bus Route Destiny", { size: 120, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 900; game.addChild(titleText); // Create start button var startButton = game.addChild(LK.getAsset('passengerStop', { anchorX: 0.5, anchorY: 0.5, width: 400, height: 100, x: 1024, y: 1300, color: 0x27ae60 })); var startText = new Text2("Start Driving", { size: 60, fill: 0xFFFFFF }); startText.anchor.set(0.5, 0.5); startText.x = 1024; startText.y = 1300; game.addChild(startText); // Create description var descText = new Text2("Drive the city bus, make choices at each stop,\nand discover your ultimate destination.", { size: 50, fill: 0xFFFFFF }); descText.anchor.set(0.5, 0.5); descText.x = 1024; descText.y = 1100; game.addChild(descText); // Start button interaction startButton.interactive = true; startButton.down = function () { tween(startButton, { alpha: 0.7 }, { duration: 100, easing: tween.linear }); }; startButton.up = function () { tween(startButton, { alpha: 1 }, { duration: 100, easing: tween.linear, onFinish: function onFinish() { initGame(); } }); }; } // Show choices at a stop function showChoices(stop) { // Stop the bus bus.stopMoving(); // Make choice panel visible choicePanel.visible = true; // Setup choice buttons for (var i = 0; i < stop.choices.length && i < choiceButtons.length; i++) { var choice = stop.choices[i]; choiceButtons[i].visible = true; choiceButtons[i].setChoice(choice.text, { action: function (choiceIndex) { return function () { // Apply choice effects var effect = stop.choices[choiceIndex].effect; if (effect.efficiency) { bus.efficiencyScore += effect.efficiency; } if (effect.hero) { bus.heroScore += effect.hero; } if (effect.risk) { bus.riskScore += effect.risk; } if (effect.destination) { bus.destinationScore += effect.destination; } // Add passengers for (var j = 0; j < stop.passengersWaiting; j++) { if (bus.addPassenger()) { LK.getSound('pickup').play(); LK.setScore(LK.getScore() + 1); updateScoreText(); } } // Mark stop as visited stop.visited = true; stop.deactivate(); // Hide choice panel choicePanel.visible = false; // Find next stop var nextStopId = stop.choices[choiceIndex].nextStop; if (nextStopId === "end") { // End the game and show the ending LK.setTimeout(function () { showEnding(); }, 1000); } else { // Find the next stop in the array for (var j = 0; j < stops.length; j++) { if (stops[j].id === nextStopId) { currentStop = j; stops[j].activate(); updateDestinationText(stops[j].name); break; } } // Resume driving bus.startMoving(); } }; }(i) }); } // Hide any unused buttons for (var i = stop.choices.length; i < choiceButtons.length; i++) { choiceButtons[i].visible = false; } } // Show game ending based on scores function showEnding() { gameState = "ending"; // Stop music LK.stopMusic(); // Determine ending type based on highest score var endingType = "standard"; var highestScore = Math.max(bus.destinationScore, bus.heroScore, bus.efficiencyScore, bus.riskScore); if (highestScore === bus.destinationScore) { endingType = "destination"; } else if (highestScore === bus.heroScore) { endingType = "hero"; } else if (highestScore === bus.efficiencyScore) { endingType = "efficiency"; } else if (highestScore === bus.riskScore) { endingType = "risk"; } // Clear game clearGame(); // Create ending screen elements var titleText = new Text2("Your Journey Ends", { size: 100, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 700; game.addChild(titleText); var endingText = ""; switch (endingType) { case "destination": endingText = "You followed the standard route flawlessly.\nYou've earned the respect of the transit authority for your reliability."; break; case "hero": endingText = "You went above and beyond to help passengers in need.\nYour compassion has made you a local hero in the community."; break; case "efficiency": endingText = "You prioritized efficiency and schedule adherence.\nYou've been promoted to lead driver for your professionalism."; break; case "risk": endingText = "Your adventurous driving style made for an exciting journey.\nPassengers remember your route as the most thrilling in town!"; break; default: endingText = "You completed your bus route.\nThank you for your service to the city."; } var descText = new Text2(endingText, { size: 50, fill: 0xFFFFFF }); descText.anchor.set(0.5, 0.5); descText.x = 1024; descText.y = 900; game.addChild(descText); // Show scores var scoresText = new Text2("Passengers: " + bus.passengers + "\n" + "Reliability Score: " + bus.destinationScore + "\n" + "Heroism Score: " + bus.heroScore + "\n" + "Efficiency Score: " + bus.efficiencyScore + "\n" + "Adventure Score: " + bus.riskScore, { size: 40, fill: 0xFFFFFF }); scoresText.anchor.set(0.5, 0.5); scoresText.x = 1024; scoresText.y = 1200; game.addChild(scoresText); // Create restart button var restartButton = game.addChild(LK.getAsset('passengerStop', { anchorX: 0.5, anchorY: 0.5, width: 400, height: 100, x: 1024, y: 1500, color: 0x27ae60 })); var restartText = new Text2("Drive Again", { size: 60, fill: 0xFFFFFF }); restartText.anchor.set(0.5, 0.5); restartText.x = 1024; restartText.y = 1500; game.addChild(restartText); // Restart button interaction restartButton.interactive = true; restartButton.down = function () { tween(restartButton, { alpha: 0.7 }, { duration: 100, easing: tween.linear }); }; restartButton.up = function () { tween(restartButton, { alpha: 1 }, { duration: 100, easing: tween.linear, onFinish: function onFinish() { showTitleScreen(); } }); }; } // Update UI functions function updateScoreText() { scoreText.setText("Score: " + LK.getScore()); passengerCountText.setText("Passengers: " + bus.passengers + "/" + bus.maxPassengers); } function updateDestinationText(stopName) { destinationText.setText("Next Stop: " + stopName); } // Game down event handler game.down = function (x, y, obj) { if (gameState === "title") { // Title screen interaction handled by button } else if (gameState === "playing") { // Check if bus horn area is pressed if (bus && !choicePanel.visible && x > bus.x - 150 && x < bus.x + 150 && y > bus.y - 75 && y < bus.y + 75) { bus.honkHorn(); } // Move bus left or right based on touch position if (x < 1024) { bus.x -= 50; // Move left } else { bus.x += 50; // Move right bus.movingForward = !bus.movingForward; // Toggle direction } } }; // Main game update game.update = function () { if (!gameStarted) { // Show title screen if game hasn't started yet if (gameState !== "title" && gameState !== "ending") { showTitleScreen(); } return; } // Update road for (var i = 0; i < roadSegments.length; i++) { if (bus.moving) { roadSegments[i].y += bus.speed; // If road segment is off screen, move it to the top if (roadSegments[i].y > 2732 + 200) { roadSegments[i].y = roadY; roadY -= 400; } } } // Update stops for (var i = 0; i < stops.length; i++) { if (bus.moving) { stops[i].y += bus.speed; } // Check if bus is at a stop if (!stops[i].visited && stops[i].active && Math.abs(bus.y - stops[i].y) < 50) { bus.stopMoving(); showChoices(stops[i]); } } // Update police police.update(); // Check for collision between police and bus if (!police.lastWasIntersecting && police.intersects(bus)) { // Collision just started LK.setTimeout(function () { showPoliceEnding(); }, 1000); } police.lastWasIntersecting = police.intersects(bus); // Update UI updateScoreText(); }; // Initialize by showing title screen showTitleScreen();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bus = Container.expand(function () {
var self = Container.call(this);
var busGraphics = self.attachAsset('bus', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.maxSpeed = 5;
self.acceleration = 0.1;
self.deceleration = 0.2;
self.moving = false;
self.movingForward = true;
self.passengers = 0;
self.maxPassengers = 20;
self.destinationScore = 0;
self.heroScore = 0;
self.efficiencyScore = 0;
self.riskScore = 0;
self.startMoving = function () {
self.moving = true;
};
self.stopMoving = function () {
self.moving = false;
};
self.accelerate = function () {
if (self.speed < self.maxSpeed) {
self.speed += self.acceleration;
}
if (self.speed > self.maxSpeed) {
self.speed = self.maxSpeed;
}
};
self.decelerate = function () {
if (self.speed > 0) {
self.speed -= self.deceleration;
}
if (self.speed < 0) {
self.speed = 0;
}
};
self.addPassenger = function () {
if (self.passengers < self.maxPassengers) {
self.passengers++;
return true;
}
return false;
};
self.honkHorn = function () {
LK.getSound('busHorn').play();
};
self.update = function () {
if (self.moving) {
self.accelerate();
} else {
self.decelerate();
}
self.y += self.speed * (self.movingForward ? -1 : 1);
};
return self;
});
var ChoiceButton = Container.expand(function () {
var self = Container.call(this);
self.background = self.attachAsset('passengerStop', {
anchorX: 0.5,
anchorY: 0.5,
width: 800,
height: 120,
color: 0x3498db
});
self.label = new Text2("", {
size: 50,
fill: 0xFFFFFF
});
self.label.anchor.set(0.5, 0.5);
self.addChild(self.label);
self.choiceData = null;
self.setChoice = function (text, data) {
self.label.setText(text);
self.choiceData = data;
};
self.down = function () {
tween(self.background, {
alpha: 0.7
}, {
duration: 100,
easing: tween.linear
});
};
self.up = function () {
tween(self.background, {
alpha: 1
}, {
duration: 100,
easing: tween.linear,
onFinish: function onFinish() {
if (self.choiceData && typeof self.choiceData.action === 'function') {
self.choiceData.action();
}
}
});
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.active = true;
self.disable = function () {
self.active = false;
tween(obstacleGraphics, {
alpha: 0
}, {
duration: 500,
easing: tween.easeOut
});
};
return self;
});
var Passenger = Container.expand(function () {
var self = Container.call(this);
var passengerGraphics = self.attachAsset('passenger', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = "standard"; // standard, elderly, emergency, etc.
self.pointValue = 1;
self.destinationStopId = "";
self.highlight = function () {
tween(passengerGraphics, {
alpha: 0.7
}, {
duration: 300,
easing: tween.easeInOut
});
};
self.unhighlight = function () {
tween(passengerGraphics, {
alpha: 1
}, {
duration: 300,
easing: tween.easeInOut
});
};
return self;
});
var PassengerStop = Container.expand(function () {
var self = Container.call(this);
var stopGraphics = self.attachAsset('passengerStop', {
anchorX: 0.5,
anchorY: 0.5
});
self.id = "";
self.choices = [];
self.passengersWaiting = 0;
self.visited = false;
self.active = false;
self.activate = function () {
self.active = true;
tween(stopGraphics, {
alpha: 0.5
}, {
duration: 500,
easing: tween.easeInOut
});
};
self.deactivate = function () {
self.active = false;
tween(stopGraphics, {
alpha: 1
}, {
duration: 500,
easing: tween.easeInOut
});
};
self.reset = function () {
self.visited = false;
self.active = false;
stopGraphics.alpha = 1;
};
self.down = function (x, y, obj) {
if (self.active && !self.visited) {
showChoices(self);
}
};
return self;
});
var Police = Container.expand(function () {
var self = Container.call(this);
var policeGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.update = function () {
if (bus.moving) {
// Police follows the bus vertically
if (self.y < bus.y) {
self.y += self.speed;
} else {
self.y -= self.speed;
}
// Police follows the bus horizontally
if (self.x < bus.x) {
self.x += self.speed;
} else if (self.x > bus.x) {
self.x -= self.speed;
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue
});
/****
* Game Code
****/
function showPoliceEnding() {
gameState = "ending";
// Stop music
LK.stopMusic();
// Clear game
clearGame();
// Create ending screen elements
var titleText = new Text2("Caught by the Police!", {
size: 100,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 700;
game.addChild(titleText);
var descText = new Text2("The police caught up with your bus.\nYour journey ends here.", {
size: 50,
fill: 0xFFFFFF
});
descText.anchor.set(0.5, 0.5);
descText.x = 1024;
descText.y = 900;
game.addChild(descText);
// Create restart button
var restartButton = game.addChild(LK.getAsset('passengerStop', {
anchorX: 0.5,
anchorY: 0.5,
width: 400,
height: 100,
x: 1024,
y: 1500,
color: 0x27ae60
}));
var restartText = new Text2("Try Again", {
size: 60,
fill: 0xFFFFFF
});
restartText.anchor.set(0.5, 0.5);
restartText.x = 1024;
restartText.y = 1500;
game.addChild(restartText);
// Restart button interaction
restartButton.interactive = true;
restartButton.down = function () {
tween(restartButton, {
alpha: 0.7
}, {
duration: 100,
easing: tween.linear
});
};
restartButton.up = function () {
tween(restartButton, {
alpha: 1
}, {
duration: 100,
easing: tween.linear,
onFinish: function onFinish() {
showTitleScreen();
}
});
};
}
// Game globals
var bus;
var police;
var currentStop = 0;
var stops = [];
var passengers = [];
var obstacles = [];
var choiceButtons = [];
var choicePanel;
var gameStarted = false;
var roadSegments = [];
var roadY = 0;
var scoreText;
var passengerCountText;
var destinationText;
var gameState = "title"; // title, playing, ending
// Game routes and choices data
var routes = [{
id: "downtown",
name: "Downtown Route",
stops: [{
id: "central_station",
name: "Central Station",
x: 1024,
y: 500,
//{2Z} // Move the sixth stop closer
// Move the first stop further down
choices: [{
text: "Pick up business commuters (Efficiency +1)",
effect: {
efficiency: 1
},
nextStop: "financial_district"
}, {
text: "Take shortcut through alley (Risk +1)",
effect: {
risk: 1
},
nextStop: "market_street"
}]
}, {
id: "financial_district",
name: "Financial District",
x: 700,
y: -500,
// Move the final stop closer
//{28} // Move the second stop further down
choices: [{
text: "Continue on schedule (Efficiency +1)",
effect: {
efficiency: 1
},
nextStop: "city_hall"
}, {
text: "Help lost tourist (Hero +1)",
effect: {
hero: 1
},
nextStop: "city_hall"
}]
}, {
id: "market_street",
name: "Market Street",
x: 1350,
y: 2000,
//{2m} // Move the third stop closer
//{2m} // Move the third stop further down
choices: [{
text: "Take main road (Destination +1)",
effect: {
destination: 1
},
nextStop: "city_hall"
}, {
text: "Speed through yellow lights (Risk +1)",
effect: {
risk: 1
},
nextStop: "city_park"
}]
}, {
id: "city_hall",
name: "City Hall",
x: 1024,
y: 1500,
//{2z} // Move the fourth stop closer
//{2z} // Move the fourth stop further down
choices: [{
text: "Follow standard route (Destination +1)",
effect: {
destination: 1
},
nextStop: "hospital"
}, {
text: "Wait for elderly passenger (Hero +1)",
effect: {
hero: 1
},
nextStop: "hospital"
}]
}, {
id: "city_park",
name: "City Park",
x: 1500,
y: 1000,
//{2M} // Move the fifth stop closer
//{2M} // Move the fifth stop further down
choices: [{
text: "Return to main route (Destination +1)",
effect: {
destination: 1
},
nextStop: "hospital"
}, {
text: "Drive through park scenery (Risk +1)",
effect: {
risk: 1
},
nextStop: "university"
}]
}, {
id: "hospital",
name: "Hospital",
x: 1024,
y: 0,
//{3c} // Move the seventh stop closer
//{2Z} // Move the sixth stop further down
choices: [{
text: "Complete route on time (Efficiency +1)",
effect: {
efficiency: 1
},
nextStop: "final_downtown"
}, {
text: "Help medical emergency (Hero +2)",
effect: {
hero: 2
},
nextStop: "final_downtown"
}]
}, {
id: "university",
name: "University",
x: 1350,
y: 3000,
//{3c} // Move the seventh stop further down
choices: [{
text: "Drive carefully with students (Destination +1)",
effect: {
destination: 1
},
nextStop: "final_downtown"
}, {
text: "Race the campus loop (Risk +2)",
effect: {
risk: 2
},
nextStop: "final_downtown"
}]
}, {
id: "final_downtown",
name: "Downtown Terminal",
x: 1024,
y: 2500,
// Move the final stop further down
choices: [{
text: "Complete Journey",
effect: {},
nextStop: "end"
}]
}]
}];
// Road generation
function createRoad() {
for (var i = 0; i < 25; i++) {
// Increase the number of road segments to match the longer distance
var roadSegment = game.addChild(LK.getAsset('road', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: roadY
}));
roadSegments.push(roadSegment);
roadY -= 400;
}
}
// Initialize game elements
function initGame() {
// Clear any existing elements
clearGame();
// Set game state
gameState = "playing";
// Create road
roadY = 5000; // Increase the initial roadY to extend the distance between stops
createRoad();
// Create bus
bus = game.addChild(new Bus());
bus.x = 1024;
bus.y = 2500;
// Create police
police = game.addChild(new Police());
police.x = 1024;
police.y = 2700;
// Initialize stops based on the downtown route
var routeData = routes[0]; // Use downtown route
for (var i = 0; i < routeData.stops.length; i++) {
var stopData = routeData.stops[i];
var stop = game.addChild(new PassengerStop());
stop.id = stopData.id;
stop.name = stopData.name;
stop.x = stopData.x;
stop.y = stopData.y;
stop.choices = stopData.choices;
stop.passengersWaiting = Math.floor(Math.random() * 5) + 1;
stops.push(stop);
}
// Create choice panel (initially hidden)
choicePanel = game.addChild(new Container());
choicePanel.visible = false;
// Create choice buttons
for (var i = 0; i < 2; i++) {
var button = choicePanel.addChild(new ChoiceButton());
button.x = 1024;
button.y = 1366 + i * 150;
choiceButtons.push(button);
}
// Create UI text elements
scoreText = new Text2("Score: 0", {
size: 50,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
passengerCountText = new Text2("Passengers: 0/" + bus.maxPassengers, {
size: 50,
fill: 0xFFFFFF
});
passengerCountText.anchor.set(1, 0);
passengerCountText.x = -50; // Offset from right edge
LK.gui.topRight.addChild(passengerCountText);
destinationText = new Text2("", {
size: 50,
fill: 0xFFFFFF
});
destinationText.anchor.set(0.5, 1);
LK.gui.bottom.addChild(destinationText);
// Start game
gameStarted = true;
currentStop = 0;
// Play background music
LK.playMusic('busMusic', {
fade: {
start: 0,
end: 0.3,
duration: 1000
}
});
// Activate first stop
if (stops.length > 0) {
stops[0].activate();
updateDestinationText(stops[0].name);
}
// Start the bus moving immediately
bus.startMoving();
}
// Clean up all game elements
function clearGame() {
// Clear arrays
stops = [];
passengers = [];
obstacles = [];
roadSegments = [];
choiceButtons = [];
// Remove all children from game
while (game.children.length > 0) {
game.removeChild(game.children[0]);
}
// Reset states
gameStarted = false;
currentStop = 0;
}
// Show title screen
function showTitleScreen() {
gameState = "title";
// Clear game
clearGame();
// Create title
var titleText = new Text2("Bus Route Destiny", {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 900;
game.addChild(titleText);
// Create start button
var startButton = game.addChild(LK.getAsset('passengerStop', {
anchorX: 0.5,
anchorY: 0.5,
width: 400,
height: 100,
x: 1024,
y: 1300,
color: 0x27ae60
}));
var startText = new Text2("Start Driving", {
size: 60,
fill: 0xFFFFFF
});
startText.anchor.set(0.5, 0.5);
startText.x = 1024;
startText.y = 1300;
game.addChild(startText);
// Create description
var descText = new Text2("Drive the city bus, make choices at each stop,\nand discover your ultimate destination.", {
size: 50,
fill: 0xFFFFFF
});
descText.anchor.set(0.5, 0.5);
descText.x = 1024;
descText.y = 1100;
game.addChild(descText);
// Start button interaction
startButton.interactive = true;
startButton.down = function () {
tween(startButton, {
alpha: 0.7
}, {
duration: 100,
easing: tween.linear
});
};
startButton.up = function () {
tween(startButton, {
alpha: 1
}, {
duration: 100,
easing: tween.linear,
onFinish: function onFinish() {
initGame();
}
});
};
}
// Show choices at a stop
function showChoices(stop) {
// Stop the bus
bus.stopMoving();
// Make choice panel visible
choicePanel.visible = true;
// Setup choice buttons
for (var i = 0; i < stop.choices.length && i < choiceButtons.length; i++) {
var choice = stop.choices[i];
choiceButtons[i].visible = true;
choiceButtons[i].setChoice(choice.text, {
action: function (choiceIndex) {
return function () {
// Apply choice effects
var effect = stop.choices[choiceIndex].effect;
if (effect.efficiency) {
bus.efficiencyScore += effect.efficiency;
}
if (effect.hero) {
bus.heroScore += effect.hero;
}
if (effect.risk) {
bus.riskScore += effect.risk;
}
if (effect.destination) {
bus.destinationScore += effect.destination;
}
// Add passengers
for (var j = 0; j < stop.passengersWaiting; j++) {
if (bus.addPassenger()) {
LK.getSound('pickup').play();
LK.setScore(LK.getScore() + 1);
updateScoreText();
}
}
// Mark stop as visited
stop.visited = true;
stop.deactivate();
// Hide choice panel
choicePanel.visible = false;
// Find next stop
var nextStopId = stop.choices[choiceIndex].nextStop;
if (nextStopId === "end") {
// End the game and show the ending
LK.setTimeout(function () {
showEnding();
}, 1000);
} else {
// Find the next stop in the array
for (var j = 0; j < stops.length; j++) {
if (stops[j].id === nextStopId) {
currentStop = j;
stops[j].activate();
updateDestinationText(stops[j].name);
break;
}
}
// Resume driving
bus.startMoving();
}
};
}(i)
});
}
// Hide any unused buttons
for (var i = stop.choices.length; i < choiceButtons.length; i++) {
choiceButtons[i].visible = false;
}
}
// Show game ending based on scores
function showEnding() {
gameState = "ending";
// Stop music
LK.stopMusic();
// Determine ending type based on highest score
var endingType = "standard";
var highestScore = Math.max(bus.destinationScore, bus.heroScore, bus.efficiencyScore, bus.riskScore);
if (highestScore === bus.destinationScore) {
endingType = "destination";
} else if (highestScore === bus.heroScore) {
endingType = "hero";
} else if (highestScore === bus.efficiencyScore) {
endingType = "efficiency";
} else if (highestScore === bus.riskScore) {
endingType = "risk";
}
// Clear game
clearGame();
// Create ending screen elements
var titleText = new Text2("Your Journey Ends", {
size: 100,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 700;
game.addChild(titleText);
var endingText = "";
switch (endingType) {
case "destination":
endingText = "You followed the standard route flawlessly.\nYou've earned the respect of the transit authority for your reliability.";
break;
case "hero":
endingText = "You went above and beyond to help passengers in need.\nYour compassion has made you a local hero in the community.";
break;
case "efficiency":
endingText = "You prioritized efficiency and schedule adherence.\nYou've been promoted to lead driver for your professionalism.";
break;
case "risk":
endingText = "Your adventurous driving style made for an exciting journey.\nPassengers remember your route as the most thrilling in town!";
break;
default:
endingText = "You completed your bus route.\nThank you for your service to the city.";
}
var descText = new Text2(endingText, {
size: 50,
fill: 0xFFFFFF
});
descText.anchor.set(0.5, 0.5);
descText.x = 1024;
descText.y = 900;
game.addChild(descText);
// Show scores
var scoresText = new Text2("Passengers: " + bus.passengers + "\n" + "Reliability Score: " + bus.destinationScore + "\n" + "Heroism Score: " + bus.heroScore + "\n" + "Efficiency Score: " + bus.efficiencyScore + "\n" + "Adventure Score: " + bus.riskScore, {
size: 40,
fill: 0xFFFFFF
});
scoresText.anchor.set(0.5, 0.5);
scoresText.x = 1024;
scoresText.y = 1200;
game.addChild(scoresText);
// Create restart button
var restartButton = game.addChild(LK.getAsset('passengerStop', {
anchorX: 0.5,
anchorY: 0.5,
width: 400,
height: 100,
x: 1024,
y: 1500,
color: 0x27ae60
}));
var restartText = new Text2("Drive Again", {
size: 60,
fill: 0xFFFFFF
});
restartText.anchor.set(0.5, 0.5);
restartText.x = 1024;
restartText.y = 1500;
game.addChild(restartText);
// Restart button interaction
restartButton.interactive = true;
restartButton.down = function () {
tween(restartButton, {
alpha: 0.7
}, {
duration: 100,
easing: tween.linear
});
};
restartButton.up = function () {
tween(restartButton, {
alpha: 1
}, {
duration: 100,
easing: tween.linear,
onFinish: function onFinish() {
showTitleScreen();
}
});
};
}
// Update UI functions
function updateScoreText() {
scoreText.setText("Score: " + LK.getScore());
passengerCountText.setText("Passengers: " + bus.passengers + "/" + bus.maxPassengers);
}
function updateDestinationText(stopName) {
destinationText.setText("Next Stop: " + stopName);
}
// Game down event handler
game.down = function (x, y, obj) {
if (gameState === "title") {
// Title screen interaction handled by button
} else if (gameState === "playing") {
// Check if bus horn area is pressed
if (bus && !choicePanel.visible && x > bus.x - 150 && x < bus.x + 150 && y > bus.y - 75 && y < bus.y + 75) {
bus.honkHorn();
}
// Move bus left or right based on touch position
if (x < 1024) {
bus.x -= 50; // Move left
} else {
bus.x += 50; // Move right
bus.movingForward = !bus.movingForward; // Toggle direction
}
}
};
// Main game update
game.update = function () {
if (!gameStarted) {
// Show title screen if game hasn't started yet
if (gameState !== "title" && gameState !== "ending") {
showTitleScreen();
}
return;
}
// Update road
for (var i = 0; i < roadSegments.length; i++) {
if (bus.moving) {
roadSegments[i].y += bus.speed;
// If road segment is off screen, move it to the top
if (roadSegments[i].y > 2732 + 200) {
roadSegments[i].y = roadY;
roadY -= 400;
}
}
}
// Update stops
for (var i = 0; i < stops.length; i++) {
if (bus.moving) {
stops[i].y += bus.speed;
}
// Check if bus is at a stop
if (!stops[i].visited && stops[i].active && Math.abs(bus.y - stops[i].y) < 50) {
bus.stopMoving();
showChoices(stops[i]);
}
}
// Update police
police.update();
// Check for collision between police and bus
if (!police.lastWasIntersecting && police.intersects(bus)) {
// Collision just started
LK.setTimeout(function () {
showPoliceEnding();
}, 1000);
}
police.lastWasIntersecting = police.intersects(bus);
// Update UI
updateScoreText();
};
// Initialize by showing title screen
showTitleScreen();