User prompt
bence başka bir kod bunu kısıtlıyor yaazılar büyümüyor readable falan olmadı
User prompt
yazı tipini eskisi gibi yap büyük olsun bu nedir yahu görünmüyor
User prompt
can you fix the problems
User prompt
it wasnt work do it again
User prompt
make all texts 10x bigger
User prompt
make buttons for role choosing screen. Courier's button is green, police' button is blue, vandal is black and all texts are white.
User prompt
MAke texts are bigger enough
User prompt
ok do it
User prompt
add white stroke to COURIER, POLICE, VANDAL
User prompt
can you make it white background and %80 transparent. And "Choose Your Role" sentence can be with in black stroke
User prompt
can you make good background for start menu ? i cant read them.
User prompt
show only our customer which one is will take delivery and hide others. And make smallest "I'm here" word.
User prompt
and now take the customer outside of build because we made bigger houses but customers still stay behind. I hope you are understand
User prompt
vandals are so fast make them 2x slower than current
User prompt
builds are shown bigger than current. Their solid bases are same but they need shown to be bigger.
User prompt
create fences asset
User prompt
create assets for arrows.
User prompt
add more polices and vandals
User prompt
when i go on customer complete the delivery.
User prompt
put the customers bottom rightside of house. And show only our customer.
User prompt
when i collect the order show the customer location with arrow.
User prompt
Now player stuck near the customer. Please set the customers size 1x1 and at the out of house.
User prompt
I cant reach the customer.
User prompt
vandals cant be move faster than 1.1x of courier
User prompt
Couriers start with $20. And all npcs do their job can't be stay anywhere.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var AICourier = Container.expand(function () {
var self = Container.call(this);
var courierGraphics = self.attachAsset('courierAsset', {
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;
}
}
// Check collision with customers
for (var i = 0; i < customers.length; i++) {
var tempCourier = {
x: newX,
y: newY,
width: 9,
height: 9
};
var customer = customers[i];
if (tempCourier.x < customer.x + 1 / 2 && tempCourier.x + tempCourier.width / 2 > customer.x - 1 / 2 && tempCourier.y < customer.y + 1 / 2 && tempCourier.y + tempCourier.height / 2 > customer.y - 1 / 2) {
canMove = false;
break;
}
}
if (canMove) {
self.x = newX;
self.y = newY;
}
}
};
self.update = function () {
self.thinkTimer += 16.67;
// AI decision making every 200ms - more frequent thinking
if (self.thinkTimer >= 200) {
self.thinkTimer = 0;
if (self.state === 'searching' && !self.hasOrder) {
// Always move around when searching for orders
if (!self.searchTarget || Math.abs(self.x - self.searchTarget.x) < 30 && Math.abs(self.y - self.searchTarget.y) < 30) {
self.searchTarget = {
x: 200 + Math.random() * 1600,
y: 200 + Math.random() * 2300
};
}
self.moveToward(self.searchTarget.x, self.searchTarget.y);
// 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 "I'm here" text from building
var customer = self.currentOrder.customer;
var building = null;
for (var b = 0; b < buildings.length; b++) {
if (buildings[b].x === customer.x && buildings[b].y === customer.y) {
building = buildings[b];
break;
}
}
if (building && building.customerText) {
building.customerText.destroy();
building.customerText = 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('courierAsset', {
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;
}
}
// Check collision with customers
for (var i = 0; i < customers.length; i++) {
var tempCourier = {
x: newX,
y: newY,
width: 9,
height: 9
};
var customer = customers[i];
if (tempCourier.x < customer.x + 1 / 2 && tempCourier.x + tempCourier.width / 2 > customer.x - 1 / 2 && tempCourier.y < customer.y + 1 / 2 && tempCourier.y + tempCourier.height / 2 > customer.y - 1 / 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 Police = Container.expand(function () {
var self = Container.call(this);
var policeGraphics = self.attachAsset('policeAsset', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4;
self.money = 0;
self.targetVandal = null;
self.targetCourier = null;
self.state = 'patrolling'; // 'patrolling', 'chasing', 'checking'
self.thinkTimer = 0;
self.flashTimer = 0;
self.isFlashing = false;
// Start flashing animation with bright colors
tween(policeGraphics, {
tint: 0xff0000
}, {
duration: 300,
onFinish: function onFinish() {
tween(policeGraphics, {
tint: 0x0080ff
}, {
duration: 300,
onFinish: function onFinish() {
// Continue flashing cycle
self.startFlashing();
}
});
}
});
self.startFlashing = function () {
tween(policeGraphics, {
tint: 0xff0000
}, {
duration: 300,
onFinish: function onFinish() {
tween(policeGraphics, {
tint: 0x0080ff
}, {
duration: 300,
onFinish: function onFinish() {
self.startFlashing();
}
});
}
});
};
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 tempPolice = {
x: newX,
y: newY,
width: 9,
height: 9
};
var building = buildings[i];
if (tempPolice.x < building.x + building.width / 2 && tempPolice.x + tempPolice.width / 2 > building.x - building.width / 2 && tempPolice.y < building.y + building.height / 2 && tempPolice.y + tempPolice.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;
if (self.thinkTimer >= 150) {
self.thinkTimer = 0;
if (self.state === 'patrolling') {
// Always move to random patrol points when not chasing
if (!self.patrolTarget || Math.abs(self.x - self.patrolTarget.x) < 20 && Math.abs(self.y - self.patrolTarget.y) < 20) {
self.patrolTarget = {
x: 200 + Math.random() * 1600,
y: 200 + Math.random() * 2300
};
}
self.moveToward(self.patrolTarget.x, self.patrolTarget.y);
// Look for vandals first
var closestVandal = null;
var closestVandalDistance = Infinity;
for (var i = 0; i < vandals.length; i++) {
var vandal = vandals[i];
var dx = vandal.x - self.x;
var dy = vandal.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 300 && distance < closestVandalDistance) {
closestVandal = vandal;
closestVandalDistance = distance;
}
}
if (closestVandal) {
self.targetVandal = closestVandal;
self.state = 'chasing';
} else {
// Check for couriers without insurance
var targets = [];
// Check player courier
if (playerRole === 'courier' && courier && courier.hasOrder && !hasInsurance) {
var dx = courier.x - self.x;
var dy = courier.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 200) {
targets.push({
courier: courier,
distance: distance
});
}
}
// Check AI couriers (they never have insurance)
for (var i = 0; i < aiCouriers.length; i++) {
var aiCourier = aiCouriers[i];
if (aiCourier.hasOrder) {
var dx = aiCourier.x - self.x;
var dy = aiCourier.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 200) {
targets.push({
courier: aiCourier,
distance: distance
});
}
}
}
if (targets.length > 0) {
targets.sort(function (a, b) {
return a.distance - b.distance;
});
self.targetCourier = targets[0].courier;
self.state = 'checking';
}
}
}
}
if (self.state === 'chasing' && self.targetVandal) {
self.moveToward(self.targetVandal.x, self.targetVandal.y);
// Check if close enough to catch
var dx = self.targetVandal.x - self.x;
var dy = self.targetVandal.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 25) {
self.catchVandal();
}
} else if (self.state === 'checking' && self.targetCourier) {
self.moveToward(self.targetCourier.x, self.targetCourier.y);
// Check if close enough to fine
var dx = self.targetCourier.x - self.x;
var dy = self.targetCourier.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 30) {
self.fineUninsuredCourier();
}
}
};
self.catchVandal = function () {
if (!self.targetVandal) return;
// Take 50% of vandal's money
var stolenMoney = Math.floor(self.targetVandal.money * 0.5);
self.money += stolenMoney;
self.targetVandal.money -= stolenMoney;
// Reset vandal to safe house
self.targetVandal.x = self.targetVandal.safeHouseX;
self.targetVandal.y = self.targetVandal.safeHouseY;
self.targetVandal.state = 'searching';
self.targetVandal.hasOrder = false;
if (self.targetVandal.currentOrder) {
self.targetVandal.currentOrder.destroy();
self.targetVandal.currentOrder = null;
}
self.targetVandal = null;
self.state = 'patrolling';
};
self.fineUninsuredCourier = function () {
if (!self.targetCourier) return;
var fineAmount = 0;
if (self.targetCourier === courier && currentOrder) {
// Fine player courier
var dx = currentOrder.restaurant.x - currentOrder.customer.x;
var dy = currentOrder.restaurant.y - currentOrder.customer.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var orderValue = Math.max(2, Math.min(10, Math.floor(distance / 100) + 2));
fineAmount = Math.floor(orderValue * 0.5);
money = Math.max(0, money - fineAmount);
self.money += fineAmount;
} else if (self.targetCourier.currentOrder) {
// Fine AI courier
var dx = self.targetCourier.currentOrder.restaurant.x - self.targetCourier.currentOrder.customer.x;
var dy = self.targetCourier.currentOrder.restaurant.y - self.targetCourier.currentOrder.customer.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var orderValue = Math.max(2, Math.min(10, Math.floor(distance / 100) + 2));
fineAmount = Math.floor(orderValue * 0.5);
self.money += fineAmount;
}
self.targetCourier = null;
self.state = 'patrolling';
};
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;
});
var Vandal = Container.expand(function () {
var self = Container.call(this);
var vandalGraphics = self.attachAsset('vandalAsset', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = Math.min(8.8, 3 + Math.random() * 2); // Limited to 1.1x courier speed max
self.hasOrder = false;
self.targetOrder = null;
self.money = 0;
self.state = 'searching'; // 'searching', 'stealing', 'fleeing'
self.thinkTimer = 0;
self.safeHouseX = 100;
self.safeHouseY = 100;
self.flashTimer = 0;
self.isFlashing = false;
// Start flashing animation
tween(vandalGraphics, {
tint: 0xffffff
}, {
duration: 500,
onFinish: function onFinish() {
tween(vandalGraphics, {
tint: 0x000000
}, {
duration: 500,
onFinish: function onFinish() {
// Recursive flashing
tween(vandalGraphics, {
tint: 0xffffff
}, {
duration: 500,
onFinish: function onFinish() {
tween(vandalGraphics, {
tint: 0x000000
}, {
duration: 500,
onFinish: function onFinish() {
// Continue flashing cycle
self.startFlashing();
}
});
}
});
}
});
}
});
self.startFlashing = function () {
tween(vandalGraphics, {
tint: 0xffffff
}, {
duration: 500,
onFinish: function onFinish() {
tween(vandalGraphics, {
tint: 0x000000
}, {
duration: 500,
onFinish: function onFinish() {
self.startFlashing();
}
});
}
});
};
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 tempVandal = {
x: newX,
y: newY,
width: 9,
height: 9
};
var building = buildings[i];
if (tempVandal.x < building.x + building.width / 2 && tempVandal.x + tempVandal.width / 2 > building.x - building.width / 2 && tempVandal.y < building.y + building.height / 2 && tempVandal.y + tempVandal.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;
if (self.thinkTimer >= 200) {
self.thinkTimer = 0;
if (self.state === 'searching' && !self.hasOrder) {
// Always move around when searching
if (!self.searchTarget || Math.abs(self.x - self.searchTarget.x) < 30 && Math.abs(self.y - self.searchTarget.y) < 30) {
self.searchTarget = {
x: 200 + Math.random() * 1600,
y: 200 + Math.random() * 2300
};
}
self.moveToward(self.searchTarget.x, self.searchTarget.y);
// Look for couriers with orders to steal
var targets = [];
// Check player courier
if (courier && courier.hasOrder && currentOrder) {
var dx = courier.x - self.x;
var dy = courier.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 200) {
targets.push({
courier: courier,
order: currentOrder,
distance: distance
});
}
}
// Check AI couriers
for (var i = 0; i < aiCouriers.length; i++) {
var aiCourier = aiCouriers[i];
if (aiCourier.hasOrder && aiCourier.currentOrder) {
var dx = aiCourier.x - self.x;
var dy = aiCourier.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 200) {
targets.push({
courier: aiCourier,
order: aiCourier.currentOrder,
distance: distance
});
}
}
}
if (targets.length > 0) {
// Target closest courier with order
targets.sort(function (a, b) {
return a.distance - b.distance;
});
self.targetOrder = targets[0];
self.state = 'stealing';
}
}
}
if (self.state === 'stealing' && self.targetOrder) {
self.moveToward(self.targetOrder.courier.x, self.targetOrder.courier.y);
// Check if close enough to steal
var dx = self.targetOrder.courier.x - self.x;
var dy = self.targetOrder.courier.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 30) {
// Steal the order
self.stealOrder();
}
} else if (self.state === 'fleeing') {
self.moveToward(self.safeHouseX, self.safeHouseY);
// Check if reached safe house
var dx = self.safeHouseX - self.x;
var dy = self.safeHouseY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 50) {
self.state = 'searching';
self.hasOrder = false;
if (self.currentOrder) {
self.currentOrder.destroy();
self.currentOrder = null;
}
}
}
};
self.stealOrder = function () {
if (!self.targetOrder) return;
var targetCourier = self.targetOrder.courier;
var stolenOrder = self.targetOrder.order;
// Calculate order value based on distance
var dx = stolenOrder.restaurant.x - stolenOrder.customer.x;
var dy = stolenOrder.restaurant.y - stolenOrder.customer.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var orderValue = Math.max(2, Math.min(10, Math.floor(distance / 100) + 2));
self.money += orderValue;
self.hasOrder = true;
self.currentOrder = stolenOrder;
self.state = 'fleeing';
// Remove order from target courier
if (targetCourier === courier && courier) {
// Stolen from player
courier.hasOrder = false;
currentOrder = null;
gameState = 'pickup';
// Clean up arrows
if (deliveryArrow) {
deliveryArrow.destroy();
deliveryArrow = null;
}
// Create new order for player
LK.setTimeout(function () {
createNewOrder();
}, 1000);
} else {
// Stolen from AI courier
targetCourier.hasOrder = false;
targetCourier.currentOrder = null;
targetCourier.state = 'searching';
}
// Move order to vandal
stolenOrder.x = self.x;
stolenOrder.y = self.y - 40;
self.targetOrder = null;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x8BC34A
});
/****
* Game Code
****/
// Game variables
var courier;
var aiCouriers = [];
var vandals = [];
var police = [];
var restaurants = [];
var customers = [];
var orders = [];
var aiOrders = [];
var powerUps = [];
var buildings = [];
var health = 100;
var money = 20;
var currentOrder = null;
var gameState = 'pickup'; // 'pickup', 'delivery'
var timeFreezeActive = false;
var timeFreezeRemaining = 0;
// Role system
var playerRole = storage.playerRole || null; // 'courier', 'police', 'vandal'
var hasInsurance = false;
var insuranceEndTime = 0;
var gameStarted = false;
// 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;
// Role selection UI
var roleSelectionContainer = new Container();
LK.gui.center.addChild(roleSelectionContainer);
var roleTitle = new Text2('Choose Your Role', {
size: 80,
fill: 0xFFFFFF
});
roleTitle.anchor.set(0.5, 0.5);
roleTitle.y = -200;
roleSelectionContainer.addChild(roleTitle);
var courierButton = new Text2('COURIER', {
size: 60,
fill: 0x4caf50
});
courierButton.anchor.set(0.5, 0.5);
courierButton.y = -50;
roleSelectionContainer.addChild(courierButton);
var policeButton = new Text2('POLICE', {
size: 60,
fill: 0x2196f3
});
policeButton.anchor.set(0.5, 0.5);
policeButton.y = 50;
roleSelectionContainer.addChild(policeButton);
var vandalButton = new Text2('VANDAL', {
size: 60,
fill: 0x000000
});
vandalButton.anchor.set(0.5, 0.5);
vandalButton.y = 150;
roleSelectionContainer.addChild(vandalButton);
// Insurance UI (for couriers)
var insuranceButton = new Text2('Buy Insurance ($5)', {
size: 40,
fill: 0xFFD700
});
insuranceButton.anchor.set(0.5, 0);
LK.gui.top.addChild(insuranceButton);
insuranceButton.y = 160;
insuranceButton.visible = false;
var insuranceStatus = new Text2('', {
size: 30,
fill: 0x00FF00
});
insuranceStatus.anchor.set(0.5, 0);
LK.gui.top.addChild(insuranceStatus);
insuranceStatus.y = 210;
// 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 = 60; // Restaurant asset width
restaurant.height = 60; // 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 outside 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 outside building (to the right side)
customer.x = buildings[i].x + 30;
customer.y = buildings[i].y;
// Make customers visible outside buildings
customer.visible = true;
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: 10
}));
topFence.width = 2000;
topFence.height = fenceThickness;
if (topFence.children && topFence.children.length > 0) {
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: 2722
}));
bottomFence.width = 2000;
bottomFence.height = fenceThickness;
if (bottomFence.children && bottomFence.children.length > 0) {
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: 10,
y: 1400
}));
leftFence.width = fenceThickness;
leftFence.height = 2700;
if (leftFence.children && leftFence.children.length > 0) {
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: 2038,
y: 1400
}));
rightFence.width = fenceThickness;
rightFence.height = 2700;
if (rightFence.children && rightFence.children.length > 0) {
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;
// Add "I'm here" text to the building that has the customer
var building = null;
for (var b = 0; b < buildings.length; b++) {
if (buildings[b].x === customer.x && buildings[b].y === customer.y) {
building = buildings[b];
break;
}
}
if (building && !building.customerText) {
var customerText = new Text2("I'm here", {
size: 20,
fill: 0xFFFFFF
});
customerText.anchor.set(0.5, 0.5);
customerText.x = 0;
customerText.y = -30;
building.addChild(customerText);
building.customerText = customerText;
}
customer.deliveryTarget = null;
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;
// Add "I'm here" text to the building that has the customer
var building = null;
for (var b = 0; b < buildings.length; b++) {
if (buildings[b].x === customer.x && buildings[b].y === customer.y) {
building = buildings[b];
break;
}
}
if (building && !building.customerText) {
var customerText = new Text2("I'm here", {
size: 20,
fill: 0xFFFFFF
});
customerText.anchor.set(0.5, 0.5);
customerText.x = 0;
customerText.y = -30;
building.addChild(customerText);
building.customerText = customerText;
}
customer.deliveryTarget = null;
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() {
if (playerRole === 'courier') {
healthBar.setText('Health: ' + Math.floor(health));
moneyText.setText('$' + money);
if (hasInsurance) {
var timeLeft = Math.max(0, (insuranceEndTime - Date.now()) / 1000);
insuranceStatus.setText('Insurance: ' + timeLeft.toFixed(0) + 's');
insuranceStatus.visible = true;
} else {
insuranceStatus.visible = false;
}
if (currentOrder && gameState === 'delivery') {
var timeLeft = Math.max(0, currentOrder.timeRemaining / 1000);
orderTimer.setText('Deliver in: ' + timeLeft.toFixed(1) + 's');
} else {
orderTimer.setText('');
}
} else if (playerRole === 'police') {
healthBar.setText('Police Money: $' + courier.money);
moneyText.setText('Player: $' + money);
orderTimer.setText('');
insuranceStatus.visible = false;
} else if (playerRole === 'vandal') {
healthBar.setText('Vandal Money: $' + courier.money);
moneyText.setText('Player: $' + money);
orderTimer.setText('');
insuranceStatus.visible = false;
}
}
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();
}
// Find the building that contains this customer for the arrow
var targetBuilding = null;
for (var b = 0; b < buildings.length; b++) {
if (buildings[b].x === currentOrder.customer.x && buildings[b].y === currentOrder.customer.y) {
targetBuilding = buildings[b];
break;
}
}
if (targetBuilding) {
deliveryArrow = game.addChild(new ArrowIndicator(targetBuilding.x, targetBuilding.y, 0xff0000));
}
}
}
// Check courier-customer collision for delivery
if (gameState === 'delivery' && currentOrder && courier.hasOrder) {
// Find the building that contains this customer
var targetBuilding = null;
for (var b = 0; b < buildings.length; b++) {
if (buildings[b].x === currentOrder.customer.x && buildings[b].y === currentOrder.customer.y) {
targetBuilding = buildings[b];
break;
}
}
if (targetBuilding) {
// Check if courier is near the building from any side (expanded collision area)
var dx = courier.x - targetBuilding.x;
var dy = courier.y - targetBuilding.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Allow delivery from any side of building (80 pixel radius around building center)
if (distance < 80) {
// 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 - calculate price based on distance
var dx = currentOrder.restaurant.x - currentOrder.customer.x;
var dy = currentOrder.restaurant.y - currentOrder.customer.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var basePrice = Math.max(2, Math.min(10, Math.floor(distance / 100) + 2));
var timeBonus = Math.floor(currentOrder.timeRemaining / 1000);
bonus = basePrice + Math.min(timeBonus, 3); // Cap time bonus at $3
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 "I'm here" text from building
var customer = currentOrder.customer;
var building = null;
for (var b = 0; b < buildings.length; b++) {
if (buildings[b].x === customer.x && buildings[b].y === customer.y) {
building = buildings[b];
break;
}
}
if (building && building.customerText) {
building.customerText.destroy();
building.customerText = 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();
// Courier will be created after role selection
// Role selection handlers
courierButton.down = function () {
selectRole('courier');
};
policeButton.down = function () {
selectRole('police');
};
vandalButton.down = function () {
selectRole('vandal');
};
insuranceButton.down = function () {
buyInsurance();
};
function selectRole(role) {
playerRole = role;
storage.playerRole = role;
roleSelectionContainer.visible = false;
if (role === 'courier') {
insuranceButton.visible = true;
courier = worldContainer.addChild(new Courier());
courier.x = 1000;
courier.y = 1400;
} else if (role === 'police') {
courier = worldContainer.addChild(new Police());
courier.x = 1000;
courier.y = 1400;
} else if (role === 'vandal') {
courier = worldContainer.addChild(new Vandal());
courier.x = 1000;
courier.y = 1400;
}
gameStarted = true;
if (role === 'courier') {
createNewOrder();
}
}
function buyInsurance() {
if (money >= 5 && !hasInsurance) {
money -= 5;
hasInsurance = true;
insuranceEndTime = Date.now() + 300000; // 5 minutes
insuranceButton.visible = false;
}
}
// Touch controls
var targetX = 1000;
var targetY = 1400;
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 3 vandals
for (var i = 0; i < 3; i++) {
var vandal = worldContainer.addChild(new Vandal());
var vandalPositions = [{
x: 300,
y: 300
}, {
x: 700,
y: 600
}, {
x: 1200,
y: 900
}];
var pos = vandalPositions[i];
vandal.x = pos.x;
vandal.y = pos.y;
vandals.push(vandal);
}
// Create 4 police
for (var i = 0; i < 4; i++) {
var policeOfficer = worldContainer.addChild(new Police());
var policePositions = [{
x: 500,
y: 400
}, {
x: 900,
y: 700
}, {
x: 1300,
y: 1000
}, {
x: 600,
y: 1200
}];
var pos = policePositions[i];
policeOfficer.x = pos.x;
policeOfficer.y = pos.y;
police.push(policeOfficer);
}
// Don't create initial order until role is selected
LK.setTimeout(function () {
createAIOrder();
}, 500);
LK.setTimeout(function () {
createAIOrder();
}, 1000);
// Spawn initial power-up
LK.setTimeout(function () {
spawnPowerUp();
}, 3000);
game.update = function () {
// Only run game logic if role is selected
if (!gameStarted || !courier) return;
// Update insurance status
if (hasInsurance && Date.now() > insuranceEndTime) {
hasInsurance = false;
if (playerRole === 'courier') {
insuranceButton.visible = true;
}
}
// 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;
}
// No delivery target flashing needed anymore - buildings show "I'm here" text instead
// 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();
}
// Update vandals
for (var i = 0; i < vandals.length; i++) {
vandals[i].update();
}
// Update police
for (var i = 0; i < police.length; i++) {
police[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();
// Game is now endless - no win condition
}; ===================================================================
--- original.js
+++ change.js
@@ -65,9 +65,9 @@
width: 9,
height: 9
};
var customer = customers[i];
- if (tempCourier.x < customer.x + 160 / 2 && tempCourier.x + tempCourier.width / 2 > customer.x - 160 / 2 && tempCourier.y < customer.y + 160 / 2 && tempCourier.y + tempCourier.height / 2 > customer.y - 160 / 2) {
+ if (tempCourier.x < customer.x + 1 / 2 && tempCourier.x + tempCourier.width / 2 > customer.x - 1 / 2 && tempCourier.y < customer.y + 1 / 2 && tempCourier.y + tempCourier.height / 2 > customer.y - 1 / 2) {
canMove = false;
break;
}
}
@@ -284,9 +284,9 @@
width: 9,
height: 9
};
var customer = customers[i];
- if (tempCourier.x < customer.x + 160 / 2 && tempCourier.x + tempCourier.width / 2 > customer.x - 160 / 2 && tempCourier.y < customer.y + 160 / 2 && tempCourier.y + tempCourier.height / 2 > customer.y - 160 / 2) {
+ if (tempCourier.x < customer.x + 1 / 2 && tempCourier.x + tempCourier.width / 2 > customer.x - 1 / 2 && tempCourier.y < customer.y + 1 / 2 && tempCourier.y + tempCourier.height / 2 > customer.y - 1 / 2) {
canMove = false;
break;
}
}
@@ -1027,17 +1027,17 @@
// Remove building if it overlaps
building.destroy();
}
}
- // Create customers - place them inside buildings (not restaurants)
+ // Create customers - place them outside 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;
+ // Place customer outside building (to the right side)
+ customer.x = buildings[i].x + 30;
customer.y = buildings[i].y;
- // Hide customers inside buildings
- customer.visible = false;
+ // Make customers visible outside buildings
+ customer.visible = true;
customers.push(customer);
}
// Create boundary fences around the neighborhood
var fenceThickness = 20;
ı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