User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'tint')' in or related to this line: 'topFenceGraphics.tint = fenceColor;' Line Number: 1062
User prompt
hide customers in buildings. Because they are living in buildings.
User prompt
make polices vandals and couriers different assets
User prompt
make vandals flashing white and black. And polices flashing bright red and bright blue. They must be move. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'hasOrder')' in or related to this line: 'if (courier.hasOrder && currentOrder) {' Line Number: 641
User prompt
At the starting game asking 3 options Courier, Police or Vandal. And at the pause there have insurance option for couriers. Orders prices between 2$-10$. Prices changes due to distance. Add the insurance module in the game. And insurance limit is 5min. Add 3 vandals in the game and their job is steal the orders from couriers. Their speed is between 0.75-1.25 for courier. And add the 4 polices. each vandal are looking black and white. And each police is blue and red flashing. Policeses job is check insurance and catch the vandals. Vandals earn money when they are steal goods. Polices earn money when they catch a vandal or no insurance couriers. Polices earn 0,5x of money current delivery with no insurance couriers. If polices catch a vandal get 0.5x of their money. Vandals can go a safe house and game is endless (it's mean no limitation like $200 etc). ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
fences are more outer of the map
User prompt
player must be start middle of the map and on the road
User prompt
orders can be complete any side of building.
User prompt
make all builds are solid. And no one can pass on it. Doesnt matter big or small builds.
User prompt
shops scale is 60x60
User prompt
shops are standart 1x scale
User prompt
delete customer dots flashing and make the building as customer. And write on building "im here".
User prompt
set speed limit for ai couriers slower and no one can pass on builds and shops
User prompt
other ai couriers and boosts must be start on road. And keep around our neighbour with fences.
User prompt
Buildings and shops cannot overlap.
User prompt
please change some builds scale 0,5x to 4x
User prompt
scale courier 0,5
User prompt
couriers must be start on the road.
User prompt
Please zoom it 3x and courier scale is 0.15
User prompt
fill the map with buildings and shops. 1 shop for 15 houses. and please mix them.
User prompt
other ai couriers can collect and deliver order. They can be complete orders nearby the building.
User prompt
delivery timing start at when a courier collect an order and set it 25 seconds minimum. If the courier go far away calculate it couriers max speed and when can be reach to customer and add 2 seconds extra.
User prompt
Let's reduce the courier size by half
User prompt
Could we zoom in a bit more to give the impression of a global world? This will widen the roads and make the couriers smaller. Currently, avoiding buildings is a bit difficult since the couriers and buildings are the same size. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/****
* 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 = 3; // Much 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: 9,
height: 9
};
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 restaurants/shops
for (var i = 0; i < restaurants.length; i++) {
var tempCourier = {
x: newX,
y: newY,
width: 9,
height: 9
};
var restaurant = restaurants[i];
if (tempCourier.x < restaurant.x + restaurant.width / 2 && tempCourier.x + tempCourier.width / 2 > restaurant.x - restaurant.width / 2 && tempCourier.y < restaurant.y + restaurant.height / 2 && tempCourier.y + tempCourier.height / 2 > restaurant.y - restaurant.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 from both aiOrders and regular orders
var availableOrders = aiOrders.filter(function (order) {
return !order.claimed;
});
// Also check regular orders that are nearby (within 400 pixels)
var nearbyRegularOrders = orders.filter(function (order) {
if (order === currentOrder) return false; // Don't take player's current order
var dx = order.restaurant.x - self.x;
var dy = order.restaurant.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
return distance < 400 && !order.claimed;
});
// Combine both types of orders
var allAvailableOrders = availableOrders.concat(nearbyRegularOrders);
if (allAvailableOrders.length > 0) {
// Find the closest order
var closestOrder = allAvailableOrders[0];
var closestDistance = Math.sqrt(Math.pow(closestOrder.restaurant.x - self.x, 2) + Math.pow(closestOrder.restaurant.y - self.y, 2));
for (var j = 1; j < allAvailableOrders.length; j++) {
var order = allAvailableOrders[j];
var distance = Math.sqrt(Math.pow(order.restaurant.x - self.x, 2) + Math.pow(order.restaurant.y - self.y, 2));
if (distance < closestDistance) {
closestOrder = order;
closestDistance = distance;
}
}
self.currentOrder = closestOrder;
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';
// Start delivery timer for AI courier
self.currentOrder.startDeliveryTimer(self.speed);
// 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);
// Update time limit based on AI courier distance
self.currentOrder.updateTimeLimit(self.x, self.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;
// Reset customer color to default
self.currentOrder.customer.setOrderColor(0x2196f3);
// 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();
// Remove from aiOrders if it exists there
for (var i = aiOrders.length - 1; i >= 0; i--) {
if (aiOrders[i] === self.currentOrder) {
aiOrders.splice(i, 1);
break;
}
}
// Remove from regular orders if it exists there
for (var i = orders.length - 1; i >= 0; i--) {
if (orders[i] === self.currentOrder) {
orders.splice(i, 1);
break;
}
}
self.currentOrder = null;
self.hasOrder = false;
self.state = 'searching';
};
return self;
});
var ArrowIndicator = Container.expand(function (targetX, targetY, color) {
var self = Container.call(this);
// Create arrow shape using a simple triangle
var arrowGraphics = self.attachAsset('deliveryTarget', {
anchorX: 0.5,
anchorY: 0.5
});
arrowGraphics.tint = color;
arrowGraphics.scaleX = 0.8;
arrowGraphics.scaleY = 1.2;
self.targetX = targetX;
self.targetY = targetY;
self.update = function () {
// Calculate direction to target
var dx = self.targetX - courier.x;
var dy = self.targetY - courier.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 150) {
// Position arrow at edge of screen pointing toward target
var angle = Math.atan2(dy, dx);
var edgeDistance = 300;
// Position relative to screen center (where courier appears)
self.x = 1024 + Math.cos(angle) * edgeDistance;
self.y = 1366 + Math.sin(angle) * edgeDistance;
// Rotate arrow to point toward target
arrowGraphics.rotation = angle;
self.visible = true;
} else {
self.visible = false;
}
};
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 > 5) {
// Smooth movement with momentum for agar.io feel
var moveSpeed = Math.min(self.speed, distance * 0.15);
var newX = self.x + dx / distance * moveSpeed;
var newY = self.y + dy / distance * moveSpeed;
// Check collision with buildings
var canMove = true;
for (var i = 0; i < buildings.length; i++) {
var tempCourier = {
x: newX,
y: newY,
width: 9,
height: 9
};
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 restaurants/shops
for (var i = 0; i < restaurants.length; i++) {
var tempCourier = {
x: newX,
y: newY,
width: 9,
height: 9
};
var restaurant = restaurants[i];
if (tempCourier.x < restaurant.x + restaurant.width / 2 && tempCourier.x + tempCourier.width / 2 > restaurant.x - restaurant.width / 2 && tempCourier.y < restaurant.y + restaurant.height / 2 && tempCourier.y + tempCourier.height / 2 > restaurant.y - restaurant.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.orderColor = 0x2196f3; // Default blue
self.setOrderColor = function (color) {
self.orderColor = color;
customerGraphics.tint = color;
};
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.baseTimeLimit = 25000; // 25 seconds minimum
self.timeLimit = self.baseTimeLimit;
self.timeRemaining = self.timeLimit;
self.isPickedUp = false;
self.courierSpeed = 8; // Default courier speed
self.setColor = function (color) {
orderGraphics.tint = color;
};
self.startDeliveryTimer = function (courierSpeed) {
self.isPickedUp = true;
self.courierSpeed = courierSpeed;
self.timeLimit = self.baseTimeLimit;
self.timeRemaining = self.timeLimit;
};
self.updateTimeLimit = function (courierX, courierY) {
if (!self.isPickedUp || !self.customer) return;
// Calculate distance to customer
var dx = self.customer.x - courierX;
var dy = self.customer.y - courierY;
var distance = Math.sqrt(dx * dx + dy * dy);
// Calculate time needed to reach customer at max speed + 2 seconds buffer
var timeToReach = distance / self.courierSpeed * 16.67 + 2000; // Convert to ms and add 2s buffer
// Use the greater of base time limit or calculated time
var newTimeLimit = Math.max(self.baseTimeLimit, timeToReach);
// Only extend time, never reduce it
if (newTimeLimit > self.timeLimit) {
var extension = newTimeLimit - self.timeLimit;
self.timeLimit = newTimeLimit;
self.timeRemaining += extension;
}
};
self.update = function () {
if (self.isPickedUp && 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;
// Camera system
var cameraX = 0;
var cameraY = 0;
var worldContainer;
var pickupArrow = null;
var deliveryArrow = null;
// Order colors for variety
var orderColors = [0xffff00, 0xff4444, 0x44ff44, 0x4444ff, 0xff44ff, 0x44ffff, 0xffa500, 0x800080];
// 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() {
// Fill entire screen with buildings and restaurants
var buildingRows = 20; // More rows to fill the map
var buildingCols = 15; // More columns to fill the map
var gridSpacingX = 135; // Tighter spacing
var gridSpacingY = 135; // Tighter spacing
var startX = 70; // Start position
var startY = 150; // Start from top, leaving space for UI
// Helper function to check if two objects overlap
function checkOverlap(obj1, obj2) {
var obj1Left = obj1.x - obj1.width / 2;
var obj1Right = obj1.x + obj1.width / 2;
var obj1Top = obj1.y - obj1.height / 2;
var obj1Bottom = obj1.y + obj1.height / 2;
var obj2Left = obj2.x - obj2.width / 2;
var obj2Right = obj2.x + obj2.width / 2;
var obj2Top = obj2.y - obj2.height / 2;
var obj2Bottom = obj2.y + obj2.height / 2;
return !(obj1Right < obj2Left || obj1Left > obj2Right || obj1Bottom < obj2Top || obj1Top > obj2Bottom);
}
// Create array of all positions
var allPositions = [];
for (var row = 0; row < buildingRows; row++) {
for (var col = 0; col < buildingCols; col++) {
var buildingX = startX + col * gridSpacingX;
var buildingY = startY + row * gridSpacingY;
// Ensure buildings stay within reasonable bounds
if (buildingX < 2000 && buildingY < 2700) {
allPositions.push({
x: buildingX,
y: buildingY
});
}
}
}
// Calculate shop count (1 shop per 15 buildings)
var totalPositions = allPositions.length;
var shopCount = Math.floor(totalPositions / 16); // 1 shop for every 15 buildings (16 total positions)
// Shuffle positions to randomly distribute shops
for (var i = allPositions.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = allPositions[i];
allPositions[i] = allPositions[j];
allPositions[j] = temp;
}
// Track all placed objects to prevent overlaps
var placedObjects = [];
// Place shops in first N positions after shuffle
for (var i = 0; i < shopCount; i++) {
var pos = allPositions[i];
var restaurant = worldContainer.addChild(new Restaurant());
restaurant.x = pos.x;
restaurant.y = pos.y;
restaurant.width = 320; // Restaurant asset width
restaurant.height = 320; // Restaurant asset height
// Check for overlaps with existing objects
var overlaps = false;
for (var j = 0; j < placedObjects.length; j++) {
if (checkOverlap(restaurant, placedObjects[j])) {
overlaps = true;
break;
}
}
if (!overlaps) {
restaurants.push(restaurant);
placedObjects.push(restaurant);
} else {
// Remove restaurant if it overlaps
restaurant.destroy();
}
}
// Place buildings in remaining positions
for (var i = shopCount; i < totalPositions; i++) {
var pos = allPositions[i];
var building = worldContainer.addChild(LK.getAsset('building', {
anchorX: 0.5,
anchorY: 0.5,
x: pos.x,
y: pos.y
}));
building.width = 40; // Building asset width
building.height = 40; // Building asset height
// Check for overlaps with existing objects
var overlaps = false;
for (var j = 0; j < placedObjects.length; j++) {
if (checkOverlap(building, placedObjects[j])) {
overlaps = true;
break;
}
}
if (!overlaps) {
buildings.push(building);
placedObjects.push(building);
} else {
// Remove building if it overlaps
building.destroy();
}
}
// Create customers - place them inside buildings (not restaurants)
var customerCount = Math.min(25, buildings.length);
for (var i = 0; i < customerCount; i++) {
var customer = worldContainer.addChild(new Customer());
// Place customer at same position as building
customer.x = buildings[i].x;
customer.y = buildings[i].y;
customers.push(customer);
}
// Create boundary fences around the neighborhood
var fenceThickness = 20;
var fenceColor = 0x8b4513; // Brown color for fences
// Top fence
var topFence = worldContainer.addChild(LK.getAsset('building', {
anchorX: 0.5,
anchorY: 0.5,
x: 1000,
y: 50
}));
topFence.width = 2000;
topFence.height = fenceThickness;
var topFenceGraphics = topFence.children[0];
topFenceGraphics.tint = fenceColor;
buildings.push(topFence);
// Bottom fence
var bottomFence = worldContainer.addChild(LK.getAsset('building', {
anchorX: 0.5,
anchorY: 0.5,
x: 1000,
y: 2750
}));
bottomFence.width = 2000;
bottomFence.height = fenceThickness;
var bottomFenceGraphics = bottomFence.children[0];
bottomFenceGraphics.tint = fenceColor;
buildings.push(bottomFence);
// Left fence
var leftFence = worldContainer.addChild(LK.getAsset('building', {
anchorX: 0.5,
anchorY: 0.5,
x: 25,
y: 1400
}));
leftFence.width = fenceThickness;
leftFence.height = 2700;
var leftFenceGraphics = leftFence.children[0];
leftFenceGraphics.tint = fenceColor;
buildings.push(leftFence);
// Right fence
var rightFence = worldContainer.addChild(LK.getAsset('building', {
anchorX: 0.5,
anchorY: 0.5,
x: 1975,
y: 1400
}));
rightFence.width = fenceThickness;
rightFence.height = 2700;
var rightFenceGraphics = rightFence.children[0];
rightFenceGraphics.tint = fenceColor;
buildings.push(rightFence);
}
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 = worldContainer.addChild(new Order());
order.x = restaurant.x;
order.y = restaurant.y - 60;
order.restaurant = restaurant;
order.customer = customer;
order.claimed = false; // Allow AI couriers to claim this order
// Set random order color and match customer color
var orderColor = orderColors[Math.floor(Math.random() * orderColors.length)];
order.setColor(orderColor);
customer.setOrderColor(orderColor);
restaurant.hasOrder = true;
restaurant.orderReady = true;
customer.waitingForOrder = true;
customer.orderTime = 0;
// Create delivery target indicator
var deliveryTarget = worldContainer.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';
// Create pickup arrow indicator
if (pickupArrow) {
pickupArrow.destroy();
}
pickupArrow = game.addChild(new ArrowIndicator(restaurant.x, restaurant.y, 0x00ff00));
}
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 = worldContainer.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
// Set random order color and match customer color
var orderColor = orderColors[Math.floor(Math.random() * orderColors.length)];
order.setColor(orderColor);
customer.setOrderColor(orderColor);
restaurant.hasOrder = true;
restaurant.orderReady = true;
customer.waitingForOrder = true;
customer.orderTime = 0;
// Create delivery target indicator
var deliveryTarget = worldContainer.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 = worldContainer.addChild(new PowerUp(type));
// Spawn power-ups on road positions between buildings
var roadPositions = [{
x: 200,
y: 220
}, {
x: 335,
y: 220
}, {
x: 470,
y: 220
}, {
x: 605,
y: 220
}, {
x: 740,
y: 220
}, {
x: 200,
y: 355
}, {
x: 335,
y: 355
}, {
x: 470,
y: 355
}, {
x: 605,
y: 355
}, {
x: 740,
y: 355
}, {
x: 200,
y: 490
}, {
x: 335,
y: 490
}, {
x: 470,
y: 490
}, {
x: 605,
y: 490
}, {
x: 740,
y: 490
}, {
x: 200,
y: 625
}, {
x: 335,
y: 625
}, {
x: 470,
y: 625
}, {
x: 605,
y: 625
}, {
x: 740,
y: 625
}];
var roadPos = roadPositions[Math.floor(Math.random() * roadPositions.length)];
powerUp.x = roadPos.x;
powerUp.y = roadPos.y;
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.claimed = true; // Mark as claimed by player
currentOrder.x = courier.x;
currentOrder.y = courier.y - 40;
// Start delivery timer now that order is picked up
currentOrder.startDeliveryTimer(courier.speed);
// Remove pickup arrow and create delivery arrow
if (pickupArrow) {
pickupArrow.destroy();
pickupArrow = null;
}
if (deliveryArrow) {
deliveryArrow.destroy();
}
deliveryArrow = game.addChild(new ArrowIndicator(currentOrder.customer.x, currentOrder.customer.y, 0xff0000));
}
}
// 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;
// Reset customer color to default
currentOrder.customer.setOrderColor(0x2196f3);
// 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';
// Clean up arrow indicators
if (deliveryArrow) {
deliveryArrow.destroy();
deliveryArrow = null;
}
// Create new order after short delay
LK.setTimeout(function () {
createNewOrder();
}, 1000);
}
// Create world container for scrolling
worldContainer = game.addChild(new Container());
// Scale up the world to zoom in more - this makes roads wider and couriers appear smaller
worldContainer.scaleX = 3;
worldContainer.scaleY = 3;
// Initialize game elements
createNeighborhood();
// Create courier - spawn on road (between buildings)
courier = worldContainer.addChild(new Courier());
// Place courier on a road position between buildings
courier.x = 200; // Road position between building columns
courier.y = 220; // Road position between building rows
// Touch controls
var targetX = courier.x;
var targetY = courier.y;
game.down = function (x, y, obj) {
// Convert screen coordinates to world coordinates accounting for scale
targetX = x / worldContainer.scaleX + cameraX;
targetY = y / worldContainer.scaleY + cameraY;
};
game.move = function (x, y, obj) {
// Convert screen coordinates to world coordinates accounting for scale
targetX = x / worldContainer.scaleX + cameraX;
targetY = y / worldContainer.scaleY + cameraY;
};
// Create AI couriers - spawn on road positions
for (var i = 0; i < 2; i++) {
var aiCourier = worldContainer.addChild(new AICourier());
// Place AI couriers on road positions between buildings (same as courier spawn logic)
var roadPositions = [{
x: 200,
y: 220
},
// Same as courier start position
{
x: 335,
y: 220
},
// Road between columns
{
x: 470,
y: 220
},
// Road between columns
{
x: 200,
y: 355
},
// Road between rows
{
x: 335,
y: 355
},
// Road between rows
{
x: 470,
y: 355
} // Road between rows
];
var roadPos = roadPositions[i % roadPositions.length];
aiCourier.x = roadPos.x;
aiCourier.y = roadPos.y;
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 camera to follow courier
cameraX = courier.x - 1024 / worldContainer.scaleX; // Center courier horizontally accounting for scale
cameraY = courier.y - 1366 / worldContainer.scaleY; // Center courier vertically accounting for scale
// Apply camera offset to world container
worldContainer.x = -cameraX * worldContainer.scaleX;
worldContainer.y = -cameraY * worldContainer.scaleY;
// Update time freeze
if (timeFreezeActive) {
timeFreezeRemaining -= 16.67;
if (timeFreezeRemaining <= 0) {
timeFreezeActive = false;
}
}
// Update current order timer (if not frozen)
if (currentOrder && !timeFreezeActive) {
// Update time limit based on courier distance if picked up
if (courier.hasOrder && gameState === 'delivery') {
currentOrder.updateTimeLimit(courier.x, courier.y);
}
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 arrow indicators
if (pickupArrow) {
pickupArrow.update();
}
if (deliveryArrow) {
deliveryArrow.update();
}
// Update UI
updateUI();
// Win condition (optional - could be score based)
if (money >= 200) {
LK.showYouWin();
}
}; ===================================================================
--- original.js
+++ change.js
@@ -12,9 +12,9 @@
anchorX: 0.5,
anchorY: 0.5
});
courierGraphics.tint = 0xff5722; // Orange tint for AI courier
- self.speed = 6; // Slightly slower than player
+ self.speed = 3; // Much slower than player
self.hasOrder = false;
self.targetRestaurant = null;
self.targetCustomer = null;
self.currentOrder = null;
@@ -41,8 +41,22 @@
canMove = false;
break;
}
}
+ // Check collision with restaurants/shops
+ for (var i = 0; i < restaurants.length; i++) {
+ var tempCourier = {
+ x: newX,
+ y: newY,
+ width: 9,
+ height: 9
+ };
+ var restaurant = restaurants[i];
+ if (tempCourier.x < restaurant.x + restaurant.width / 2 && tempCourier.x + tempCourier.width / 2 > restaurant.x - restaurant.width / 2 && tempCourier.y < restaurant.y + restaurant.height / 2 && tempCourier.y + tempCourier.height / 2 > restaurant.y - restaurant.height / 2) {
+ canMove = false;
+ break;
+ }
+ }
if (canMove) {
self.x = newX;
self.y = newY;
}
@@ -217,8 +231,22 @@
canMove = false;
break;
}
}
+ // Check collision with restaurants/shops
+ for (var i = 0; i < restaurants.length; i++) {
+ var tempCourier = {
+ x: newX,
+ y: newY,
+ width: 9,
+ height: 9
+ };
+ var restaurant = restaurants[i];
+ if (tempCourier.x < restaurant.x + restaurant.width / 2 && tempCourier.x + tempCourier.width / 2 > restaurant.x - restaurant.width / 2 && tempCourier.y < restaurant.y + restaurant.height / 2 && tempCourier.y + tempCourier.height / 2 > restaurant.y - restaurant.height / 2) {
+ canMove = false;
+ break;
+ }
+ }
if (canMove) {
self.x = newX;
self.y = newY;
}
ı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