User prompt
Let's make the game a bit more agar.io-style, with the courier in the center and the map scrolling. And arrows indicate the pickup and delivery points. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Let's make the game a bit more agar.io-style, with the courier in the center and the map scrolling. And arrows indicate the pickup and delivery points. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
fill all screen with shops and buildings. And change colours orders and customers. Customers colors match the their order color ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
delete gray bars on screen
User prompt
please add another ai couriers and at the start may be more than 1 customer order different foods. And fix the building and shops locations. emptied first row because player cant reach there ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Connect building entrances with buildings. Have couriers pick up and deliver packages. If couriers intersect with each other or the player, they can change their path or turn back and take an alternative route.
User prompt
Please direct the couriers' paths so they don't intersect. They also can't pick up or deliver packages. Please also adjust the height of building entrances to 1px.
User prompt
Other AI couriers are frozen. Could you please take a look at them? They are not doing their job.
User prompt
The neighborhood should be infinite, like going to the far left of the screen and reaching the far right. Like in the game Snake. Packages should keep appearing. Each time a package is completed, a new one is created.
User prompt
At the beginning of the game, there can be multiple packages at the same time, for example, 5 packages. Match the colors of these packages and the customer. Other couriers should not be chasing the same package.
User prompt
Cars should be able to enter the neighborhood. Buildings and shops should have entrances. Couriers should be required to come to the asphalt in front of the entrance to pick up and make deliveries. The red dot representing customers should be located exactly in the middle of the building.
User prompt
Other couriers can only move vertically or horizontally between buildings. They cannot travel diagonally. Their speeds also vary. They can create traffic congestion. Add cars based on the money earned outside of the couriers. Start with 10 cars and increase to 20 cars until you reach $200. Cars, couriers, and the player cannot drive over each other.
User prompt
The size of the buildings should be smaller and the roads should be wider.
User prompt
The order is completed when it arrives at the customer's premises.
User prompt
Buildings should be arranged in an orderly manner. All buildings should have roads around them and these roads should be connected to each other.
User prompt
The neighborhood layout should consist of a 4-block park in the middle and buildings arranged in a non-circular pattern around it.
User prompt
To avoid couriers getting stuck in buildings, designate wider routes and have couriers follow them to reach the customer. They should choose which route to use. However, they must be able to reach the customer. Furthermore, if a package arrives anywhere in the store, it should be picked up and delivered to the customer's location within the building.
User prompt
Couriers do not wander around randomly, they just follow the routes and pick up and deliver the package.
User prompt
The purpose of other couriers is to pick up the order and deliver it to the customer.
User prompt
Customers should only be visible when the order arrives. If the courier doesn't pick up the order, it should disappear after a while. And then there will be new orders and new customers at different locations. Other couriers will be randomly passing through the streets, and they will be competing with us.
User prompt
The package's time starts when the courier receives the package.
User prompt
Please have buildings and shops line up in a circle. Layer by layer, covering the entire screen, with these circles gradually taking on more of the screen shape with each layer. Roads should be asphalt-colored, with no buildings overlapping. Shops and houses should change with each new game.
User prompt
the shops are need to be in a row as circular. And every new game will be changed shops and houses randomly.
User prompt
okay, we need to change the map. I want to make a neighbourhood. Middle of the screen have a park. And houses like a circular plan. and 1 outer layer is circular and have another houses and shops randomly. And i dont want to see gray squares on the screen.
User prompt
please show buildings are with dark blue, shops are orange, order is yellow. And customers must be in buildings. And please allow minimum 25 seconds per order completing.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var AICourier = Container.expand(function () {
var self = Container.call(this);
var courierGraphics = self.attachAsset('courier', {
anchorX: 0.5,
anchorY: 0.5
});
courierGraphics.tint = 0xff5722; // Orange tint for AI courier
self.speed = 6; // Slightly slower than player
self.hasOrder = false;
self.targetRestaurant = null;
self.targetCustomer = null;
self.currentOrder = null;
self.state = 'searching'; // 'searching', 'pickup', 'delivery'
self.thinkTimer = 0;
self.moveToward = function (targetX, targetY) {
var dx = targetX - self.x;
var dy = targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 10) {
var newX = self.x + dx / distance * self.speed;
var newY = self.y + dy / distance * self.speed;
// Check collision with buildings
var canMove = true;
for (var i = 0; i < buildings.length; i++) {
var tempCourier = {
x: newX,
y: newY,
width: 60,
height: 60
};
var building = buildings[i];
if (tempCourier.x < building.x + building.width / 2 && tempCourier.x + tempCourier.width / 2 > building.x - building.width / 2 && tempCourier.y < building.y + building.height / 2 && tempCourier.y + tempCourier.height / 2 > building.y - building.height / 2) {
canMove = false;
break;
}
}
if (canMove) {
self.x = newX;
self.y = newY;
}
}
};
self.update = function () {
self.thinkTimer += 16.67;
// AI decision making every 500ms
if (self.thinkTimer >= 500) {
self.thinkTimer = 0;
if (self.state === 'searching' && !self.hasOrder) {
// Look for available orders
var availableOrders = aiOrders.filter(function (order) {
return !order.claimed;
});
if (availableOrders.length > 0) {
self.currentOrder = availableOrders[0];
self.currentOrder.claimed = true;
self.state = 'pickup';
}
}
}
// Execute current behavior
if (self.state === 'pickup' && self.currentOrder) {
self.moveToward(self.currentOrder.restaurant.x, self.currentOrder.restaurant.y);
// Check if reached restaurant
var dx = self.currentOrder.restaurant.x - self.x;
var dy = self.currentOrder.restaurant.y - self.y;
if (Math.sqrt(dx * dx + dy * dy) < 50) {
self.hasOrder = true;
self.state = 'delivery';
// Move order visual to AI courier
self.currentOrder.x = self.x;
self.currentOrder.y = self.y - 40;
}
} else if (self.state === 'delivery' && self.currentOrder && self.hasOrder) {
self.moveToward(self.currentOrder.customer.x, self.currentOrder.customer.y);
// Move order with AI courier
self.currentOrder.x = self.x;
self.currentOrder.y = self.y - 40;
// Check if reached customer
var dx = self.currentOrder.customer.x - self.x;
var dy = self.currentOrder.customer.y - self.y;
if (Math.sqrt(dx * dx + dy * dy) < 50) {
// Complete delivery
self.completeDelivery();
}
}
};
self.completeDelivery = function () {
if (!self.currentOrder) return;
// Clean up order
self.currentOrder.restaurant.hasOrder = false;
self.currentOrder.customer.waitingForOrder = false;
// Remove delivery target indicator
if (self.currentOrder.customer.deliveryTarget) {
tween.stop(self.currentOrder.customer.deliveryTarget);
self.currentOrder.customer.deliveryTarget.destroy();
self.currentOrder.customer.deliveryTarget = null;
}
self.currentOrder.destroy();
for (var i = aiOrders.length - 1; i >= 0; i--) {
if (aiOrders[i] === self.currentOrder) {
aiOrders.splice(i, 1);
break;
}
}
self.currentOrder = null;
self.hasOrder = false;
self.state = 'searching';
};
return self;
});
var Courier = Container.expand(function () {
var self = Container.call(this);
var courierGraphics = self.attachAsset('courier', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.hasOrder = false;
self.targetRestaurant = null;
self.targetCustomer = null;
self.moveToward = function (targetX, targetY) {
var dx = targetX - self.x;
var dy = targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 10) {
var newX = self.x + dx / distance * self.speed;
var newY = self.y + dy / distance * self.speed;
// Check collision with buildings
var canMove = true;
for (var i = 0; i < buildings.length; i++) {
var tempCourier = {
x: newX,
y: newY,
width: 60,
height: 60
};
var building = buildings[i];
if (tempCourier.x < building.x + building.width / 2 && tempCourier.x + tempCourier.width / 2 > building.x - building.width / 2 && tempCourier.y < building.y + building.height / 2 && tempCourier.y + tempCourier.height / 2 > building.y - building.height / 2) {
canMove = false;
break;
}
}
if (canMove) {
self.x = newX;
self.y = newY;
}
}
};
return self;
});
var Customer = Container.expand(function () {
var self = Container.call(this);
var customerGraphics = self.attachAsset('customer', {
anchorX: 0.5,
anchorY: 0.5
});
self.waitingForOrder = false;
self.orderTime = 0;
self.maxWaitTime = 10000; // 10 seconds
self.deliveryTarget = null;
self.update = function () {
if (self.waitingForOrder) {
self.orderTime += 16.67; // Approximate ms per frame at 60fps
}
};
return self;
});
var Order = Container.expand(function () {
var self = Container.call(this);
var orderGraphics = self.attachAsset('order', {
anchorX: 0.5,
anchorY: 0.5
});
self.restaurant = null;
self.customer = null;
self.timeLimit = 25000; // 25 seconds
self.timeRemaining = self.timeLimit;
self.update = function () {
if (self.timeRemaining > 0) {
self.timeRemaining -= 16.67;
}
};
return self;
});
var PowerUp = Container.expand(function (type) {
var self = Container.call(this);
var powerupGraphics = self.attachAsset(type === 'health' ? 'healthPowerup' : 'timePowerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = type;
self.lifeTime = 0;
self.maxLifeTime = 8000; // 8 seconds
self.update = function () {
self.lifeTime += 16.67;
// Pulse animation
var pulse = 1 + 0.2 * Math.sin(self.lifeTime * 0.01);
powerupGraphics.scaleX = pulse;
powerupGraphics.scaleY = pulse;
};
return self;
});
var Restaurant = Container.expand(function () {
var self = Container.call(this);
var restaurantGraphics = self.attachAsset('restaurant', {
anchorX: 0.5,
anchorY: 0.5
});
self.hasOrder = false;
self.orderReady = false;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x8BC34A
});
/****
* Game Code
****/
// Game variables
var courier;
var aiCouriers = [];
var restaurants = [];
var customers = [];
var orders = [];
var aiOrders = [];
var powerUps = [];
var buildings = [];
var health = 100;
var money = 0;
var currentOrder = null;
var gameState = 'pickup'; // 'pickup', 'delivery'
var timeFreezeActive = false;
var timeFreezeRemaining = 0;
// UI Elements
var healthBar = new Text2('Health: 100', {
size: 60,
fill: 0xFF0000
});
healthBar.anchor.set(0, 0);
LK.gui.topLeft.addChild(healthBar);
healthBar.x = 120;
healthBar.y = 20;
var moneyText = new Text2('$0', {
size: 60,
fill: 0x00FF00
});
moneyText.anchor.set(1, 0);
LK.gui.topRight.addChild(moneyText);
moneyText.x = -20;
moneyText.y = 20;
var orderTimer = new Text2('', {
size: 50,
fill: 0xFFFF00
});
orderTimer.anchor.set(0.5, 0);
LK.gui.top.addChild(orderTimer);
orderTimer.y = 100;
// Create neighborhood layout
function createNeighborhood() {
// Create roads (grid pattern)
for (var x = 0; x < 2048; x += 300) {
for (var y = 0; y < 2732; y += 300) {
var road = game.addChild(LK.getAsset('road', {
anchorX: 0.5,
anchorY: 0.5,
x: x + 150,
y: y + 150
}));
}
}
// Create buildings in grid formation avoiding roads and first row
var buildingRows = 6;
var buildingCols = 5;
var gridSpacingX = 300; // Match road spacing
var gridSpacingY = 300; // Match road spacing
var startX = 225; // Center buildings between roads
var startY = 375; // Start from second row to keep first row empty
for (var row = 1; row < buildingRows; row++) {
// Start from row 1, not 0
for (var col = 0; col < buildingCols; col++) {
var buildingX = startX + col * gridSpacingX;
var buildingY = startY + row * gridSpacingY;
// Ensure buildings stay within game bounds
if (buildingX < 2048 - 60 && buildingY < 2732 - 50) {
var building = game.addChild(LK.getAsset('building', {
anchorX: 0.5,
anchorY: 0.5,
x: buildingX,
y: buildingY
}));
buildings.push(building);
}
}
}
// Create restaurants in proper grid positions avoiding first row
for (var i = 0; i < 6; i++) {
var restaurant = game.addChild(new Restaurant());
restaurant.x = 75 + i % 3 * 300;
restaurant.y = 375 + Math.floor(i / 3) * 600;
restaurants.push(restaurant);
}
// Create customers - place them inside buildings
var customerCount = Math.min(8, buildings.length);
for (var i = 0; i < customerCount; i++) {
var customer = game.addChild(new Customer());
// Place customer at same position as building
customer.x = buildings[i].x;
customer.y = buildings[i].y;
customers.push(customer);
}
}
function createNewOrder() {
if (currentOrder) return;
var availableRestaurants = restaurants.filter(function (r) {
return !r.hasOrder;
});
var availableCustomers = customers.filter(function (c) {
return !c.waitingForOrder;
});
if (availableRestaurants.length === 0 || availableCustomers.length === 0) return;
var restaurant = availableRestaurants[Math.floor(Math.random() * availableRestaurants.length)];
var customer = availableCustomers[Math.floor(Math.random() * availableCustomers.length)];
var order = game.addChild(new Order());
order.x = restaurant.x;
order.y = restaurant.y - 60;
order.restaurant = restaurant;
order.customer = customer;
restaurant.hasOrder = true;
restaurant.orderReady = true;
customer.waitingForOrder = true;
customer.orderTime = 0;
// Create delivery target indicator
var deliveryTarget = game.addChild(LK.getAsset('deliveryTarget', {
anchorX: 0.5,
anchorY: 0.5,
x: customer.x,
y: customer.y - 50
}));
customer.deliveryTarget = deliveryTarget;
// Start flashing animation
tween(deliveryTarget, {
alpha: 0.3
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(deliveryTarget, {
alpha: 1
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (deliveryTarget.parent) {
tween(deliveryTarget, {
alpha: 0.3
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(deliveryTarget, {
alpha: 1
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
}
}
});
}
});
currentOrder = order;
orders.push(order);
gameState = 'pickup';
}
function createAIOrder() {
var availableRestaurants = restaurants.filter(function (r) {
return !r.hasOrder;
});
var availableCustomers = customers.filter(function (c) {
return !c.waitingForOrder;
});
if (availableRestaurants.length === 0 || availableCustomers.length === 0) return;
var restaurant = availableRestaurants[Math.floor(Math.random() * availableRestaurants.length)];
var customer = availableCustomers[Math.floor(Math.random() * availableCustomers.length)];
var order = game.addChild(new Order());
order.x = restaurant.x;
order.y = restaurant.y - 60;
order.restaurant = restaurant;
order.customer = customer;
order.claimed = false; // For AI to claim
restaurant.hasOrder = true;
restaurant.orderReady = true;
customer.waitingForOrder = true;
customer.orderTime = 0;
// Create delivery target indicator
var deliveryTarget = game.addChild(LK.getAsset('deliveryTarget', {
anchorX: 0.5,
anchorY: 0.5,
x: customer.x,
y: customer.y - 50
}));
customer.deliveryTarget = deliveryTarget;
// Start flashing animation
tween(deliveryTarget, {
alpha: 0.3
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(deliveryTarget, {
alpha: 1
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (deliveryTarget.parent) {
tween(deliveryTarget, {
alpha: 0.3
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(deliveryTarget, {
alpha: 1
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
}
}
});
}
});
aiOrders.push(order);
}
function spawnPowerUp() {
if (powerUps.length >= 3) return;
var type = Math.random() < 0.6 ? 'health' : 'time';
var powerUp = game.addChild(new PowerUp(type));
powerUp.x = Math.random() * 1800 + 124;
powerUp.y = Math.random() * 2400 + 166;
powerUps.push(powerUp);
}
function updateUI() {
healthBar.setText('Health: ' + Math.floor(health));
moneyText.setText('$' + money);
if (currentOrder && gameState === 'delivery') {
var timeLeft = Math.max(0, currentOrder.timeRemaining / 1000);
orderTimer.setText('Deliver in: ' + timeLeft.toFixed(1) + 's');
} else {
orderTimer.setText('');
}
}
function checkCollisions() {
// Check courier-restaurant collision for pickup
if (gameState === 'pickup' && currentOrder) {
if (courier.intersects(currentOrder.restaurant)) {
// Pick up order
LK.getSound('pickup').play();
courier.hasOrder = true;
gameState = 'delivery';
currentOrder.x = courier.x;
currentOrder.y = courier.y - 40;
}
}
// Check courier-customer collision for delivery
if (gameState === 'delivery' && currentOrder && courier.hasOrder) {
if (courier.intersects(currentOrder.customer)) {
// Deliver order
LK.getSound('delivery').play();
completeDelivery();
}
}
// Check courier-powerup collisions
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
if (courier.intersects(powerUp)) {
LK.getSound('powerup').play();
if (powerUp.type === 'health') {
health = Math.min(100, health + 25);
} else if (powerUp.type === 'time') {
timeFreezeActive = true;
timeFreezeRemaining = 3000; // 3 seconds
}
powerUp.destroy();
powerUps.splice(i, 1);
}
}
}
function completeDelivery() {
if (!currentOrder) return;
var deliveryTime = currentOrder.timeLimit - currentOrder.timeRemaining;
var bonus = 0;
if (currentOrder.timeRemaining > 0) {
// Successful delivery
var timeBonus = Math.floor(currentOrder.timeRemaining / 1000);
bonus = 10 + timeBonus;
money += bonus;
// Flash green for success
LK.effects.flashObject(courier, 0x00ff00, 500);
} else {
// Late delivery - health penalty
health -= 20;
LK.effects.flashObject(courier, 0xff0000, 1000);
if (health <= 0) {
LK.showGameOver();
return;
}
}
// Clean up order
currentOrder.restaurant.hasOrder = false;
currentOrder.customer.waitingForOrder = false;
// Remove delivery target indicator
if (currentOrder.customer.deliveryTarget) {
tween.stop(currentOrder.customer.deliveryTarget);
currentOrder.customer.deliveryTarget.destroy();
currentOrder.customer.deliveryTarget = null;
}
currentOrder.destroy();
for (var i = orders.length - 1; i >= 0; i--) {
if (orders[i] === currentOrder) {
orders.splice(i, 1);
break;
}
}
currentOrder = null;
courier.hasOrder = false;
gameState = 'pickup';
// Create new order after short delay
LK.setTimeout(function () {
createNewOrder();
}, 1000);
}
// Initialize game elements
createNeighborhood();
// Create courier
courier = game.addChild(new Courier());
courier.x = 1024;
courier.y = 1366;
// Touch controls
var targetX = courier.x;
var targetY = courier.y;
game.down = function (x, y, obj) {
targetX = x;
targetY = y;
};
game.move = function (x, y, obj) {
targetX = x;
targetY = y;
};
// Create AI couriers
for (var i = 0; i < 2; i++) {
var aiCourier = game.addChild(new AICourier());
aiCourier.x = 500 + i * 300;
aiCourier.y = 200;
aiCouriers.push(aiCourier);
}
// Create multiple initial orders
createNewOrder();
LK.setTimeout(function () {
createAIOrder();
}, 500);
LK.setTimeout(function () {
createAIOrder();
}, 1000);
// Spawn initial power-up
LK.setTimeout(function () {
spawnPowerUp();
}, 3000);
game.update = function () {
// Move courier toward target
courier.moveToward(targetX, targetY);
// Update time freeze
if (timeFreezeActive) {
timeFreezeRemaining -= 16.67;
if (timeFreezeRemaining <= 0) {
timeFreezeActive = false;
}
}
// Update current order timer (if not frozen)
if (currentOrder && !timeFreezeActive) {
currentOrder.update();
// Move order with courier if picked up
if (courier.hasOrder && gameState === 'delivery') {
currentOrder.x = courier.x;
currentOrder.y = courier.y - 40;
}
// Maintain delivery target flashing
if (gameState === 'delivery' && currentOrder.customer.deliveryTarget) {
var target = currentOrder.customer.deliveryTarget;
if (!target.isFlashing) {
var _flashTarget = function flashTarget() {
if (target.parent) {
tween(target, {
alpha: 0.3
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (target.parent) {
tween(target, {
alpha: 1
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: _flashTarget
});
}
}
});
}
};
target.isFlashing = true;
_flashTarget();
}
}
// Check for failed delivery
if (currentOrder.timeRemaining <= 0 && gameState === 'delivery') {
completeDelivery();
}
}
// Update customers
for (var i = 0; i < customers.length; i++) {
customers[i].update();
}
// Update AI couriers
for (var i = 0; i < aiCouriers.length; i++) {
aiCouriers[i].update();
}
// Create new AI orders periodically
if (LK.ticks % 360 === 0 && aiOrders.length < 3) {
// Every 6 seconds
createAIOrder();
}
// Update power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
powerUp.update();
if (powerUp.lifeTime >= powerUp.maxLifeTime) {
powerUp.destroy();
powerUps.splice(i, 1);
}
}
// Spawn new power-ups occasionally
if (LK.ticks % 600 === 0) {
// Every 10 seconds
spawnPowerUp();
}
// Check collisions
checkCollisions();
// Update UI
updateUI();
// Win condition (optional - could be score based)
if (money >= 200) {
LK.showYouWin();
}
}; ===================================================================
--- original.js
+++ change.js
@@ -11,332 +11,109 @@
var courierGraphics = self.attachAsset('courier', {
anchorX: 0.5,
anchorY: 0.5
});
- courierGraphics.tint = 0xff4444; // Red tint to distinguish from player
- self.speed = 6;
- self.targetX = 1024;
- self.targetY = 1366;
- self.changeTargetTimer = 0;
+ courierGraphics.tint = 0xff5722; // Orange tint for AI courier
+ self.speed = 6; // Slightly slower than player
self.hasOrder = false;
self.targetRestaurant = null;
self.targetCustomer = null;
- self.currentWaypoint = 0;
- self.routeWaypoints = [];
- self.currentPath = [];
- self.pathIndex = 0;
- self.update = function () {
- // Check for orders to pick up if not carrying one
- if (!self.hasOrder && currentOrders.length > 0) {
- // Find an unclaimed order that no other courier is chasing
- var availableOrder = null;
- for (var orderIdx = 0; orderIdx < currentOrders.length; orderIdx++) {
- var order = currentOrders[orderIdx];
- if (!order.isBeingChased && order.timerStarted === false) {
- availableOrder = order;
- break;
- }
- }
- if (availableOrder) {
- // Claim this order
- availableOrder.isBeingChased = true;
- self.targetOrder = availableOrder;
- // Check if can pick up from restaurant entrance area
- var restaurant = availableOrder.restaurant;
- var restaurantDistance = Math.sqrt(Math.pow(restaurant.entranceX - self.x, 2) + Math.pow(restaurant.entranceY - self.y, 2));
- if (restaurantDistance < 70) {
- // Pick up the order
- self.hasOrder = true;
- self.targetCustomer = availableOrder.customer;
- self.targetRestaurant = availableOrder.restaurant;
- // Start the package timer
- availableOrder.timerStarted = true;
- // Move order with AI courier
- availableOrder.x = self.x;
- availableOrder.y = self.y - 40;
- // Clear current path and find new path to customer
- var courierIndex = aiCouriers.indexOf(self);
- self.currentPath = findPath(self.x, self.y, self.targetCustomer.x, self.targetCustomer.y, courierIndex);
- self.pathIndex = 0;
- } else {
- // Find path to restaurant entrance if don't have one or reached end
- if (self.currentPath.length === 0 || self.pathIndex >= self.currentPath.length) {
- var courierIndex = aiCouriers.indexOf(self);
- self.currentPath = findPath(self.x, self.y, restaurant.entranceX, restaurant.entranceY, courierIndex);
- self.pathIndex = 0;
- }
- }
- }
- } else if (self.hasOrder && self.targetCustomer && self.targetOrder) {
- // AI courier is delivering - check if reached customer building entrance
- // Find the building that contains this customer
- var customerBuilding = null;
- for (var i = 0; i < buildings.length; i++) {
- if (buildings[i].x === self.targetCustomer.x && buildings[i].y === self.targetCustomer.y) {
- customerBuilding = buildings[i];
- break;
- }
- }
- var customerDistance = Infinity;
- if (customerBuilding) {
- customerDistance = Math.sqrt(Math.pow(customerBuilding.entranceX - self.x, 2) + Math.pow(customerBuilding.entranceY - self.y, 2));
- }
- if (customerDistance < 70) {
- // Deliver the order
- LK.getSound('delivery').play();
- self.hasOrder = false;
- self.targetCustomer = null;
- self.targetRestaurant = null;
- self.currentPath = [];
- self.pathIndex = 0;
- // Complete the delivery (similar to player delivery)
- if (self.targetOrder) {
- // Order completed successfully - AI gets the delivery done
- var deliveryTime = self.targetOrder.timeLimit - self.targetOrder.timeRemaining;
- if (self.targetOrder.timeRemaining > 0) {
- // Successful delivery by AI courier
- var timeBonus = Math.floor(self.targetOrder.timeRemaining / 1000);
- var bonus = 5 + timeBonus; // AI gets smaller bonus than player
- money += bonus;
- }
- self.targetOrder.restaurant.hasOrder = false;
- self.targetOrder.customer.waitingForOrder = false;
- self.targetOrder.customer.visible = false;
- if (self.targetOrder.customer.deliveryTarget) {
- tween.stop(self.targetOrder.customer.deliveryTarget);
- self.targetOrder.customer.deliveryTarget.destroy();
- self.targetOrder.customer.deliveryTarget = null;
- }
- self.targetOrder.destroy();
- for (var i = orders.length - 1; i >= 0; i--) {
- if (orders[i] === self.targetOrder) {
- orders.splice(i, 1);
- break;
- }
- }
- // Remove from currentOrders array
- for (var i = currentOrders.length - 1; i >= 0; i--) {
- if (currentOrders[i] === self.targetOrder) {
- currentOrders.splice(i, 1);
- break;
- }
- }
- self.targetOrder = null;
- // Create new order immediately after delivery
- createNewOrder();
- }
- } else {
- // Find path to customer building entrance if don't have one or reached end
- if (self.currentPath.length === 0 || self.pathIndex >= self.currentPath.length) {
- // Find the building that contains this customer
- var customerBuilding = null;
- for (var i = 0; i < buildings.length; i++) {
- if (buildings[i].x === self.targetCustomer.x && buildings[i].y === self.targetCustomer.y) {
- customerBuilding = buildings[i];
- break;
- }
- }
- var courierIndex = aiCouriers.indexOf(self);
- if (customerBuilding) {
- self.currentPath = findPath(self.x, self.y, customerBuilding.entranceX, customerBuilding.entranceY, courierIndex);
- } else {
- self.currentPath = findPath(self.x, self.y, self.targetCustomer.x, self.targetCustomer.y, courierIndex);
- }
- self.pathIndex = 0;
- }
- }
- } else {
- // When not carrying order, patrol using route network
- if (self.currentPath.length === 0 || self.pathIndex >= self.currentPath.length) {
- // Pick a random route node to patrol to
- if (routeNodes.length > 0) {
- var randomNode = routeNodes[Math.floor(Math.random() * routeNodes.length)];
- var courierIndex = aiCouriers.indexOf(self);
- self.currentPath = findPath(self.x, self.y, randomNode.x, randomNode.y, courierIndex);
- self.pathIndex = 0;
- }
- }
- }
- // Follow current path
- if (self.currentPath.length > 0 && self.pathIndex < self.currentPath.length) {
- var targetNode = self.currentPath[self.pathIndex];
- self.targetX = targetNode.x;
- self.targetY = targetNode.y;
- // Check if reached current path node
- var nodeDistance = Math.sqrt(Math.pow(targetNode.x - self.x, 2) + Math.pow(targetNode.y - self.y, 2));
- if (nodeDistance < 60) {
- self.pathIndex++;
- }
- } else {
- // No path or reached end - pick a random nearby target to keep moving
- if (routeNodes.length > 0) {
- var randomNode = routeNodes[Math.floor(Math.random() * routeNodes.length)];
- self.targetX = randomNode.x;
- self.targetY = randomNode.y;
- } else {
- self.targetX = self.x;
- self.targetY = self.y;
- }
- }
- // Move toward target using simple movement with collision detection
- var dx = self.targetX - self.x;
- var dy = self.targetY - self.y;
+ self.currentOrder = null;
+ self.state = 'searching'; // 'searching', 'pickup', 'delivery'
+ self.thinkTimer = 0;
+ self.moveToward = function (targetX, targetY) {
+ var dx = targetX - self.x;
+ var dy = targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 10) {
var newX = self.x + dx / distance * self.speed;
var newY = self.y + dy / distance * self.speed;
- // Check collisions before moving
+ // Check collision with buildings
var canMove = true;
- // Check collision with cars
- for (var i = 0; i < cars.length; i++) {
- var carDx = Math.abs(newX - cars[i].x);
- var carDy = Math.abs(newY - cars[i].y);
- if (carDx < 40 && carDy < 40) {
+ for (var i = 0; i < buildings.length; i++) {
+ var tempCourier = {
+ x: newX,
+ y: newY,
+ width: 60,
+ height: 60
+ };
+ var building = buildings[i];
+ if (tempCourier.x < building.x + building.width / 2 && tempCourier.x + tempCourier.width / 2 > building.x - building.width / 2 && tempCourier.y < building.y + building.height / 2 && tempCourier.y + tempCourier.height / 2 > building.y - building.height / 2) {
canMove = false;
break;
}
}
- // Check collision with player courier
- var playerDx = Math.abs(newX - courier.x);
- var playerDy = Math.abs(newY - courier.y);
- if (playerDx < 50 && playerDy < 50) {
- canMove = false;
- // If blocked by player, try alternative route
- self.currentPath = [];
- self.pathIndex = 0;
- }
- // Check collision with other AI couriers
- for (var i = 0; i < aiCouriers.length; i++) {
- if (aiCouriers[i] === self) continue;
- var aiDx = Math.abs(newX - aiCouriers[i].x);
- var aiDy = Math.abs(newY - aiCouriers[i].y);
- if (aiDx < 50 && aiDy < 50) {
- canMove = false;
- // If blocked by another AI courier, try alternative route
- self.currentPath = [];
- self.pathIndex = 0;
- break;
- }
- }
if (canMove) {
self.x = newX;
self.y = newY;
- // World wrapping - if AI courier goes off left edge, appear on right edge
- if (self.x < worldLeftBound) {
- self.x = worldRightBound;
- } else if (self.x > worldRightBound) {
- self.x = worldLeftBound;
- }
- self.stuckTimer = 0;
- } else {
- // If stuck, try alternative movement
- if (!self.stuckTimer) self.stuckTimer = 0;
- self.stuckTimer += 16.67;
- if (self.stuckTimer > 1000) {
- // If stuck for more than 1 second
- // Try moving in a different direction
- var randomAngle = Math.random() * Math.PI * 2;
- var moveDistance = 20;
- self.x += Math.cos(randomAngle) * moveDistance;
- self.y += Math.sin(randomAngle) * moveDistance;
- self.stuckTimer = 0;
- self.currentPath = []; // Clear current path to force new pathfinding
- }
}
}
- // Update order position if carrying one
- if (self.hasOrder && self.targetOrder) {
- self.targetOrder.x = self.x;
- self.targetOrder.y = self.y - 40;
- }
};
- return self;
-});
-var Car = Container.expand(function () {
- var self = Container.call(this);
- var carGraphics = self.attachAsset('courier', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- carGraphics.tint = 0x333333; // Dark gray for cars
- carGraphics.scaleX = 0.8;
- carGraphics.scaleY = 0.8;
- self.speed = 2 + Math.random() * 4; // Speed between 2-6
- self.direction = Math.random() < 0.5 ? 'horizontal' : 'vertical';
- self.movingPositive = Math.random() < 0.5; // true = right/down, false = left/up
- self.targetX = self.x;
- self.targetY = self.y;
- self.stuckTimer = 0;
- self.maxStuckTime = 2000; // 2 seconds before finding new path
self.update = function () {
- var oldX = self.x;
- var oldY = self.y;
- // Move only horizontally or vertically
- if (self.direction === 'horizontal') {
- if (self.movingPositive) {
- self.targetX = self.x + self.speed;
- } else {
- self.targetX = self.x - self.speed;
+ self.thinkTimer += 16.67;
+ // AI decision making every 500ms
+ if (self.thinkTimer >= 500) {
+ self.thinkTimer = 0;
+ if (self.state === 'searching' && !self.hasOrder) {
+ // Look for available orders
+ var availableOrders = aiOrders.filter(function (order) {
+ return !order.claimed;
+ });
+ if (availableOrders.length > 0) {
+ self.currentOrder = availableOrders[0];
+ self.currentOrder.claimed = true;
+ self.state = 'pickup';
+ }
}
- // No boundary reversal needed - world wraps infinitely
- } else {
- if (self.movingPositive) {
- self.targetY = self.y + self.speed;
- } else {
- self.targetY = self.y - self.speed;
+ }
+ // Execute current behavior
+ if (self.state === 'pickup' && self.currentOrder) {
+ self.moveToward(self.currentOrder.restaurant.x, self.currentOrder.restaurant.y);
+ // Check if reached restaurant
+ var dx = self.currentOrder.restaurant.x - self.x;
+ var dy = self.currentOrder.restaurant.y - self.y;
+ if (Math.sqrt(dx * dx + dy * dy) < 50) {
+ self.hasOrder = true;
+ self.state = 'delivery';
+ // Move order visual to AI courier
+ self.currentOrder.x = self.x;
+ self.currentOrder.y = self.y - 40;
}
- // Reverse direction at boundaries
- if (self.y > 2550 || self.y < 182) {
- self.movingPositive = !self.movingPositive;
+ } else if (self.state === 'delivery' && self.currentOrder && self.hasOrder) {
+ self.moveToward(self.currentOrder.customer.x, self.currentOrder.customer.y);
+ // Move order with AI courier
+ self.currentOrder.x = self.x;
+ self.currentOrder.y = self.y - 40;
+ // Check if reached customer
+ var dx = self.currentOrder.customer.x - self.x;
+ var dy = self.currentOrder.customer.y - self.y;
+ if (Math.sqrt(dx * dx + dy * dy) < 50) {
+ // Complete delivery
+ self.completeDelivery();
}
}
- // Check for collisions before moving
- var canMove = true;
- var testX = self.targetX;
- var testY = self.targetY;
- // Check collision with other cars
- for (var i = 0; i < cars.length; i++) {
- if (cars[i] === self) continue;
- var dx = Math.abs(testX - cars[i].x);
- var dy = Math.abs(testY - cars[i].y);
- if (dx < 50 && dy < 50) {
- canMove = false;
- break;
- }
+ };
+ self.completeDelivery = function () {
+ if (!self.currentOrder) return;
+ // Clean up order
+ self.currentOrder.restaurant.hasOrder = false;
+ self.currentOrder.customer.waitingForOrder = false;
+ // Remove delivery target indicator
+ if (self.currentOrder.customer.deliveryTarget) {
+ tween.stop(self.currentOrder.customer.deliveryTarget);
+ self.currentOrder.customer.deliveryTarget.destroy();
+ self.currentOrder.customer.deliveryTarget = null;
}
- // Check collision with couriers
- var courierDx = Math.abs(testX - courier.x);
- var courierDy = Math.abs(testY - courier.y);
- if (courierDx < 50 && courierDy < 50) {
- canMove = false;
- }
- // Check collision with AI couriers
- for (var i = 0; i < aiCouriers.length; i++) {
- var aiDx = Math.abs(testX - aiCouriers[i].x);
- var aiDy = Math.abs(testY - aiCouriers[i].y);
- if (aiDx < 50 && aiDy < 50) {
- canMove = false;
+ self.currentOrder.destroy();
+ for (var i = aiOrders.length - 1; i >= 0; i--) {
+ if (aiOrders[i] === self.currentOrder) {
+ aiOrders.splice(i, 1);
break;
}
}
- if (canMove) {
- self.x = testX;
- self.y = testY;
- self.stuckTimer = 0;
- // World wrapping - if car goes off left edge, appear on right edge
- if (self.x < worldLeftBound) {
- self.x = worldRightBound;
- } else if (self.x > worldRightBound) {
- self.x = worldLeftBound;
- }
- } else {
- // If stuck for too long, change direction
- self.stuckTimer += 16.67;
- if (self.stuckTimer >= self.maxStuckTime) {
- self.movingPositive = !self.movingPositive;
- self.stuckTimer = 0;
- }
- }
+ self.currentOrder = null;
+ self.hasOrder = false;
+ self.state = 'searching';
};
return self;
});
var Courier = Container.expand(function () {
@@ -348,163 +125,69 @@
self.speed = 8;
self.hasOrder = false;
self.targetRestaurant = null;
self.targetCustomer = null;
- self.currentPath = [];
- self.pathIndex = 0;
- self.lastTargetX = 0;
- self.lastTargetY = 0;
self.moveToward = function (targetX, targetY) {
- // Check if target changed significantly - recalculate path
- var targetChanged = Math.abs(targetX - self.lastTargetX) > 50 || Math.abs(targetY - self.lastTargetY) > 50;
- if (targetChanged || self.currentPath.length === 0 || self.pathIndex >= self.currentPath.length) {
- self.currentPath = findPath(self.x, self.y, targetX, targetY);
- self.pathIndex = 0;
- self.lastTargetX = targetX;
- self.lastTargetY = targetY;
- }
- // Follow path if available
- if (self.currentPath.length > 0 && self.pathIndex < self.currentPath.length) {
- var pathTarget = self.currentPath[self.pathIndex];
- var dx = pathTarget.x - self.x;
- var dy = pathTarget.y - self.y;
- var distance = Math.sqrt(dx * dx + dy * dy);
- // Check if reached current path node
- if (distance < 60) {
- self.pathIndex++;
- if (self.pathIndex < self.currentPath.length) {
- pathTarget = self.currentPath[self.pathIndex];
- dx = pathTarget.x - self.x;
- dy = pathTarget.y - self.y;
- distance = Math.sqrt(dx * dx + dy * dy);
+ var dx = targetX - self.x;
+ var dy = targetY - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance > 10) {
+ var newX = self.x + dx / distance * self.speed;
+ var newY = self.y + dy / distance * self.speed;
+ // Check collision with buildings
+ var canMove = true;
+ for (var i = 0; i < buildings.length; i++) {
+ var tempCourier = {
+ x: newX,
+ y: newY,
+ width: 60,
+ height: 60
+ };
+ var building = buildings[i];
+ if (tempCourier.x < building.x + building.width / 2 && tempCourier.x + tempCourier.width / 2 > building.x - building.width / 2 && tempCourier.y < building.y + building.height / 2 && tempCourier.y + tempCourier.height / 2 > building.y - building.height / 2) {
+ canMove = false;
+ break;
}
}
- if (distance > 10 && self.pathIndex < self.currentPath.length) {
- var newX = self.x + dx / distance * self.speed;
- var newY = self.y + dy / distance * self.speed;
- // Check collisions before moving
- var canMove = true;
- // Check collision with cars
- for (var i = 0; i < cars.length; i++) {
- var carDx = Math.abs(newX - cars[i].x);
- var carDy = Math.abs(newY - cars[i].y);
- if (carDx < 50 && carDy < 50) {
- canMove = false;
- break;
- }
- }
- // Check collision with AI couriers
- for (var i = 0; i < aiCouriers.length; i++) {
- var aiDx = Math.abs(newX - aiCouriers[i].x);
- var aiDy = Math.abs(newY - aiCouriers[i].y);
- if (aiDx < 55 && aiDy < 55) {
- canMove = false;
- // If blocked by AI courier, recalculate path
- self.currentPath = [];
- self.pathIndex = 0;
- break;
- }
- }
- if (canMove) {
- self.x = newX;
- self.y = newY;
- // World wrapping - if courier goes off left edge, appear on right edge
- if (self.x < worldLeftBound) {
- self.x = worldRightBound;
- } else if (self.x > worldRightBound) {
- self.x = worldLeftBound;
- }
- }
+ if (canMove) {
+ self.x = newX;
+ self.y = newY;
}
- } else {
- // Direct movement as fallback
- var dx = targetX - self.x;
- var dy = targetY - self.y;
- var distance = Math.sqrt(dx * dx + dy * dy);
- if (distance > 10) {
- var newX = self.x + dx / distance * self.speed;
- var newY = self.y + dy / distance * self.speed;
- // Check collisions before moving
- var canMove = true;
- // Check collision with cars
- for (var i = 0; i < cars.length; i++) {
- var carDx = Math.abs(newX - cars[i].x);
- var carDy = Math.abs(newY - cars[i].y);
- if (carDx < 50 && carDy < 50) {
- canMove = false;
- break;
- }
- }
- // Check collision with AI couriers
- for (var i = 0; i < aiCouriers.length; i++) {
- var aiDx = Math.abs(newX - aiCouriers[i].x);
- var aiDy = Math.abs(newY - aiCouriers[i].y);
- if (aiDx < 50 && aiDy < 50) {
- canMove = false;
- break;
- }
- }
- if (canMove) {
- self.x = newX;
- self.y = newY;
- // World wrapping - if courier goes off left edge, appear on right edge
- if (self.x < worldLeftBound) {
- self.x = worldRightBound;
- } else if (self.x > worldRightBound) {
- self.x = worldLeftBound;
- }
- }
- }
}
};
return self;
});
-var Customer = Container.expand(function (color) {
+var Customer = Container.expand(function () {
var self = Container.call(this);
var customerGraphics = self.attachAsset('customer', {
anchorX: 0.5,
anchorY: 0.5
});
- // Set customer color
- self.customerColor = color || 0x2196f3;
- customerGraphics.tint = self.customerColor;
self.waitingForOrder = false;
self.orderTime = 0;
self.maxWaitTime = 10000; // 10 seconds
self.deliveryTarget = null;
- self.visible = false; // Start invisible
self.update = function () {
if (self.waitingForOrder) {
self.orderTime += 16.67; // Approximate ms per frame at 60fps
}
};
return self;
});
-var Order = Container.expand(function (color) {
+var Order = Container.expand(function () {
var self = Container.call(this);
var orderGraphics = self.attachAsset('order', {
anchorX: 0.5,
anchorY: 0.5
});
- // Set order color
- self.orderColor = color || 0xffff00;
- orderGraphics.tint = self.orderColor;
self.restaurant = null;
self.customer = null;
self.timeLimit = 25000; // 25 seconds
self.timeRemaining = self.timeLimit;
- self.timerStarted = false; // Timer doesn't start until courier picks up
- self.lifeTime = 0; // Track how long order has existed
- self.maxLifeTime = 15000; // Order expires after 15 seconds if not picked up
- self.isBeingChased = false; // Track if an AI courier is chasing this order
self.update = function () {
- if (self.timerStarted && self.timeRemaining > 0) {
+ if (self.timeRemaining > 0) {
self.timeRemaining -= 16.67;
}
- // Track order lifetime for auto-expiry
- if (!self.timerStarted) {
- self.lifeTime += 16.67;
- }
};
return self;
});
var PowerUp = Container.expand(function (type) {
@@ -548,26 +231,20 @@
****/
// Game variables
var courier;
var aiCouriers = [];
-var cars = [];
var restaurants = [];
var customers = [];
var orders = [];
+var aiOrders = [];
var powerUps = [];
var buildings = [];
var health = 100;
var money = 0;
var currentOrder = null;
-var currentOrders = []; // Track multiple active orders
-var orderColors = [0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xff00ff]; // Red, Green, Blue, Yellow, Magenta
var gameState = 'pickup'; // 'pickup', 'delivery'
var timeFreezeActive = false;
var timeFreezeRemaining = 0;
-// World wrapping variables
-var worldWidth = 2048; // Game screen width
-var worldLeftBound = 100;
-var worldRightBound = 1950;
// UI Elements
var healthBar = new Text2('Health: 100', {
size: 60,
fill: 0xFF0000
@@ -590,611 +267,190 @@
});
orderTimer.anchor.set(0.5, 0);
LK.gui.top.addChild(orderTimer);
orderTimer.y = 100;
-// Game-wide route system
-var routes = [];
-var routeNodes = [];
// Create neighborhood layout
function createNeighborhood() {
- // Center coordinates
- var centerX = 1024;
- var centerY = 1366;
- // Create orderly grid layout with proper roads
- var blockSize = 200; // Distance between blocks
- var roadWidth = 120; // Width of roads (increased from 80)
- var buildingSize = 80; // Size of buildings (reduced from 120)
- // Create 4-block central park (2x2 grid of park blocks)
- var parkSize = blockSize;
- var parkPositions = [{
- x: centerX - parkSize / 2,
- y: centerY - parkSize / 2
- },
- // Top-left
- {
- x: centerX + parkSize / 2,
- y: centerY - parkSize / 2
- },
- // Top-right
- {
- x: centerX - parkSize / 2,
- y: centerY + parkSize / 2
- },
- // Bottom-left
- {
- x: centerX + parkSize / 2,
- y: centerY + parkSize / 2
- } // Bottom-right
- ];
- // Create the 4 park blocks
- for (var i = 0; i < parkPositions.length; i++) {
- var park = game.addChild(LK.getAsset('building', {
- anchorX: 0.5,
- anchorY: 0.5,
- x: parkPositions[i].x,
- y: parkPositions[i].y
- }));
- park.tint = 0x4CAF50; // Green color for park
- park.scaleX = 1.6;
- park.scaleY = 1.6;
- }
- // Define grid layout for city blocks around the park
- var gridRows = 8;
- var gridCols = 6;
- var startX = centerX - gridCols * blockSize / 2;
- var startY = centerY - gridRows * blockSize / 2;
- // Create horizontal roads
- for (var row = 0; row <= gridRows; row++) {
- var roadY = startY + row * blockSize;
- if (roadY > 150 && roadY < 2582) {
+ // Create roads (grid pattern)
+ for (var x = 0; x < 2048; x += 300) {
+ for (var y = 0; y < 2732; y += 300) {
var road = game.addChild(LK.getAsset('road', {
anchorX: 0.5,
anchorY: 0.5,
- x: centerX,
- y: roadY
+ x: x + 150,
+ y: y + 150
}));
- road.scaleX = 15; // Make road span full width
- road.scaleY = roadWidth / 80;
}
}
- // Create vertical roads
- for (var col = 0; col <= gridCols; col++) {
- var roadX = startX + col * blockSize;
- if (roadX > 150 && roadX < 1898) {
- var road = game.addChild(LK.getAsset('road', {
- anchorX: 0.5,
- anchorY: 0.5,
- x: roadX,
- y: centerY
- }));
- road.scaleX = roadWidth / 100;
- road.scaleY = 20; // Make road span full height
- }
- }
- // Store all building and restaurant positions
- var allBuildingPositions = [];
- var allRestaurantPositions = [];
- // Generate building positions in the center of each block
- for (var row = 0; row < gridRows; row++) {
- for (var col = 0; col < gridCols; col++) {
- var blockCenterX = startX + col * blockSize + blockSize / 2;
- var blockCenterY = startY + row * blockSize + blockSize / 2;
- // Skip blocks that overlap with the central park
- var distanceToCenter = Math.sqrt(Math.pow(blockCenterX - centerX, 2) + Math.pow(blockCenterY - centerY, 2));
- if (distanceToCenter < parkSize * 1.2) continue;
- // Only add positions within game bounds
- if (blockCenterX > 200 && blockCenterX < 1848 && blockCenterY > 250 && blockCenterY < 2482) {
- // Randomly assign as building or restaurant
- if (Math.random() < 0.3) {
- // 30% chance for restaurant
- allRestaurantPositions.push({
- x: blockCenterX,
- y: blockCenterY
- });
- } else {
- // 70% chance for building
- allBuildingPositions.push({
- x: blockCenterX,
- y: blockCenterY
- });
- }
+ // Create buildings in grid formation avoiding roads and first row
+ var buildingRows = 6;
+ var buildingCols = 5;
+ var gridSpacingX = 300; // Match road spacing
+ var gridSpacingY = 300; // Match road spacing
+ var startX = 225; // Center buildings between roads
+ var startY = 375; // Start from second row to keep first row empty
+ for (var row = 1; row < buildingRows; row++) {
+ // Start from row 1, not 0
+ for (var col = 0; col < buildingCols; col++) {
+ var buildingX = startX + col * gridSpacingX;
+ var buildingY = startY + row * gridSpacingY;
+ // Ensure buildings stay within game bounds
+ if (buildingX < 2048 - 60 && buildingY < 2732 - 50) {
+ var building = game.addChild(LK.getAsset('building', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: buildingX,
+ y: buildingY
+ }));
+ buildings.push(building);
}
}
}
- // Create buildings at calculated positions
- for (var i = 0; i < allBuildingPositions.length; i++) {
- var building = game.addChild(LK.getAsset('building', {
- anchorX: 0.5,
- anchorY: 0.5,
- x: allBuildingPositions[i].x,
- y: allBuildingPositions[i].y
- }));
- // Add entrance asphalt in front of building (south side)
- var entranceAsphalt = game.addChild(LK.getAsset('road', {
- anchorX: 0.5,
- anchorY: 0.5,
- x: allBuildingPositions[i].x,
- y: allBuildingPositions[i].y + buildingSize / 2 + 30
- }));
- entranceAsphalt.scaleX = 1.2;
- entranceAsphalt.scaleY = 0.0125;
- entranceAsphalt.tint = 0x606060; // Darker asphalt for entrance
- building.entranceX = allBuildingPositions[i].x;
- building.entranceY = allBuildingPositions[i].y + buildingSize / 2 + 30;
- building.entrance = entranceAsphalt; // Store reference to entrance
- entranceAsphalt.connectedBuilding = building; // Two-way reference
- buildings.push(building);
- }
- // Create restaurants at calculated positions
- for (var i = 0; i < allRestaurantPositions.length; i++) {
+ // Create restaurants in proper grid positions avoiding first row
+ for (var i = 0; i < 6; i++) {
var restaurant = game.addChild(new Restaurant());
- restaurant.x = allRestaurantPositions[i].x;
- restaurant.y = allRestaurantPositions[i].y;
- // Add entrance asphalt in front of restaurant (south side)
- var entranceAsphalt = game.addChild(LK.getAsset('road', {
- anchorX: 0.5,
- anchorY: 0.5,
- x: allRestaurantPositions[i].x,
- y: allRestaurantPositions[i].y + buildingSize / 2 + 30
- }));
- entranceAsphalt.scaleX = 1.2;
- entranceAsphalt.scaleY = 0.0125;
- entranceAsphalt.tint = 0x606060; // Darker asphalt for entrance
- restaurant.entranceX = allRestaurantPositions[i].x;
- restaurant.entranceY = allRestaurantPositions[i].y + buildingSize / 2 + 30;
- restaurant.entrance = entranceAsphalt; // Store reference to entrance
- entranceAsphalt.connectedRestaurant = restaurant; // Two-way reference
+ restaurant.x = 75 + i % 3 * 300;
+ restaurant.y = 375 + Math.floor(i / 3) * 600;
restaurants.push(restaurant);
}
- // Create customers - place them exactly in the center of buildings
- var customerCount = Math.min(buildings.length, 20);
+ // Create customers - place them inside buildings
+ var customerCount = Math.min(8, buildings.length);
for (var i = 0; i < customerCount; i++) {
var customer = game.addChild(new Customer());
- // Place customer exactly at building center (red dot in middle of building)
+ // Place customer at same position as building
customer.x = buildings[i].x;
customer.y = buildings[i].y;
customers.push(customer);
}
- // Create route network after building placement
- createRouteNetwork();
}
-// Create a network of route nodes for pathfinding
-function createRouteNetwork() {
- routeNodes = [];
- routes = [];
- var centerX = 1024;
- var centerY = 1366;
- var blockSize = 200;
- var gridRows = 8;
- var gridCols = 6;
- var startX = centerX - gridCols * blockSize / 2;
- var startY = centerY - gridRows * blockSize / 2;
- // Create route nodes at road intersections
- for (var row = 0; row <= gridRows; row++) {
- for (var col = 0; col <= gridCols; col++) {
- var nodeX = startX + col * blockSize;
- var nodeY = startY + row * blockSize;
- // Only add nodes within game bounds
- if (nodeX > 150 && nodeX < 1898 && nodeY > 150 && nodeY < 2582) {
- routeNodes.push({
- x: nodeX,
- y: nodeY,
- connections: [],
- isIntersection: true
- });
- }
- }
- }
- // Add route nodes at the center of each road segment for better pathfinding
- // Horizontal road segments
- for (var row = 0; row <= gridRows; row++) {
- for (var col = 0; col < gridCols; col++) {
- var nodeX = startX + col * blockSize + blockSize / 2;
- var nodeY = startY + row * blockSize;
- if (nodeX > 150 && nodeX < 1898 && nodeY > 150 && nodeY < 2582) {
- routeNodes.push({
- x: nodeX,
- y: nodeY,
- connections: []
- });
- }
- }
- }
- // Vertical road segments
- for (var row = 0; row < gridRows; row++) {
- for (var col = 0; col <= gridCols; col++) {
- var nodeX = startX + col * blockSize;
- var nodeY = startY + row * blockSize + blockSize / 2;
- if (nodeX > 150 && nodeX < 1898 && nodeY > 150 && nodeY < 2582) {
- routeNodes.push({
- x: nodeX,
- y: nodeY,
- connections: []
- });
- }
- }
- }
- // Add building access nodes near each building and restaurant
- for (var i = 0; i < buildings.length; i++) {
- var building = buildings[i];
- // Add access nodes on the roads around the building
- var accessNodes = [{
- x: building.x,
- y: building.y - blockSize / 2
- },
- // North road
- {
- x: building.x,
- y: building.y + blockSize / 2
- },
- // South road
- {
- x: building.x - blockSize / 2,
- y: building.y
- },
- // West road
- {
- x: building.x + blockSize / 2,
- y: building.y
- } // East road
- ];
- for (var j = 0; j < accessNodes.length; j++) {
- var accessNode = accessNodes[j];
- if (accessNode.x > 150 && accessNode.x < 1898 && accessNode.y > 150 && accessNode.y < 2582) {
- routeNodes.push({
- x: accessNode.x,
- y: accessNode.y,
- connections: [],
- buildingAccess: i
- });
- }
- }
- }
- for (var i = 0; i < restaurants.length; i++) {
- var restaurant = restaurants[i];
- // Add access nodes on the roads around the restaurant
- var accessNodes = [{
- x: restaurant.x,
- y: restaurant.y - blockSize / 2
- },
- // North road
- {
- x: restaurant.x,
- y: restaurant.y + blockSize / 2
- },
- // South road
- {
- x: restaurant.x - blockSize / 2,
- y: restaurant.y
- },
- // West road
- {
- x: restaurant.x + blockSize / 2,
- y: restaurant.y
- } // East road
- ];
- for (var j = 0; j < accessNodes.length; j++) {
- var accessNode = accessNodes[j];
- if (accessNode.x > 150 && accessNode.x < 1898 && accessNode.y > 150 && accessNode.y < 2582) {
- routeNodes.push({
- x: accessNode.x,
- y: accessNode.y,
- connections: [],
- restaurantAccess: i
- });
- }
- }
- }
- // Connect route nodes - connect nodes that are on the same road
- for (var i = 0; i < routeNodes.length; i++) {
- for (var j = i + 1; j < routeNodes.length; j++) {
- var distance = getDistance(routeNodes[i], routeNodes[j]);
- var node1 = routeNodes[i];
- var node2 = routeNodes[j];
- // Connect nodes if they're on the same horizontal or vertical road
- var sameHorizontalRoad = Math.abs(node1.y - node2.y) < 20 && distance < blockSize + 50;
- var sameVerticalRoad = Math.abs(node1.x - node2.x) < 20 && distance < blockSize + 50;
- if ((sameHorizontalRoad || sameVerticalRoad) && distance > 10) {
- routeNodes[i].connections.push(j);
- routeNodes[j].connections.push(i);
- }
- }
- }
-}
-// Find closest route node to a position
-function findClosestRouteNode(x, y) {
- var closestIndex = -1;
- var closestDistance = Infinity;
- for (var i = 0; i < routeNodes.length; i++) {
- var distance = getDistance({
- x: x,
- y: y
- }, routeNodes[i]);
- if (distance < closestDistance) {
- closestDistance = distance;
- closestIndex = i;
- }
- }
- return closestIndex;
-}
-// Check if path between two nodes is clear of buildings
-function isPathClear(node1, node2) {
- var steps = 10;
- var stepX = (node2.x - node1.x) / steps;
- var stepY = (node2.y - node1.y) / steps;
- for (var step = 0; step <= steps; step++) {
- var checkX = node1.x + stepX * step;
- var checkY = node1.y + stepY * step;
- // Check if this point intersects with any building
- for (var i = 0; i < buildings.length; i++) {
- var building = buildings[i];
- var dx = Math.abs(checkX - building.x);
- var dy = Math.abs(checkY - building.y);
- if (dx < building.width / 2 + 30 && dy < building.height / 2 + 30) {
- return false;
- }
- }
- }
- return true;
-}
-// Get distance between two points
-function getDistance(point1, point2) {
- var dx = point1.x - point2.x;
- var dy = point1.y - point2.y;
- return Math.sqrt(dx * dx + dy * dy);
-}
-// Global path reservation system to prevent AI courier path conflicts
-var reservedPaths = [];
-// Find path between two positions using A* pathfinding with courier separation
-function findPath(startX, startY, endX, endY, courierIndex) {
- var startNode = findClosestRouteNode(startX, startY);
- var endNode = findClosestRouteNode(endX, endY);
- if (startNode === -1 || endNode === -1) return [];
- if (startNode === endNode) return [routeNodes[endNode]];
- // Simple A* implementation with path reservation
- var openSet = [{
- index: startNode,
- g: 0,
- h: getDistance(routeNodes[startNode], routeNodes[endNode]),
- parent: null
- }];
- var closedSet = [];
- var visited = [];
- while (openSet.length > 0) {
- // Find node with lowest f score
- var current = openSet[0];
- var currentIndex = 0;
- for (var i = 1; i < openSet.length; i++) {
- if (openSet[i].g + openSet[i].h < current.g + current.h) {
- current = openSet[i];
- currentIndex = i;
- }
- }
- // Move current from open to closed
- openSet.splice(currentIndex, 1);
- closedSet.push(current);
- visited.push(current.index);
- // Check if we reached the goal
- if (current.index === endNode) {
- var path = [];
- var pathNode = current;
- while (pathNode) {
- path.unshift(routeNodes[pathNode.index]);
- pathNode = pathNode.parent;
- }
- // Reserve this path for the courier to prevent conflicts
- if (courierIndex !== undefined) {
- // Clear previous reservation for this courier
- for (var r = reservedPaths.length - 1; r >= 0; r--) {
- if (reservedPaths[r].courierIndex === courierIndex) {
- reservedPaths.splice(r, 1);
+function createNewOrder() {
+ if (currentOrder) return;
+ var availableRestaurants = restaurants.filter(function (r) {
+ return !r.hasOrder;
+ });
+ var availableCustomers = customers.filter(function (c) {
+ return !c.waitingForOrder;
+ });
+ if (availableRestaurants.length === 0 || availableCustomers.length === 0) return;
+ var restaurant = availableRestaurants[Math.floor(Math.random() * availableRestaurants.length)];
+ var customer = availableCustomers[Math.floor(Math.random() * availableCustomers.length)];
+ var order = game.addChild(new Order());
+ order.x = restaurant.x;
+ order.y = restaurant.y - 60;
+ order.restaurant = restaurant;
+ order.customer = customer;
+ restaurant.hasOrder = true;
+ restaurant.orderReady = true;
+ customer.waitingForOrder = true;
+ customer.orderTime = 0;
+ // Create delivery target indicator
+ var deliveryTarget = game.addChild(LK.getAsset('deliveryTarget', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: customer.x,
+ y: customer.y - 50
+ }));
+ customer.deliveryTarget = deliveryTarget;
+ // Start flashing animation
+ tween(deliveryTarget, {
+ alpha: 0.3
+ }, {
+ duration: 500,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ tween(deliveryTarget, {
+ alpha: 1
+ }, {
+ duration: 500,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ if (deliveryTarget.parent) {
+ tween(deliveryTarget, {
+ alpha: 0.3
+ }, {
+ duration: 500,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ tween(deliveryTarget, {
+ alpha: 1
+ }, {
+ duration: 500,
+ easing: tween.easeInOut
+ });
+ }
+ });
}
}
- // Add new path reservation
- reservedPaths.push({
- courierIndex: courierIndex,
- path: path,
- timestamp: Date.now()
- });
- }
- return path;
+ });
}
- // Check all neighbors
- var connections = routeNodes[current.index].connections;
- for (var i = 0; i < connections.length; i++) {
- var neighborIndex = connections[i];
- // Skip if already visited
- if (visited.indexOf(neighborIndex) !== -1) continue;
- // Check if this node is reserved by another courier
- var isReserved = false;
- if (courierIndex !== undefined) {
- for (var r = 0; r < reservedPaths.length; r++) {
- if (reservedPaths[r].courierIndex !== courierIndex) {
- for (var p = 0; p < reservedPaths[r].path.length; p++) {
- var reservedNode = reservedPaths[r].path[p];
- if (Math.abs(reservedNode.x - routeNodes[neighborIndex].x) < 50 && Math.abs(reservedNode.y - routeNodes[neighborIndex].y) < 50) {
- isReserved = true;
- break;
+ });
+ currentOrder = order;
+ orders.push(order);
+ gameState = 'pickup';
+}
+function createAIOrder() {
+ var availableRestaurants = restaurants.filter(function (r) {
+ return !r.hasOrder;
+ });
+ var availableCustomers = customers.filter(function (c) {
+ return !c.waitingForOrder;
+ });
+ if (availableRestaurants.length === 0 || availableCustomers.length === 0) return;
+ var restaurant = availableRestaurants[Math.floor(Math.random() * availableRestaurants.length)];
+ var customer = availableCustomers[Math.floor(Math.random() * availableCustomers.length)];
+ var order = game.addChild(new Order());
+ order.x = restaurant.x;
+ order.y = restaurant.y - 60;
+ order.restaurant = restaurant;
+ order.customer = customer;
+ order.claimed = false; // For AI to claim
+ restaurant.hasOrder = true;
+ restaurant.orderReady = true;
+ customer.waitingForOrder = true;
+ customer.orderTime = 0;
+ // Create delivery target indicator
+ var deliveryTarget = game.addChild(LK.getAsset('deliveryTarget', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: customer.x,
+ y: customer.y - 50
+ }));
+ customer.deliveryTarget = deliveryTarget;
+ // Start flashing animation
+ tween(deliveryTarget, {
+ alpha: 0.3
+ }, {
+ duration: 500,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ tween(deliveryTarget, {
+ alpha: 1
+ }, {
+ duration: 500,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ if (deliveryTarget.parent) {
+ tween(deliveryTarget, {
+ alpha: 0.3
+ }, {
+ duration: 500,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ tween(deliveryTarget, {
+ alpha: 1
+ }, {
+ duration: 500,
+ easing: tween.easeInOut
+ });
}
- }
- if (isReserved) break;
+ });
}
}
- }
- var g = current.g + getDistance(routeNodes[current.index], routeNodes[neighborIndex]);
- var h = getDistance(routeNodes[neighborIndex], routeNodes[endNode]);
- // Add penalty for reserved nodes
- if (isReserved) {
- g += 200; // High penalty for reserved paths
- }
- // Check if this path to neighbor is better
- var existingOpen = null;
- for (var j = 0; j < openSet.length; j++) {
- if (openSet[j].index === neighborIndex) {
- existingOpen = openSet[j];
- break;
- }
- }
- if (!existingOpen || g < existingOpen.g) {
- var neighbor = {
- index: neighborIndex,
- g: g,
- h: h,
- parent: current
- };
- if (existingOpen) {
- openSet[j] = neighbor;
- } else {
- openSet.push(neighbor);
- }
- }
+ });
}
- }
- return []; // No path found
+ });
+ aiOrders.push(order);
}
-function createNewOrder() {
- // Create multiple orders if we have less than 5
- var ordersToCreate = Math.min(5 - currentOrders.length, 5);
- for (var orderNum = 0; orderNum < ordersToCreate; orderNum++) {
- var availableRestaurants = restaurants.filter(function (r) {
- return !r.hasOrder;
- });
- if (availableRestaurants.length === 0) break;
- // Select random restaurant and building for new customer
- var restaurant = availableRestaurants[Math.floor(Math.random() * availableRestaurants.length)];
- var availableBuildings = buildings.filter(function (b) {
- // Don't use buildings that already have visible customers
- for (var i = 0; i < customers.length; i++) {
- if (customers[i].visible && customers[i].x === b.x && customers[i].y === b.y) {
- return false;
- }
- }
- return true;
- });
- if (availableBuildings.length === 0) break;
- var selectedBuilding = availableBuildings[Math.floor(Math.random() * availableBuildings.length)];
- // Select color for this order
- var orderColor = orderColors[orderNum % orderColors.length];
- // Find or create customer at selected building with matching color
- var customer = null;
- for (var i = 0; i < customers.length; i++) {
- if (!customers[i].waitingForOrder && customers[i].x === selectedBuilding.x && customers[i].y === selectedBuilding.y) {
- customer = customers[i];
- break;
- }
- }
- // If no customer at this building, create one with matching color
- if (!customer) {
- customer = game.addChild(new Customer(orderColor));
- customer.x = selectedBuilding.x;
- customer.y = selectedBuilding.y;
- customers.push(customer);
- } else {
- // Update existing customer color to match order
- customer.customerColor = orderColor;
- customer.children[0].tint = orderColor;
- }
- var order = game.addChild(new Order(orderColor));
- order.x = restaurant.x;
- order.y = restaurant.y - 60;
- order.restaurant = restaurant;
- order.customer = customer;
- restaurant.hasOrder = true;
- restaurant.orderReady = true;
- customer.waitingForOrder = true;
- customer.visible = true; // Make customer visible when order arrives
- customer.orderTime = 0;
- // Create delivery target indicator with matching color
- var deliveryTarget = game.addChild(LK.getAsset('deliveryTarget', {
- anchorX: 0.5,
- anchorY: 0.5,
- x: customer.x,
- y: customer.y - 50
- }));
- deliveryTarget.tint = orderColor; // Match target color to order/customer
- customer.deliveryTarget = deliveryTarget;
- // Start flashing animation
- tween(deliveryTarget, {
- alpha: 0.3
- }, {
- duration: 500,
- easing: tween.easeInOut,
- onFinish: function onFinish() {
- tween(deliveryTarget, {
- alpha: 1
- }, {
- duration: 500,
- easing: tween.easeInOut,
- onFinish: function onFinish() {
- if (deliveryTarget.parent) {
- tween(deliveryTarget, {
- alpha: 0.3
- }, {
- duration: 500,
- easing: tween.easeInOut,
- onFinish: function onFinish() {
- tween(deliveryTarget, {
- alpha: 1
- }, {
- duration: 500,
- easing: tween.easeInOut
- });
- }
- });
- }
- }
- });
- }
- });
- currentOrders.push(order);
- orders.push(order);
- // Set first order as current order for player
- if (!currentOrder) {
- currentOrder = order;
- gameState = 'pickup';
- }
- }
-}
-function createCars() {
- var targetCarCount = 10; // Start with 10 cars
- if (money >= 200) {
- targetCarCount = 20; // Max 20 cars at $200
- } else if (money > 0) {
- // Gradually increase from 10 to 20 based on money
- targetCarCount = 10 + Math.floor(money / 200 * 10);
- }
- // Add cars if we need more
- while (cars.length < targetCarCount) {
- var car = game.addChild(new Car());
- // Place cars on roads including near building entrances
- var spawnChoice = Math.random();
- if (spawnChoice < 0.4) {
- // Place on horizontal road
- car.x = Math.random() * 1800 + 124;
- car.y = 1366 + (Math.floor(Math.random() * 8) - 4) * 200; // Various horizontal roads
- } else if (spawnChoice < 0.8) {
- // Place on vertical road
- car.x = 1024 + (Math.floor(Math.random() * 6) - 3) * 200; // Various vertical roads
- car.y = Math.random() * 2400 + 166;
- } else {
- // Place near building entrances to simulate cars entering neighborhood
- if (buildings.length > 0) {
- var randomBuilding = buildings[Math.floor(Math.random() * buildings.length)];
- car.x = randomBuilding.entranceX + (Math.random() - 0.5) * 100;
- car.y = randomBuilding.entranceY + (Math.random() - 0.5) * 50;
- } else {
- car.x = Math.random() * 1800 + 124;
- car.y = Math.random() * 2400 + 166;
- }
- }
- cars.push(car);
- }
- // Remove excess cars if money decreased (shouldn't happen but safety check)
- while (cars.length > targetCarCount) {
- var removedCar = cars.pop();
- removedCar.destroy();
- }
-}
function spawnPowerUp() {
if (powerUps.length >= 3) return;
var type = Math.random() < 0.6 ? 'health' : 'time';
var powerUp = game.addChild(new PowerUp(type));
@@ -1212,51 +468,26 @@
orderTimer.setText('');
}
}
function checkCollisions() {
- // Check courier-restaurant entrance collision for pickup
- if (gameState === 'pickup' && currentOrders.length > 0) {
- // Check all available orders
- for (var orderIdx = 0; orderIdx < currentOrders.length; orderIdx++) {
- var order = currentOrders[orderIdx];
- if (order.timerStarted) continue; // Skip orders already picked up
- var restaurant = order.restaurant;
- var pickupDistance = Math.sqrt(Math.pow(restaurant.entranceX - courier.x, 2) + Math.pow(restaurant.entranceY - courier.y, 2));
- if (pickupDistance < 70) {
- // Check entrance area
- // Pick up order
- LK.getSound('pickup').play();
- courier.hasOrder = true;
- currentOrder = order; // Set as current order for player
- gameState = 'delivery';
- currentOrder.x = courier.x;
- currentOrder.y = courier.y - 40;
- // Start the package timer when courier receives the package
- currentOrder.timerStarted = true;
- break; // Only pick up one order
- }
+ // Check courier-restaurant collision for pickup
+ if (gameState === 'pickup' && currentOrder) {
+ if (courier.intersects(currentOrder.restaurant)) {
+ // Pick up order
+ LK.getSound('pickup').play();
+ courier.hasOrder = true;
+ gameState = 'delivery';
+ currentOrder.x = courier.x;
+ currentOrder.y = courier.y - 40;
}
}
- // Check courier-customer building entrance collision for delivery
+ // Check courier-customer collision for delivery
if (gameState === 'delivery' && currentOrder && courier.hasOrder) {
- var customer = currentOrder.customer;
- // Find the building that contains this customer
- var customerBuilding = null;
- for (var i = 0; i < buildings.length; i++) {
- if (buildings[i].x === customer.x && buildings[i].y === customer.y) {
- customerBuilding = buildings[i];
- break;
- }
+ if (courier.intersects(currentOrder.customer)) {
+ // Deliver order
+ LK.getSound('delivery').play();
+ completeDelivery();
}
- if (customerBuilding) {
- var deliveryDistance = Math.sqrt(Math.pow(customerBuilding.entranceX - courier.x, 2) + Math.pow(customerBuilding.entranceY - courier.y, 2));
- if (deliveryDistance < 70) {
- // Check entrance area
- // Deliver order
- LK.getSound('delivery').play();
- completeDelivery();
- }
- }
}
// Check courier-powerup collisions
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
@@ -1295,9 +526,8 @@
}
// Clean up order
currentOrder.restaurant.hasOrder = false;
currentOrder.customer.waitingForOrder = false;
- currentOrder.customer.visible = false; // Hide customer after delivery
// Remove delivery target indicator
if (currentOrder.customer.deliveryTarget) {
tween.stop(currentOrder.customer.deliveryTarget);
currentOrder.customer.deliveryTarget.destroy();
@@ -1312,51 +542,19 @@
}
currentOrder = null;
courier.hasOrder = false;
gameState = 'pickup';
- // Create new order immediately to maintain constant flow
- createNewOrder();
+ // Create new order after short delay
+ LK.setTimeout(function () {
+ createNewOrder();
+ }, 1000);
}
// Initialize game elements
createNeighborhood();
// Create courier
courier = game.addChild(new Courier());
courier.x = 1024;
courier.y = 1366;
-// Initialize cars
-createCars();
-// Create AI couriers
-for (var i = 0; i < 3; i++) {
- var aiCourier = game.addChild(new AICourier());
- aiCourier.x = Math.random() * 1800 + 124;
- aiCourier.y = Math.random() * 2400 + 166;
- // Create route waypoints based on restaurant and road positions
- aiCourier.routeWaypoints = [];
- // Add restaurant positions as waypoints
- for (var j = 0; j < restaurants.length; j++) {
- aiCourier.routeWaypoints.push({
- x: restaurants[j].x,
- y: restaurants[j].y
- });
- }
- // Add some road intersection points as additional waypoints
- var centerX = 1024;
- var centerY = 1366;
- var roadRadii = [450, 750]; // Road layer radii
- for (var r = 0; r < roadRadii.length; r++) {
- for (var angle = 0; angle < Math.PI * 2; angle += Math.PI / 4) {
- var roadX = centerX + Math.cos(angle) * roadRadii[r];
- var roadY = centerY + Math.sin(angle) * roadRadii[r];
- if (roadX > 100 && roadX < 1948 && roadY > 100 && roadY < 2632) {
- aiCourier.routeWaypoints.push({
- x: roadX,
- y: roadY
- });
- }
- }
- }
- aiCouriers.push(aiCourier);
-}
// Touch controls
var targetX = courier.x;
var targetY = courier.y;
game.down = function (x, y, obj) {
@@ -1366,10 +564,23 @@
game.move = function (x, y, obj) {
targetX = x;
targetY = y;
};
-// Create first order
+// Create AI couriers
+for (var i = 0; i < 2; i++) {
+ var aiCourier = game.addChild(new AICourier());
+ aiCourier.x = 500 + i * 300;
+ aiCourier.y = 200;
+ aiCouriers.push(aiCourier);
+}
+// Create multiple initial orders
createNewOrder();
+LK.setTimeout(function () {
+ createAIOrder();
+}, 500);
+LK.setTimeout(function () {
+ createAIOrder();
+}, 1000);
// Spawn initial power-up
LK.setTimeout(function () {
spawnPowerUp();
}, 3000);
@@ -1385,96 +596,60 @@
}
// Update current order timer (if not frozen)
if (currentOrder && !timeFreezeActive) {
currentOrder.update();
- // Check if order expired before pickup
- if (!currentOrder.timerStarted && currentOrder.lifeTime >= currentOrder.maxLifeTime) {
- // Order expired - clean up and create new one
- currentOrder.restaurant.hasOrder = false;
- currentOrder.customer.waitingForOrder = false;
- currentOrder.customer.visible = false; // Hide customer
- if (currentOrder.customer.deliveryTarget) {
- tween.stop(currentOrder.customer.deliveryTarget);
- currentOrder.customer.deliveryTarget.destroy();
- currentOrder.customer.deliveryTarget = null;
- }
- currentOrder.destroy();
- for (var i = orders.length - 1; i >= 0; i--) {
- if (orders[i] === currentOrder) {
- orders.splice(i, 1);
- break;
- }
- }
- currentOrder = null;
- gameState = 'pickup';
- // Create new order immediately
- createNewOrder();
- } else {
- // Move order with courier if picked up
- if (courier.hasOrder && gameState === 'delivery') {
- currentOrder.x = courier.x;
- currentOrder.y = courier.y - 40;
- }
- // Maintain delivery target flashing
- if (gameState === 'delivery' && currentOrder.customer.deliveryTarget) {
- var target = currentOrder.customer.deliveryTarget;
- if (!target.isFlashing) {
- var _flashTarget = function flashTarget() {
- if (target.parent) {
- tween(target, {
- alpha: 0.3
- }, {
- duration: 500,
- easing: tween.easeInOut,
- onFinish: function onFinish() {
- if (target.parent) {
- tween(target, {
- alpha: 1
- }, {
- duration: 500,
- easing: tween.easeInOut,
- onFinish: _flashTarget
- });
- }
+ // Move order with courier if picked up
+ if (courier.hasOrder && gameState === 'delivery') {
+ currentOrder.x = courier.x;
+ currentOrder.y = courier.y - 40;
+ }
+ // Maintain delivery target flashing
+ if (gameState === 'delivery' && currentOrder.customer.deliveryTarget) {
+ var target = currentOrder.customer.deliveryTarget;
+ if (!target.isFlashing) {
+ var _flashTarget = function flashTarget() {
+ if (target.parent) {
+ tween(target, {
+ alpha: 0.3
+ }, {
+ duration: 500,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ if (target.parent) {
+ tween(target, {
+ alpha: 1
+ }, {
+ duration: 500,
+ easing: tween.easeInOut,
+ onFinish: _flashTarget
+ });
}
- });
- }
- };
- target.isFlashing = true;
- _flashTarget();
- }
+ }
+ });
+ }
+ };
+ target.isFlashing = true;
+ _flashTarget();
}
- // Check for failed delivery
- if (currentOrder.timeRemaining <= 0 && gameState === 'delivery') {
- completeDelivery();
- }
}
- }
- // Update car count based on money
- createCars();
- // Update cars
- for (var i = 0; i < cars.length; i++) {
- cars[i].update();
- }
- // Clean up old path reservations every 5 seconds
- if (LK.ticks % 300 === 0) {
- var currentTime = Date.now();
- for (var r = reservedPaths.length - 1; r >= 0; r--) {
- if (currentTime - reservedPaths[r].timestamp > 5000) {
- reservedPaths.splice(r, 1);
- }
+ // Check for failed delivery
+ if (currentOrder.timeRemaining <= 0 && gameState === 'delivery') {
+ completeDelivery();
}
}
- // Update AI couriers
- for (var i = 0; i < aiCouriers.length; i++) {
- if (aiCouriers[i] && aiCouriers[i].update) {
- aiCouriers[i].update();
- }
- }
// Update customers
for (var i = 0; i < customers.length; i++) {
customers[i].update();
}
+ // Update AI couriers
+ for (var i = 0; i < aiCouriers.length; i++) {
+ aiCouriers[i].update();
+ }
+ // Create new AI orders periodically
+ if (LK.ticks % 360 === 0 && aiOrders.length < 3) {
+ // Every 6 seconds
+ createAIOrder();
+ }
// Update power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
powerUp.update();
ıts a courier scooter its looking behind . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
police car with flashing lights. In-Game asset. 2d. High contrast. No shadows
vandal riding dirt bike. In-Game asset. High contrast. No shadows
health powerup. In-Game asset. 2d. High contrast. No shadows
pizza boxes. In-Game asset. 2d. High contrast. No shadows
extra time powerup. In-Game asset. 2d. High contrast. No shadows
restaurant shop. In-Game asset. High contrast. No shadows
town house. In-Game asset. 2d. High contrast. No shadows
a man waiting outside. In-Game asset. 2d. High contrast. No shadows
arrow. In-Game asset. 2d. High contrast. No shadows
fence. In-Game asset. 2d. High contrast. No shadows