Code edit (1 edits merged)
Please save this source code
User prompt
Plague Doctor: Village Purge
User prompt
Make a game where we are plague doctors and travel from village to village to find sick people and execute them. There should be walking keys to move our character in the game and a start screen. Instead of a large map, there should be a spatial village map where we can move horizontally and there should be normal and sick people around. We need to find and kill sick people.put a button to execute sick villagers and we can move up and down not just left and rightThe villagers should not suddenly appear, they should already be there
User prompt
The villagers should not suddenly appear, they should already be there
User prompt
put a button to execute sick villagers and we can move up and down not just left and right
Initial prompt
Make a game where we are plague doctors and travel from village to village to find sick people and execute them. There should be walking keys to move our character in the game and a start screen. Instead of a large map, there should be a spatial village map where we can move horizontally and there should be normal and sick people around. We need to find and kill sick people.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // D-Pad Button class var DPadButton = Container.expand(function () { var self = Container.call(this); self.bg = self.attachAsset('dpadBtn', { anchorX: 0.5, anchorY: 0.5 }); self.bg.alpha = 0.7; self.icon = null; // Will be set by game code return self; }); // Execute Button class var ExecuteButton = Container.expand(function () { var self = Container.call(this); self.bg = self.attachAsset('executeBtn', { anchorX: 0.5, anchorY: 0.5 }); self.bg.alpha = 0.92; self.label = new Text2('EXECUTE', { size: 60, fill: "#fff" }); self.label.anchor.set(0.5, 0.5); self.addChild(self.label); self.visible = false; return self; }); // Plague Doctor (player) class var PlagueDoctor = Container.expand(function () { var self = Container.call(this); var doctorSprite = self.attachAsset('plagueDoctor', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 18; // Movement speed per tick // For collision box, use the asset's width/height self.getBounds = function () { return { x: self.x - doctorSprite.width / 2, y: self.y - doctorSprite.height / 2, width: doctorSprite.width, height: doctorSprite.height }; }; return self; }); // Villager class var Villager = Container.expand(function () { var self = Container.call(this); self.isSick = false; self.isAlive = true; self.init = function (isSick) { self.isSick = isSick; self.isAlive = true; self.removeChildren(); var assetId = isSick ? 'villagerSick' : 'villagerHealthy'; self.sprite = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); }; self.getBounds = function () { return { x: self.x - self.sprite.width / 2, y: self.y - self.sprite.height / 2, width: self.sprite.width, height: self.sprite.height }; }; self.execute = function () { self.isAlive = false; // Animate fade out and shrink tween(self.sprite, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 400, easing: tween.cubicIn, onFinish: function onFinish() { self.visible = false; } }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xf2e5bc }); /**** * Game Code ****/ // D-pad buttons // "Execute" button // Sick villager // Healthy villager // Plague Doctor (player) // --- Game constants --- var VILLAGE_WIDTH = 4096; // The map is twice the screen width, scrollable horizontally var VILLAGE_HEIGHT = 2048; // Slightly less than full height for padding var NUM_VILLAGERS = 18; var NUM_SICK = 6; var VILLAGER_MIN_DIST = 220; // Minimum distance between villagers // --- Game state --- var player; var villagers = []; var sickLeft = NUM_SICK; var executeBtn; var dpadBtns = {}; var dpadState = { up: false, down: false, left: false, right: false }; var cameraX = 0; // For horizontal scrolling var draggingDPad = null; var canExecuteVillager = null; // Reference to sick villager in range // --- GUI elements --- var sickLeftTxt = new Text2('Sick left: ' + sickLeft, { size: 90, fill: 0xB16262 }); sickLeftTxt.anchor.set(0.5, 0); // Place at top center, but not in top 100px LK.gui.top.addChild(sickLeftTxt); sickLeftTxt.y = 110; // --- Helper functions --- function clamp(val, min, max) { if (val < min) return min; if (val > max) return max; return val; } // Axis-aligned bounding box collision function aabbIntersect(a, b) { return a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y; } // --- Map and villagers setup --- // Center the map vertically, allow horizontal scrolling var mapOffsetY = (game.height - VILLAGE_HEIGHT) / 2; // Place villagers randomly, but not too close to each other or the player start function placeVillagers() { villagers = []; var placed = 0; var sickPlaced = 0; while (placed < NUM_VILLAGERS) { var isSick = sickPlaced < NUM_SICK ? true : false; var villager = new Villager(); villager.init(isSick); // Random position in map bounds, avoid top 100px var x = 200 + Math.random() * (VILLAGE_WIDTH - 400); var y = mapOffsetY + 120 + Math.random() * (VILLAGE_HEIGHT - 240); // Don't place too close to player start (center left) if (Math.abs(x - 300) < 300 && Math.abs(y - game.height / 2) < 300) continue; // Don't place too close to other villagers var tooClose = false; for (var i = 0; i < villagers.length; ++i) { var dx = x - villagers[i].x; var dy = y - villagers[i].y; if (Math.sqrt(dx * dx + dy * dy) < VILLAGER_MIN_DIST) { tooClose = true; break; } } if (tooClose) continue; villager.x = x; villager.y = y; game.addChild(villager); villagers.push(villager); if (isSick) sickPlaced++; placed++; } } // --- Player setup --- player = new PlagueDoctor(); player.x = 300; player.y = game.height / 2; game.addChild(player); // --- Villagers --- placeVillagers(); // --- Execute Button --- executeBtn = new ExecuteButton(); executeBtn.x = game.width / 2; executeBtn.y = game.height - 320; LK.gui.bottom.addChild(executeBtn); // --- D-Pad Controls (bottom left, not in top 100px) --- var dpadSize = 140; var dpadMargin = 60; var dpadCenterX = 180; var dpadCenterY = game.height - 320; function createDPadBtn(dir, dx, dy, label) { var btn = new DPadButton(); btn.x = dpadCenterX + dx * (dpadSize + dpadMargin); btn.y = dpadCenterY + dy * (dpadSize + dpadMargin); // Add icon btn.icon = new Text2(label, { size: 70, fill: "#222" }); btn.icon.anchor.set(0.5, 0.5); btn.addChild(btn.icon); LK.gui.bottomLeft.addChild(btn); dpadBtns[dir] = btn; } createDPadBtn('up', 0, -1, '▲'); createDPadBtn('down', 0, 1, '▼'); createDPadBtn('left', -1, 0, '◀'); createDPadBtn('right', 1, 0, '▶'); // --- D-Pad event handling --- function dpadBtnForPos(x, y) { for (var dir in dpadBtns) { var btn = dpadBtns[dir]; var bx = btn.x; var by = btn.y; var r = dpadSize / 2; if ((x - bx) * (x - bx) + (y - by) * (y - by) < r * r) { return dir; } } return null; } // D-Pad touch/mouse down LK.gui.bottomLeft.down = function (x, y, obj) { var dir = dpadBtnForPos(x, y); if (dir) { dpadState[dir] = true; draggingDPad = dir; // Visual feedback tween(dpadBtns[dir].bg, { alpha: 1 }, { duration: 80 }); } }; // D-Pad touch/mouse up LK.gui.bottomLeft.up = function (x, y, obj) { if (draggingDPad) { dpadState[draggingDPad] = false; tween(dpadBtns[draggingDPad].bg, { alpha: 0.7 }, { duration: 120 }); draggingDPad = null; } }; // D-Pad move (drag) LK.gui.bottomLeft.move = function (x, y, obj) { if (draggingDPad) { var dir = dpadBtnForPos(x, y); for (var d in dpadState) { if (d === dir) { if (!dpadState[d]) { dpadState[d] = true; tween(dpadBtns[d].bg, { alpha: 1 }, { duration: 80 }); } } else { if (dpadState[d]) { dpadState[d] = false; tween(dpadBtns[d].bg, { alpha: 0.7 }, { duration: 120 }); } } } } }; // --- Execute Button event handling --- executeBtn.down = function (x, y, obj) { if (canExecuteVillager && canExecuteVillager.isAlive) { canExecuteVillager.execute(); sickLeft--; sickLeftTxt.setText('Sick left: ' + sickLeft); executeBtn.visible = false; canExecuteVillager = null; // Win condition if (sickLeft === 0) { LK.showYouWin(); } } }; // --- Main game move handler (for dragging player, not used here) --- game.move = function (x, y, obj) { // No drag-to-move, only D-pad }; // --- Main game update loop --- game.update = function () { // --- Player movement --- var dx = 0, dy = 0; if (dpadState.left) dx -= 1; if (dpadState.right) dx += 1; if (dpadState.up) dy -= 1; if (dpadState.down) dy += 1; if (dx !== 0 || dy !== 0) { var len = Math.sqrt(dx * dx + dy * dy); if (len > 0) { dx /= len; dy /= len; } player.x += dx * player.speed; player.y += dy * player.speed; } // Clamp player to map bounds player.x = clamp(player.x, 60, VILLAGE_WIDTH - 60); player.y = clamp(player.y, mapOffsetY + 90, mapOffsetY + VILLAGE_HEIGHT - 90); // --- Camera scrolling (horizontal only) --- var screenCenterX = game.width / 2; cameraX = player.x - screenCenterX; cameraX = clamp(cameraX, 0, VILLAGE_WIDTH - game.width); // Move all game children (player, villagers) relative to cameraX for (var i = 0; i < game.children.length; ++i) { var obj = game.children[i]; obj.visible = true; if (obj === player) { obj.x = player.x - cameraX; obj.y = player.y; } else if (obj instanceof Villager) { obj.x = obj.x0 !== undefined ? obj.x0 - cameraX : obj.x - cameraX; obj.y = obj.y0 !== undefined ? obj.y0 : obj.y; } } // --- Villager proximity check --- canExecuteVillager = null; for (var i = 0; i < villagers.length; ++i) { var villager = villagers[i]; if (!villager.isAlive || !villager.isSick) continue; // Use world coordinates for collision var px = player.x; var py = player.y; var vx = villager.x0 !== undefined ? villager.x0 : villager.x + cameraX; var vy = villager.y0 !== undefined ? villager.y0 : villager.y; var dist = Math.sqrt((px - vx) * (px - vx) + (py - vy) * (py - vy)); if (dist < 140) { canExecuteVillager = villager; break; } } // --- Execute button visibility --- if (canExecuteVillager && canExecuteVillager.isAlive) { executeBtn.visible = true; } else { executeBtn.visible = false; } }; // --- Store original world positions for villagers (for camera) --- for (var i = 0; i < villagers.length; ++i) { villagers[i].x0 = villagers[i].x; villagers[i].y0 = villagers[i].y; } // --- Initial camera position --- cameraX = 0; for (var i = 0; i < game.children.length; ++i) { var obj = game.children[i]; if (obj === player) { obj.x = player.x - cameraX; obj.y = player.y; } else if (obj instanceof Villager) { obj.x = obj.x0 - cameraX; obj.y = obj.y0; } }
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,383 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// D-Pad Button class
+var DPadButton = Container.expand(function () {
+ var self = Container.call(this);
+ self.bg = self.attachAsset('dpadBtn', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.bg.alpha = 0.7;
+ self.icon = null; // Will be set by game code
+ return self;
+});
+// Execute Button class
+var ExecuteButton = Container.expand(function () {
+ var self = Container.call(this);
+ self.bg = self.attachAsset('executeBtn', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.bg.alpha = 0.92;
+ self.label = new Text2('EXECUTE', {
+ size: 60,
+ fill: "#fff"
+ });
+ self.label.anchor.set(0.5, 0.5);
+ self.addChild(self.label);
+ self.visible = false;
+ return self;
+});
+// Plague Doctor (player) class
+var PlagueDoctor = Container.expand(function () {
+ var self = Container.call(this);
+ var doctorSprite = self.attachAsset('plagueDoctor', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 18; // Movement speed per tick
+ // For collision box, use the asset's width/height
+ self.getBounds = function () {
+ return {
+ x: self.x - doctorSprite.width / 2,
+ y: self.y - doctorSprite.height / 2,
+ width: doctorSprite.width,
+ height: doctorSprite.height
+ };
+ };
+ return self;
+});
+// Villager class
+var Villager = Container.expand(function () {
+ var self = Container.call(this);
+ self.isSick = false;
+ self.isAlive = true;
+ self.init = function (isSick) {
+ self.isSick = isSick;
+ self.isAlive = true;
+ self.removeChildren();
+ var assetId = isSick ? 'villagerSick' : 'villagerHealthy';
+ self.sprite = self.attachAsset(assetId, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ };
+ self.getBounds = function () {
+ return {
+ x: self.x - self.sprite.width / 2,
+ y: self.y - self.sprite.height / 2,
+ width: self.sprite.width,
+ height: self.sprite.height
+ };
+ };
+ self.execute = function () {
+ self.isAlive = false;
+ // Animate fade out and shrink
+ tween(self.sprite, {
+ alpha: 0,
+ scaleX: 0.1,
+ scaleY: 0.1
+ }, {
+ duration: 400,
+ easing: tween.cubicIn,
+ onFinish: function onFinish() {
+ self.visible = false;
+ }
+ });
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0xf2e5bc
+});
+
+/****
+* Game Code
+****/
+// D-pad buttons
+// "Execute" button
+// Sick villager
+// Healthy villager
+// Plague Doctor (player)
+// --- Game constants ---
+var VILLAGE_WIDTH = 4096; // The map is twice the screen width, scrollable horizontally
+var VILLAGE_HEIGHT = 2048; // Slightly less than full height for padding
+var NUM_VILLAGERS = 18;
+var NUM_SICK = 6;
+var VILLAGER_MIN_DIST = 220; // Minimum distance between villagers
+// --- Game state ---
+var player;
+var villagers = [];
+var sickLeft = NUM_SICK;
+var executeBtn;
+var dpadBtns = {};
+var dpadState = {
+ up: false,
+ down: false,
+ left: false,
+ right: false
+};
+var cameraX = 0; // For horizontal scrolling
+var draggingDPad = null;
+var canExecuteVillager = null; // Reference to sick villager in range
+// --- GUI elements ---
+var sickLeftTxt = new Text2('Sick left: ' + sickLeft, {
+ size: 90,
+ fill: 0xB16262
+});
+sickLeftTxt.anchor.set(0.5, 0);
+// Place at top center, but not in top 100px
+LK.gui.top.addChild(sickLeftTxt);
+sickLeftTxt.y = 110;
+// --- Helper functions ---
+function clamp(val, min, max) {
+ if (val < min) return min;
+ if (val > max) return max;
+ return val;
+}
+// Axis-aligned bounding box collision
+function aabbIntersect(a, b) {
+ return a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y;
+}
+// --- Map and villagers setup ---
+// Center the map vertically, allow horizontal scrolling
+var mapOffsetY = (game.height - VILLAGE_HEIGHT) / 2;
+// Place villagers randomly, but not too close to each other or the player start
+function placeVillagers() {
+ villagers = [];
+ var placed = 0;
+ var sickPlaced = 0;
+ while (placed < NUM_VILLAGERS) {
+ var isSick = sickPlaced < NUM_SICK ? true : false;
+ var villager = new Villager();
+ villager.init(isSick);
+ // Random position in map bounds, avoid top 100px
+ var x = 200 + Math.random() * (VILLAGE_WIDTH - 400);
+ var y = mapOffsetY + 120 + Math.random() * (VILLAGE_HEIGHT - 240);
+ // Don't place too close to player start (center left)
+ if (Math.abs(x - 300) < 300 && Math.abs(y - game.height / 2) < 300) continue;
+ // Don't place too close to other villagers
+ var tooClose = false;
+ for (var i = 0; i < villagers.length; ++i) {
+ var dx = x - villagers[i].x;
+ var dy = y - villagers[i].y;
+ if (Math.sqrt(dx * dx + dy * dy) < VILLAGER_MIN_DIST) {
+ tooClose = true;
+ break;
+ }
+ }
+ if (tooClose) continue;
+ villager.x = x;
+ villager.y = y;
+ game.addChild(villager);
+ villagers.push(villager);
+ if (isSick) sickPlaced++;
+ placed++;
+ }
+}
+// --- Player setup ---
+player = new PlagueDoctor();
+player.x = 300;
+player.y = game.height / 2;
+game.addChild(player);
+// --- Villagers ---
+placeVillagers();
+// --- Execute Button ---
+executeBtn = new ExecuteButton();
+executeBtn.x = game.width / 2;
+executeBtn.y = game.height - 320;
+LK.gui.bottom.addChild(executeBtn);
+// --- D-Pad Controls (bottom left, not in top 100px) ---
+var dpadSize = 140;
+var dpadMargin = 60;
+var dpadCenterX = 180;
+var dpadCenterY = game.height - 320;
+function createDPadBtn(dir, dx, dy, label) {
+ var btn = new DPadButton();
+ btn.x = dpadCenterX + dx * (dpadSize + dpadMargin);
+ btn.y = dpadCenterY + dy * (dpadSize + dpadMargin);
+ // Add icon
+ btn.icon = new Text2(label, {
+ size: 70,
+ fill: "#222"
+ });
+ btn.icon.anchor.set(0.5, 0.5);
+ btn.addChild(btn.icon);
+ LK.gui.bottomLeft.addChild(btn);
+ dpadBtns[dir] = btn;
+}
+createDPadBtn('up', 0, -1, '▲');
+createDPadBtn('down', 0, 1, '▼');
+createDPadBtn('left', -1, 0, '◀');
+createDPadBtn('right', 1, 0, '▶');
+// --- D-Pad event handling ---
+function dpadBtnForPos(x, y) {
+ for (var dir in dpadBtns) {
+ var btn = dpadBtns[dir];
+ var bx = btn.x;
+ var by = btn.y;
+ var r = dpadSize / 2;
+ if ((x - bx) * (x - bx) + (y - by) * (y - by) < r * r) {
+ return dir;
+ }
+ }
+ return null;
+}
+// D-Pad touch/mouse down
+LK.gui.bottomLeft.down = function (x, y, obj) {
+ var dir = dpadBtnForPos(x, y);
+ if (dir) {
+ dpadState[dir] = true;
+ draggingDPad = dir;
+ // Visual feedback
+ tween(dpadBtns[dir].bg, {
+ alpha: 1
+ }, {
+ duration: 80
+ });
+ }
+};
+// D-Pad touch/mouse up
+LK.gui.bottomLeft.up = function (x, y, obj) {
+ if (draggingDPad) {
+ dpadState[draggingDPad] = false;
+ tween(dpadBtns[draggingDPad].bg, {
+ alpha: 0.7
+ }, {
+ duration: 120
+ });
+ draggingDPad = null;
+ }
+};
+// D-Pad move (drag)
+LK.gui.bottomLeft.move = function (x, y, obj) {
+ if (draggingDPad) {
+ var dir = dpadBtnForPos(x, y);
+ for (var d in dpadState) {
+ if (d === dir) {
+ if (!dpadState[d]) {
+ dpadState[d] = true;
+ tween(dpadBtns[d].bg, {
+ alpha: 1
+ }, {
+ duration: 80
+ });
+ }
+ } else {
+ if (dpadState[d]) {
+ dpadState[d] = false;
+ tween(dpadBtns[d].bg, {
+ alpha: 0.7
+ }, {
+ duration: 120
+ });
+ }
+ }
+ }
+ }
+};
+// --- Execute Button event handling ---
+executeBtn.down = function (x, y, obj) {
+ if (canExecuteVillager && canExecuteVillager.isAlive) {
+ canExecuteVillager.execute();
+ sickLeft--;
+ sickLeftTxt.setText('Sick left: ' + sickLeft);
+ executeBtn.visible = false;
+ canExecuteVillager = null;
+ // Win condition
+ if (sickLeft === 0) {
+ LK.showYouWin();
+ }
+ }
+};
+// --- Main game move handler (for dragging player, not used here) ---
+game.move = function (x, y, obj) {
+ // No drag-to-move, only D-pad
+};
+// --- Main game update loop ---
+game.update = function () {
+ // --- Player movement ---
+ var dx = 0,
+ dy = 0;
+ if (dpadState.left) dx -= 1;
+ if (dpadState.right) dx += 1;
+ if (dpadState.up) dy -= 1;
+ if (dpadState.down) dy += 1;
+ if (dx !== 0 || dy !== 0) {
+ var len = Math.sqrt(dx * dx + dy * dy);
+ if (len > 0) {
+ dx /= len;
+ dy /= len;
+ }
+ player.x += dx * player.speed;
+ player.y += dy * player.speed;
+ }
+ // Clamp player to map bounds
+ player.x = clamp(player.x, 60, VILLAGE_WIDTH - 60);
+ player.y = clamp(player.y, mapOffsetY + 90, mapOffsetY + VILLAGE_HEIGHT - 90);
+ // --- Camera scrolling (horizontal only) ---
+ var screenCenterX = game.width / 2;
+ cameraX = player.x - screenCenterX;
+ cameraX = clamp(cameraX, 0, VILLAGE_WIDTH - game.width);
+ // Move all game children (player, villagers) relative to cameraX
+ for (var i = 0; i < game.children.length; ++i) {
+ var obj = game.children[i];
+ obj.visible = true;
+ if (obj === player) {
+ obj.x = player.x - cameraX;
+ obj.y = player.y;
+ } else if (obj instanceof Villager) {
+ obj.x = obj.x0 !== undefined ? obj.x0 - cameraX : obj.x - cameraX;
+ obj.y = obj.y0 !== undefined ? obj.y0 : obj.y;
+ }
+ }
+ // --- Villager proximity check ---
+ canExecuteVillager = null;
+ for (var i = 0; i < villagers.length; ++i) {
+ var villager = villagers[i];
+ if (!villager.isAlive || !villager.isSick) continue;
+ // Use world coordinates for collision
+ var px = player.x;
+ var py = player.y;
+ var vx = villager.x0 !== undefined ? villager.x0 : villager.x + cameraX;
+ var vy = villager.y0 !== undefined ? villager.y0 : villager.y;
+ var dist = Math.sqrt((px - vx) * (px - vx) + (py - vy) * (py - vy));
+ if (dist < 140) {
+ canExecuteVillager = villager;
+ break;
+ }
+ }
+ // --- Execute button visibility ---
+ if (canExecuteVillager && canExecuteVillager.isAlive) {
+ executeBtn.visible = true;
+ } else {
+ executeBtn.visible = false;
+ }
+};
+// --- Store original world positions for villagers (for camera) ---
+for (var i = 0; i < villagers.length; ++i) {
+ villagers[i].x0 = villagers[i].x;
+ villagers[i].y0 = villagers[i].y;
+}
+// --- Initial camera position ---
+cameraX = 0;
+for (var i = 0; i < game.children.length; ++i) {
+ var obj = game.children[i];
+ if (obj === player) {
+ obj.x = player.x - cameraX;
+ obj.y = player.y;
+ } else if (obj instanceof Villager) {
+ obj.x = obj.x0 - cameraX;
+ obj.y = obj.y0;
+ }
+}
\ No newline at end of file
Kill button. In-Game asset. 2d. High contrast. No shadows
Palugue doctors full body pixel art. In-Game asset. 2d. High contrast. No shadows
Sick viliger pixel art full body
Not sick viliger pixel art
Pixel art death block.
Viliger house pixel art. In-Game asset. 2d. High contrast. No shadows
Background sand image pixel art. 4k In-Game asset. 2d. High contrast. No shadows