User prompt
delever package on the right house when player collide with correct house
User prompt
add an arrow indicator to the house where the player should be delivering the package, and also for the package that has to pickup ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
sorry, car front side is left side, switch sprite orientation ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
cars when moving always turn the sprite to that direction, the front side of the sprite is right side ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
prevent house generation to overlap, cars, dogs and player should collide with houses
User prompt
when you click in the screen, player character should follow the mouse instead of teleporting to mouse
User prompt
dog behaviour follows player when get close to him
Code edit (1 edits merged)
Please save this source code
User prompt
Delivery Dash
Initial prompt
Create a simple yet fun 2D pixel art game titled "Delivery Dash". Genre: Action / Arcade / Time Management View: Top-down (like old-school Zelda or GTA 1 style) Main Gameplay Loop: The player controls a delivery person riding a bike or walking around a city map. The objective is to deliver packages to correct houses before time runs out. Houses are randomly placed, and the player must avoid obstacles like cars, dogs, or rival delivery agents. The player earns points based on speed, accuracy, and package condition. Controls: Arrow keys or WASD to move Spacebar or E to deliver a package when standing in front of the right house Optional: Shift for dash (limited stamina) Features: Timer countdown per level Increasing difficulty with new obstacles Power-ups like time extenders, speed boosts, or package protectors Simple scoring system 2-4 progressively harder levels with different city layouts Art Style: Pixel art, colorful and cartoony Sound: Add upbeat chiptune background music and delivery sound effects Make it playable in-browser. Keep code modular and readable in case I want to expand later.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Arrow = Container.expand(function (targetType) { var self = Container.call(this); var arrowGraphics = self.attachAsset('arrow', { anchorX: 0.5, anchorY: 0.5 }); // Set color based on target type if (targetType === 'pickup') { arrowGraphics.tint = 0x00ff00; // Green for package pickup } else if (targetType === 'delivery') { arrowGraphics.tint = 0xff0000; // Red for delivery house } self.targetType = targetType; self.target = null; self.update = function () { if (self.target && player) { // Calculate direction to target var dx = self.target.x - player.x; var dy = self.target.y - player.y; var angle = Math.atan2(dy, dx); // Position arrow around player var radius = 80; self.x = player.x + Math.cos(angle) * radius; self.y = player.y + Math.sin(angle) * radius; // Rotate arrow to point towards target arrowGraphics.rotation = angle + Math.PI / 2; // Pulse animation using tween if (!self.tweening) { self.tweening = true; tween(self, { scaleX: 1.3, scaleY: 1.3 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { self.tweening = false; } }); } }); } } }; return self; }); var Car = Container.expand(function () { var self = Container.call(this); var carGraphics = self.attachAsset('car', { anchorX: 0.5, anchorY: 0.5 }); self.speedX = (Math.random() - 0.5) * 4; self.speedY = (Math.random() - 0.5) * 4; self.update = function () { var oldX = self.x; var oldY = self.y; self.x += self.speedX; self.y += self.speedY; // Calculate rotation based on movement direction // Front of sprite is left side, so 0 rotation = moving left var targetRotation = Math.atan2(self.speedY, self.speedX) + Math.PI; // Smooth rotation using tween tween.stop(carGraphics, { rotation: true }); tween(carGraphics, { rotation: targetRotation }, { duration: 200, easing: tween.easeOut }); // Check collision with houses var hitHouse = false; for (var h = 0; h < houses.length; h++) { if (self.intersects(houses[h])) { hitHouse = true; break; } } // If hit house, revert movement and bounce if (hitHouse) { self.x = oldX; self.y = oldY; self.speedX *= -1; self.speedY *= -1; } // Bounce off edges if (self.x < 40 || self.x > 2008) { self.speedX *= -1; } if (self.y < 40 || self.y > 2692) { self.speedY *= -1; } // Keep in bounds self.x = Math.max(40, Math.min(2008, self.x)); self.y = Math.max(40, Math.min(2692, self.y)); }; return self; }); var Dog = Container.expand(function () { var self = Container.call(this); var dogGraphics = self.attachAsset('dog', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 2; self.direction = Math.random() * Math.PI * 2; self.update = function () { // Check distance to player var dx = player.x - self.x; var dy = player.y - self.y; var distanceToPlayer = Math.sqrt(dx * dx + dy * dy); var detectionRange = 150; if (distanceToPlayer < detectionRange && player) { // Follow player behavior var angleToPlayer = Math.atan2(dy, dx); self.direction = angleToPlayer; self.speed = 2.5; // Slightly faster when chasing } else { // Simple AI - change direction occasionally if (Math.random() < 0.02) { self.direction = Math.random() * Math.PI * 2; } self.speed = 2; // Normal speed when wandering } var oldX = self.x; var oldY = self.y; self.x += Math.cos(self.direction) * self.speed; self.y += Math.sin(self.direction) * self.speed; // Check collision with houses var hitHouse = false; for (var h = 0; h < houses.length; h++) { if (self.intersects(houses[h])) { hitHouse = true; break; } } // If hit house, revert movement and change direction if (hitHouse) { self.x = oldX; self.y = oldY; self.direction = Math.random() * Math.PI * 2; } // Bounce off edges if (self.x < 15 || self.x > 2033) { self.direction = Math.PI - self.direction; } if (self.y < 15 || self.y > 2717) { self.direction = -self.direction; } // Keep in bounds self.x = Math.max(15, Math.min(2033, self.x)); self.y = Math.max(15, Math.min(2717, self.y)); }; return self; }); var House = Container.expand(function (houseId) { var self = Container.call(this); var houseGraphics = self.attachAsset('house', { anchorX: 0.5, anchorY: 0.5 }); self.houseId = houseId; self.hasDelivery = false; self.down = function (x, y, obj) { if (player.hasPackage && self.distanceTo(player) < 80) { if (player.targetHouse === self.houseId) { // Correct delivery LK.setScore(LK.getScore() + 100); player.hasPackage = false; player.targetHouse = null; self.hasDelivery = true; packagesDelivered++; // Visual feedback tween(self, { scaleX: 1.3, scaleY: 1.3 }, { duration: 200, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 200 }); } }); LK.getSound('delivery').play(); scoreText.setText(LK.getScore()); // Remove delivery arrow if (deliveryArrow) { deliveryArrow.destroy(); deliveryArrow = null; } // Create pickup arrow for next available package if (packages.length > 0) { pickupArrow = game.addChild(new Arrow('pickup')); pickupArrow.target = packages[0]; } // Check win condition if (packagesDelivered >= totalPackages) { if (currentLevel < 4) { currentLevel++; startLevel(); } else { LK.showYouWin(); } } } else { // Wrong delivery LK.setScore(Math.max(0, LK.getScore() - 50)); scoreText.setText(LK.getScore()); LK.effects.flashObject(self, 0xff0000, 500); } } }; self.distanceTo = function (other) { var dx = self.x - other.x; var dy = self.y - other.y; return Math.sqrt(dx * dx + dy * dy); }; return self; }); var Package = Container.expand(function () { var self = Container.call(this); var packageGraphics = self.attachAsset('package', { anchorX: 0.5, anchorY: 0.5 }); self.collected = false; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 5; self.hasPackage = false; self.targetHouse = null; return self; }); var PowerUp = Container.expand(function (type) { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); self.type = type; // 'time', 'speed', 'shield' self.collected = false; // Set different colors for different types if (type === 'time') { powerupGraphics.tint = 0x00FF00; } else if (type === 'speed') { powerupGraphics.tint = 0x0080FF; } else if (type === 'shield') { powerupGraphics.tint = 0xFFFF00; } return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x228B22 }); /**** * Game Code ****/ // Game variables var player; var packages = []; var houses = []; var cars = []; var dogs = []; var powerups = []; var currentLevel = 1; var totalPackages = 3; var packagesDelivered = 0; var gameTime = 60000; // 60 seconds var timeRemaining = gameTime; var dragNode = null; var lastCollisionCheck = {}; var targetX = null; var targetY = null; var isMoving = false; var pickupArrow = null; var deliveryArrow = null; // UI elements var scoreText = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); var timeText = new Text2('Time: 60', { size: 60, fill: 0xFFFFFF }); timeText.anchor.set(1, 0); LK.gui.topRight.addChild(timeText); var levelText = new Text2('Level 1', { size: 60, fill: 0xFFFFFF }); levelText.anchor.set(0, 0); LK.gui.topLeft.addChild(levelText); // Create road background for (var i = 0; i < 21; i++) { for (var j = 0; j < 28; j++) { var road = LK.getAsset('road', { x: i * 100, y: j * 100, anchorX: 0, anchorY: 0 }); game.addChild(road); } } function startLevel() { // Clear existing game objects for (var i = packages.length - 1; i >= 0; i--) { packages[i].destroy(); } for (var i = houses.length - 1; i >= 0; i--) { houses[i].destroy(); } for (var i = cars.length - 1; i >= 0; i--) { cars[i].destroy(); } for (var i = dogs.length - 1; i >= 0; i--) { dogs[i].destroy(); } for (var i = powerups.length - 1; i >= 0; i--) { powerups[i].destroy(); } // Clear arrow indicators if (pickupArrow) { pickupArrow.destroy(); pickupArrow = null; } if (deliveryArrow) { deliveryArrow.destroy(); deliveryArrow = null; } packages = []; houses = []; cars = []; dogs = []; powerups = []; packagesDelivered = 0; // Reset time timeRemaining = gameTime; // Update UI levelText.setText('Level ' + currentLevel); // Create player if not exists if (!player) { player = game.addChild(new Player()); player.x = 1024; player.y = 2366; } player.hasPackage = false; player.targetHouse = null; // Helper function to check if position overlaps with existing houses function isPositionClear(x, y, minDistance) { for (var j = 0; j < houses.length; j++) { var dx = x - houses[j].x; var dy = y - houses[j].y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < minDistance) { return false; } } return true; } // Create packages and houses totalPackages = 2 + currentLevel; for (var i = 0; i < totalPackages; i++) { // Create package var pkg = new Package(); pkg.x = 200 + Math.random() * 1600; pkg.y = 200 + Math.random() * 1200; packages.push(pkg); game.addChild(pkg); } // Create corresponding house with overlap prevention // Create pickup arrow indicator pointing to first available package if (packages.length > 0) { pickupArrow = game.addChild(new Arrow('pickup')); pickupArrow.target = packages[0]; } // Create packages and houses for (var i = 0; i < totalPackages; i++) { var house = new House(i); var attempts = 0; var maxAttempts = 50; var minHouseDistance = 200; // Minimum distance between houses do { house.x = 200 + Math.random() * 1600; house.y = 1500 + Math.random() * 1000; attempts++; } while (!isPositionClear(house.x, house.y, minHouseDistance) && attempts < maxAttempts); houses.push(house); game.addChild(house); } // Create cars (more with each level) var numCars = currentLevel + 1; for (var i = 0; i < numCars; i++) { var car = new Car(); car.x = Math.random() * 2048; car.y = Math.random() * 2732; cars.push(car); game.addChild(car); } // Create dogs var numDogs = Math.floor(currentLevel / 2) + 1; for (var i = 0; i < numDogs; i++) { var dog = new Dog(); dog.x = Math.random() * 2048; dog.y = Math.random() * 2732; dogs.push(dog); game.addChild(dog); } // Create power-ups var powerupTypes = ['time', 'speed', 'shield']; for (var i = 0; i < 2; i++) { var powerup = new PowerUp(powerupTypes[Math.floor(Math.random() * powerupTypes.length)]); powerup.x = Math.random() * 2048; powerup.y = Math.random() * 2732; powerups.push(powerup); game.addChild(powerup); } } function handleMove(x, y, obj) { // Set target position for smooth movement targetX = Math.max(30, Math.min(2018, x)); targetY = Math.max(30, Math.min(2702, y)); isMoving = true; } game.move = handleMove; game.down = function (x, y, obj) { // Check if clicking on package to pick up for (var i = 0; i < packages.length; i++) { var pkg = packages[i]; if (!pkg.collected && pkg.intersects && player.intersects(pkg)) { if (!player.hasPackage) { pkg.collected = true; pkg.destroy(); packages.splice(i, 1); player.hasPackage = true; player.targetHouse = i; // Set target house ID LK.getSound('pickup').play(); // Remove pickup arrow and create delivery arrow if (pickupArrow) { pickupArrow.destroy(); pickupArrow = null; } // Create delivery arrow pointing to target house if (player.targetHouse < houses.length) { deliveryArrow = game.addChild(new Arrow('delivery')); deliveryArrow.target = houses[player.targetHouse]; } return; } } } handleMove(x, y, obj); }; game.up = function (x, y, obj) { // Mouse up - no action needed for smooth movement }; game.update = function () { // Smooth player movement towards target if (isMoving && targetX !== null && targetY !== null) { var dx = targetX - player.x; var dy = targetY - player.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { // Move towards target with player speed var moveX = dx / distance * player.speed; var moveY = dy / distance * player.speed; var oldX = player.x; var oldY = player.y; player.x += moveX; player.y += moveY; // Check collision with houses var hitHouse = false; for (var h = 0; h < houses.length; h++) { if (player.intersects(houses[h])) { hitHouse = true; break; } } // If hit house, revert movement if (hitHouse) { player.x = oldX; player.y = oldY; isMoving = false; // Stop movement when hitting house } } else { // Close enough to target, stop moving player.x = targetX; player.y = targetY; isMoving = false; } } // Update time timeRemaining -= 16.67; // Approximate 60fps var seconds = Math.ceil(timeRemaining / 1000); timeText.setText('Time: ' + Math.max(0, seconds)); // Check time up if (timeRemaining <= 0) { LK.showGameOver(); return; } // Check package pickup for (var i = packages.length - 1; i >= 0; i--) { var pkg = packages[i]; if (!pkg.collected && player.intersects(pkg)) { if (!player.hasPackage) { pkg.collected = true; pkg.destroy(); packages.splice(i, 1); player.hasPackage = true; player.targetHouse = i; LK.getSound('pickup').play(); // Remove pickup arrow and create delivery arrow if (pickupArrow) { pickupArrow.destroy(); pickupArrow = null; } // Create delivery arrow pointing to target house if (player.targetHouse < houses.length) { deliveryArrow = game.addChild(new Arrow('delivery')); deliveryArrow.target = houses[player.targetHouse]; } } } } // Check package delivery when player collides with house if (player.hasPackage && player.targetHouse !== null) { for (var h = 0; h < houses.length; h++) { var house = houses[h]; var houseKey = 'house_delivery_' + h; var currentCollision = player.intersects(house); if (!lastCollisionCheck[houseKey] && currentCollision) { // Just started colliding with house if (player.targetHouse === house.houseId) { // Correct delivery LK.setScore(LK.getScore() + 100); player.hasPackage = false; player.targetHouse = null; house.hasDelivery = true; packagesDelivered++; // Visual feedback tween(house, { scaleX: 1.3, scaleY: 1.3 }, { duration: 200, onFinish: function onFinish() { tween(house, { scaleX: 1, scaleY: 1 }, { duration: 200 }); } }); LK.getSound('delivery').play(); scoreText.setText(LK.getScore()); // Remove delivery arrow if (deliveryArrow) { deliveryArrow.destroy(); deliveryArrow = null; } // Create pickup arrow for next available package if (packages.length > 0) { pickupArrow = game.addChild(new Arrow('pickup')); pickupArrow.target = packages[0]; } // Check win condition if (packagesDelivered >= totalPackages) { if (currentLevel < 4) { currentLevel++; startLevel(); } else { LK.showYouWin(); } } } else { // Wrong delivery LK.setScore(Math.max(0, LK.getScore() - 50)); scoreText.setText(LK.getScore()); LK.effects.flashObject(house, 0xff0000, 500); } } lastCollisionCheck[houseKey] = currentCollision; } } // Check powerup collection for (var i = powerups.length - 1; i >= 0; i--) { var powerup = powerups[i]; if (!powerup.collected && player.intersects(powerup)) { powerup.collected = true; powerup.destroy(); powerups.splice(i, 1); if (powerup.type === 'time') { timeRemaining += 10000; // Add 10 seconds } else if (powerup.type === 'speed') { player.speed = 8; LK.setTimeout(function () { player.speed = 5; }, 5000); } LK.getSound('powerup').play(); LK.setScore(LK.getScore() + 25); scoreText.setText(LK.getScore()); } } // Check collisions with obstacles for (var i = 0; i < cars.length; i++) { var car = cars[i]; var carKey = 'car_' + i; var currentCollision = player.intersects(car); if (!lastCollisionCheck[carKey] && currentCollision) { // Just started colliding LK.setScore(Math.max(0, LK.getScore() - 25)); scoreText.setText(LK.getScore()); LK.effects.flashObject(player, 0xff0000, 500); } lastCollisionCheck[carKey] = currentCollision; } for (var i = 0; i < dogs.length; i++) { var dog = dogs[i]; var dogKey = 'dog_' + i; var currentCollision = player.intersects(dog); if (!lastCollisionCheck[dogKey] && currentCollision) { // Just started colliding LK.setScore(Math.max(0, LK.getScore() - 15)); scoreText.setText(LK.getScore()); LK.effects.flashObject(player, 0xff0000, 300); } lastCollisionCheck[dogKey] = currentCollision; } }; // Start the first level startLevel(); // Play background music LK.playMusic('bgmusic');
===================================================================
--- original.js
+++ change.js
@@ -556,8 +556,69 @@
}
}
}
}
+ // Check package delivery when player collides with house
+ if (player.hasPackage && player.targetHouse !== null) {
+ for (var h = 0; h < houses.length; h++) {
+ var house = houses[h];
+ var houseKey = 'house_delivery_' + h;
+ var currentCollision = player.intersects(house);
+ if (!lastCollisionCheck[houseKey] && currentCollision) {
+ // Just started colliding with house
+ if (player.targetHouse === house.houseId) {
+ // Correct delivery
+ LK.setScore(LK.getScore() + 100);
+ player.hasPackage = false;
+ player.targetHouse = null;
+ house.hasDelivery = true;
+ packagesDelivered++;
+ // Visual feedback
+ tween(house, {
+ scaleX: 1.3,
+ scaleY: 1.3
+ }, {
+ duration: 200,
+ onFinish: function onFinish() {
+ tween(house, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 200
+ });
+ }
+ });
+ LK.getSound('delivery').play();
+ scoreText.setText(LK.getScore());
+ // Remove delivery arrow
+ if (deliveryArrow) {
+ deliveryArrow.destroy();
+ deliveryArrow = null;
+ }
+ // Create pickup arrow for next available package
+ if (packages.length > 0) {
+ pickupArrow = game.addChild(new Arrow('pickup'));
+ pickupArrow.target = packages[0];
+ }
+ // Check win condition
+ if (packagesDelivered >= totalPackages) {
+ if (currentLevel < 4) {
+ currentLevel++;
+ startLevel();
+ } else {
+ LK.showYouWin();
+ }
+ }
+ } else {
+ // Wrong delivery
+ LK.setScore(Math.max(0, LK.getScore() - 50));
+ scoreText.setText(LK.getScore());
+ LK.effects.flashObject(house, 0xff0000, 500);
+ }
+ }
+ lastCollisionCheck[houseKey] = currentCollision;
+ }
+ }
// Check powerup collection
for (var i = powerups.length - 1; i >= 0; i--) {
var powerup = powerups[i];
if (!powerup.collected && player.intersects(powerup)) {
shield icon inside of a blue energy bubble. In-Game asset. 2d. High contrast. No shadows
1+ up heart icon. In-Game asset. 2d. High contrast. No shadows
fast foward icon. In-Game asset. 2d. High contrast. No shadows
+10 inside of a clock icon. In-Game asset. 2d. High contrast. No shadows
Street block, garden with concrete walkway on the border. In-Game asset. 2d. High contrast. No shadows