User prompt
make the enemies npc that are independed from the other objects
User prompt
add a war background
User prompt
also add the future to win the first level after beating 10 enemies. and after going to the next level, make the goal is to beat 20 enemies
User prompt
make it so that the game takes long and it never ends unless you beat all the enemies that are trying to attack you. give our character a gun that can shoot when we click ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Dreams of the Forgotten Town
Initial prompt
Make me a game where the player wakes up in a quiet, abandoned town with no memory of who they are. The world should feel eerie but beautiful, like a dream that's slowly turning into a nightmare. The main character doesn't speak, but the people they meet seem to know them — and they’re hiding something. Let the gameplay focus on exploration, emotional storytelling, and solving symbolic puzzles tied to the protagonist's past. Every choice the player makes, even small ones, should quietly shape the story and how it ends. Use a hand-drawn, slightly surreal art style that feels like flipping through someone’s old sketchbook. There should be no combat — tension and conflict come from atmosphere, music, and the weight of decisions. Make the soundtrack dynamic, so it responds to where the player is and what they’re feeling. Themes like memory, identity, and regret should be at the core of everything. Think of it as a haunting mix of Omori, Inside, and a forgotten fairy tale.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { ending: 0, foundFragments: 0 }); /**** * Classes ****/ // Door class (scene transition) var Door = Container.expand(function () { var self = Container.call(this); var sprite = self.attachAsset('door', { anchorX: 0.5, anchorY: 0.5 }); self.targetScene = ""; self.highlight = null; self.showHighlight = function () { if (!self.highlight) { self.highlight = self.attachAsset('highlight', { anchorX: 0.5, anchorY: 0.5, alpha: 0.10 }); } self.highlight.visible = true; }; self.hideHighlight = function () { if (self.highlight) self.highlight.visible = false; }; return self; }); // Memory Fragment class var MemoryFragment = Container.expand(function () { var self = Container.call(this); var sprite = self.attachAsset('memoryFragment', { anchorX: 0.5, anchorY: 0.5 }); self.collected = false; self.highlight = null; self.showHighlight = function () { if (!self.highlight) { self.highlight = self.attachAsset('highlight', { anchorX: 0.5, anchorY: 0.5, alpha: 0.13 }); } self.highlight.visible = true; }; self.hideHighlight = function () { if (self.highlight) self.highlight.visible = false; }; return self; }); // NPC class var NPC = Container.expand(function () { var self = Container.call(this); var sprite = self.attachAsset('npc', { anchorX: 0.5, anchorY: 0.5 }); self.dialogue = []; self.dialogueIndex = 0; self.name = ""; self.interacted = false; self.highlight = null; // Show highlight when player is near self.showHighlight = function () { if (!self.highlight) { self.highlight = self.attachAsset('highlight', { anchorX: 0.5, anchorY: 0.5, alpha: 0.18 }); } self.highlight.visible = true; }; self.hideHighlight = function () { if (self.highlight) self.highlight.visible = false; }; return self; }); // Player class var Player = Container.expand(function () { var self = Container.call(this); var sprite = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 18; self.targetX = self.x; self.targetY = self.y; self.moving = false; // Move towards target self.update = function () { if (!self.moving) return; var dx = self.targetX - self.x; var dy = self.targetY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < self.speed) { self.x = self.targetX; self.y = self.targetY; self.moving = false; } else { self.x += self.speed * dx / dist; self.y += self.speed * dy / dist; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xfaf7f2 }); /**** * Game Code ****/ /* We use simple shapes for the sketchbook-like look. - 'player': the protagonist, a hand-drawn ellipse. - 'npc': townsfolk, a box with a different color. - 'memoryFragment': symbolic puzzle piece, a star-shaped box. - 'door': a rectangle for scene transitions. - 'bgTown': a large, pale rectangle as the background. - 'highlight': a transparent overlay for interactable objects. */ // --- State --- var player; var npcs = []; var memoryFragments = []; var doors = []; var currentScene = "town"; var dialogueBox = null; var dialogueText = null; var choiceButtons = []; var infoText = null; var canMove = true; var lastNearObject = null; var foundFragments = storage.foundFragments || 0; var totalFragments = 3; var ending = storage.ending || 0; // --- GUI --- function showInfo(msg, duration) { if (!infoText) { infoText = new Text2(msg, { size: 80, fill: 0x444444 }); infoText.anchor.set(0.5, 0); LK.gui.top.addChild(infoText); } infoText.setText(msg); infoText.visible = true; if (duration) { LK.setTimeout(function () { if (infoText) infoText.visible = false; }, duration); } } // --- Scene Setup --- function setupTownScene() { // Clear previous game.removeChildren(); npcs = []; memoryFragments = []; doors = []; lastNearObject = null; // Background var bg = LK.getAsset('bgTown', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); game.addChild(bg); // Player player = new Player(); player.x = 1024; player.y = 2000; game.addChild(player); // NPCs var npc1 = new NPC(); npc1.x = 700; npc1.y = 1500; npc1.name = "Caretaker"; npc1.dialogue = ["You look lost. The town remembers you, even if you don't remember it.", "Find the fragments of your memory. They are hidden in plain sight.", "Come back when you remember more."]; npcs.push(npc1); game.addChild(npc1); var npc2 = new NPC(); npc2.x = 1400; npc2.y = 1100; npc2.name = "Child"; npc2.dialogue = ["Will you play with me? Or are you too busy remembering?", "Sometimes, forgetting is easier than facing the truth."]; npcs.push(npc2); game.addChild(npc2); // Memory Fragments var frag1 = new MemoryFragment(); frag1.x = 400; frag1.y = 800; memoryFragments.push(frag1); game.addChild(frag1); var frag2 = new MemoryFragment(); frag2.x = 1700; frag2.y = 1800; memoryFragments.push(frag2); game.addChild(frag2); var frag3 = new MemoryFragment(); frag3.x = 1200; frag3.y = 2500; memoryFragments.push(frag3); game.addChild(frag3); // Door to ending var door = new Door(); door.x = 1024; door.y = 400; door.targetScene = "ending"; doors.push(door); game.addChild(door); // Show info showInfo("Explore the town. Tap to move. Find your memories.", 3000); } // --- Dialogue System --- function showDialogue(npc) { canMove = false; if (!dialogueBox) { dialogueBox = new Container(); var box = LK.getAsset('bgTown', { width: 1600, height: 400, color: 0xffffff, anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2200 }); box.alpha = 0.92; dialogueBox.addChild(box); dialogueText = new Text2("", { size: 70, fill: 0x222222 }); dialogueText.anchor.set(0.5, 0.5); dialogueText.x = 1024; dialogueText.y = 2200; dialogueBox.addChild(dialogueText); LK.gui.bottom.addChild(dialogueBox); } dialogueBox.visible = true; dialogueText.setText(npc.name + ": " + npc.dialogue[npc.dialogueIndex]); // Next dialogue on tap dialogueBox.down = function (x, y, obj) { npc.dialogueIndex++; if (npc.dialogueIndex >= npc.dialogue.length) { npc.dialogueIndex = 0; dialogueBox.visible = false; canMove = true; } else { dialogueText.setText(npc.name + ": " + npc.dialogue[npc.dialogueIndex]); } LK.getSound('choice').play(); }; } // --- Choice System --- function showChoice(msg, choices, onSelect) { canMove = false; // Remove old for (var i = 0; i < choiceButtons.length; ++i) { if (choiceButtons[i].parent) choiceButtons[i].parent.removeChild(choiceButtons[i]); } choiceButtons = []; // Message if (!dialogueBox) { dialogueBox = new Container(); var box = LK.getAsset('bgTown', { width: 1600, height: 400, color: 0xffffff, anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2200 }); box.alpha = 0.92; dialogueBox.addChild(box); dialogueText = new Text2("", { size: 70, fill: 0x222222 }); dialogueText.anchor.set(0.5, 0.5); dialogueText.x = 1024; dialogueText.y = 2200; dialogueBox.addChild(dialogueText); LK.gui.bottom.addChild(dialogueBox); } dialogueBox.visible = true; dialogueText.setText(msg); // Buttons for (var i = 0; i < choices.length; ++i) { var btn = new Text2(choices[i], { size: 70, fill: 0x3A3A3A }); btn.anchor.set(0.5, 0.5); btn.x = 1024; btn.y = 2400 + i * 120; btn.interactive = true; (function (idx) { btn.down = function (x, y, obj) { dialogueBox.visible = false; for (var j = 0; j < choiceButtons.length; ++j) { if (choiceButtons[j].parent) choiceButtons[j].parent.removeChild(choiceButtons[j]); } choiceButtons = []; canMove = true; LK.getSound('choice').play(); onSelect(idx); }; })(i); LK.gui.bottom.addChild(btn); choiceButtons.push(btn); } } // --- Memory Fragment Collection --- function collectFragment(fragment) { if (fragment.collected) return; fragment.collected = true; foundFragments++; storage.foundFragments = foundFragments; LK.getSound('memoryFound').play(); tween(fragment, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { if (fragment.parent) fragment.parent.removeChild(fragment); } }); showInfo("You found a memory fragment! (" + foundFragments + "/" + totalFragments + ")", 2000); if (foundFragments === totalFragments) { showInfo("All fragments found. The door is open.", 3000); } } // --- Ending Scene --- function setupEndingScene() { game.removeChildren(); if (dialogueBox) dialogueBox.visible = false; for (var i = 0; i < choiceButtons.length; ++i) { if (choiceButtons[i].parent) choiceButtons[i].parent.removeChild(choiceButtons[i]); } choiceButtons = []; // Background var bg = LK.getAsset('bgTown', { anchorX: 0, anchorY: 0, x: 0, y: 0, color: 0xeaeaea }); game.addChild(bg); // Ending text var endingText = new Text2("", { size: 110, fill: 0x222222 }); endingText.anchor.set(0.5, 0.5); endingText.x = 1024; endingText.y = 1200; if (foundFragments === totalFragments) { endingText.setText("You remember everything.\nThe town is at peace.\n\nThank you for playing."); storage.ending = 2; } else if (foundFragments > 0) { endingText.setText("Some memories return, but many are lost.\nThe town remains a mystery.\n\nThank you for playing."); storage.ending = 1; } else { endingText.setText("You leave, still lost.\nThe town fades behind you.\n\nThank you for playing."); storage.ending = 0; } game.addChild(endingText); // Show "You Win" after a short delay LK.setTimeout(function () { LK.showYouWin(); }, 2500); } // --- Music --- LK.playMusic('dream', { fade: { start: 0, end: 0.7, duration: 1200 } }); // --- Start Scene --- setupTownScene(); // --- Game Move Handler --- game.move = function (x, y, obj) { if (!canMove) return; // Prevent moving into top left menu area if (x < 100 && y < 100) return; // Move player player.targetX = x; player.targetY = y; player.moving = true; }; // --- Game Down Handler (for interaction) --- game.down = function (x, y, obj) { if (!canMove) return; // Check for nearby interactables var nearObj = null; // NPCs for (var i = 0; i < npcs.length; ++i) { var npc = npcs[i]; var dx = npc.x - player.x; var dy = npc.y - player.y; if (dx * dx + dy * dy < 300 * 300) { nearObj = npc; break; } } // Memory Fragments if (!nearObj) { for (var i = 0; i < memoryFragments.length; ++i) { var frag = memoryFragments[i]; if (frag.collected) continue; var dx = frag.x - player.x; var dy = frag.y - player.y; if (dx * dx + dy * dy < 180 * 180) { nearObj = frag; break; } } } // Door if (!nearObj && foundFragments === totalFragments) { for (var i = 0; i < doors.length; ++i) { var door = doors[i]; var dx = door.x - player.x; var dy = door.y - player.y; if (dx * dx + dy * dy < 220 * 220) { nearObj = door; break; } } } // Interact if (nearObj) { if (nearObj instanceof NPC) { showDialogue(nearObj); } else if (nearObj instanceof MemoryFragment) { collectFragment(nearObj); } else if (nearObj instanceof Door) { // Ending setupEndingScene(); } } }; // --- Game Update --- game.update = function () { // Player update if (player && player.update) player.update(); // Highlight nearby interactables var nearest = null; var minDist = 99999; // NPCs for (var i = 0; i < npcs.length; ++i) { var npc = npcs[i]; var dx = npc.x - player.x; var dy = npc.y - player.y; var dist = dx * dx + dy * dy; if (dist < 300 * 300 && dist < minDist) { nearest = npc; minDist = dist; } npc.hideHighlight(); } // Memory Fragments for (var i = 0; i < memoryFragments.length; ++i) { var frag = memoryFragments[i]; if (frag.collected) continue; var dx = frag.x - player.x; var dy = frag.y - player.y; var dist = dx * dx + dy * dy; if (dist < 180 * 180 && dist < minDist) { nearest = frag; minDist = dist; } frag.hideHighlight(); } // Door if (foundFragments === totalFragments) { for (var i = 0; i < doors.length; ++i) { var door = doors[i]; var dx = door.x - player.x; var dy = door.y - player.y; var dist = dx * dx + dy * dy; if (dist < 220 * 220 && dist < minDist) { nearest = door; minDist = dist; } door.hideHighlight(); } } // Show highlight if (nearest && nearest.showHighlight) nearest.showHighlight(); // Store last near object lastNearObject = nearest; };
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,519 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ ending: 0,
+ foundFragments: 0
+});
+
+/****
+* Classes
+****/
+// Door class (scene transition)
+var Door = Container.expand(function () {
+ var self = Container.call(this);
+ var sprite = self.attachAsset('door', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.targetScene = "";
+ self.highlight = null;
+ self.showHighlight = function () {
+ if (!self.highlight) {
+ self.highlight = self.attachAsset('highlight', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.10
+ });
+ }
+ self.highlight.visible = true;
+ };
+ self.hideHighlight = function () {
+ if (self.highlight) self.highlight.visible = false;
+ };
+ return self;
+});
+// Memory Fragment class
+var MemoryFragment = Container.expand(function () {
+ var self = Container.call(this);
+ var sprite = self.attachAsset('memoryFragment', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.collected = false;
+ self.highlight = null;
+ self.showHighlight = function () {
+ if (!self.highlight) {
+ self.highlight = self.attachAsset('highlight', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.13
+ });
+ }
+ self.highlight.visible = true;
+ };
+ self.hideHighlight = function () {
+ if (self.highlight) self.highlight.visible = false;
+ };
+ return self;
+});
+// NPC class
+var NPC = Container.expand(function () {
+ var self = Container.call(this);
+ var sprite = self.attachAsset('npc', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.dialogue = [];
+ self.dialogueIndex = 0;
+ self.name = "";
+ self.interacted = false;
+ self.highlight = null;
+ // Show highlight when player is near
+ self.showHighlight = function () {
+ if (!self.highlight) {
+ self.highlight = self.attachAsset('highlight', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.18
+ });
+ }
+ self.highlight.visible = true;
+ };
+ self.hideHighlight = function () {
+ if (self.highlight) self.highlight.visible = false;
+ };
+ return self;
+});
+// Player class
+var Player = Container.expand(function () {
+ var self = Container.call(this);
+ var sprite = self.attachAsset('player', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 18;
+ self.targetX = self.x;
+ self.targetY = self.y;
+ self.moving = false;
+ // Move towards target
+ self.update = function () {
+ if (!self.moving) return;
+ var dx = self.targetX - self.x;
+ var dy = self.targetY - self.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist < self.speed) {
+ self.x = self.targetX;
+ self.y = self.targetY;
+ self.moving = false;
+ } else {
+ self.x += self.speed * dx / dist;
+ self.y += self.speed * dy / dist;
+ }
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0xfaf7f2
+});
+
+/****
+* Game Code
+****/
+/*
+We use simple shapes for the sketchbook-like look.
+- 'player': the protagonist, a hand-drawn ellipse.
+- 'npc': townsfolk, a box with a different color.
+- 'memoryFragment': symbolic puzzle piece, a star-shaped box.
+- 'door': a rectangle for scene transitions.
+- 'bgTown': a large, pale rectangle as the background.
+- 'highlight': a transparent overlay for interactable objects.
+*/
+// --- State ---
+var player;
+var npcs = [];
+var memoryFragments = [];
+var doors = [];
+var currentScene = "town";
+var dialogueBox = null;
+var dialogueText = null;
+var choiceButtons = [];
+var infoText = null;
+var canMove = true;
+var lastNearObject = null;
+var foundFragments = storage.foundFragments || 0;
+var totalFragments = 3;
+var ending = storage.ending || 0;
+// --- GUI ---
+function showInfo(msg, duration) {
+ if (!infoText) {
+ infoText = new Text2(msg, {
+ size: 80,
+ fill: 0x444444
+ });
+ infoText.anchor.set(0.5, 0);
+ LK.gui.top.addChild(infoText);
+ }
+ infoText.setText(msg);
+ infoText.visible = true;
+ if (duration) {
+ LK.setTimeout(function () {
+ if (infoText) infoText.visible = false;
+ }, duration);
+ }
+}
+// --- Scene Setup ---
+function setupTownScene() {
+ // Clear previous
+ game.removeChildren();
+ npcs = [];
+ memoryFragments = [];
+ doors = [];
+ lastNearObject = null;
+ // Background
+ var bg = LK.getAsset('bgTown', {
+ anchorX: 0,
+ anchorY: 0,
+ x: 0,
+ y: 0
+ });
+ game.addChild(bg);
+ // Player
+ player = new Player();
+ player.x = 1024;
+ player.y = 2000;
+ game.addChild(player);
+ // NPCs
+ var npc1 = new NPC();
+ npc1.x = 700;
+ npc1.y = 1500;
+ npc1.name = "Caretaker";
+ npc1.dialogue = ["You look lost. The town remembers you, even if you don't remember it.", "Find the fragments of your memory. They are hidden in plain sight.", "Come back when you remember more."];
+ npcs.push(npc1);
+ game.addChild(npc1);
+ var npc2 = new NPC();
+ npc2.x = 1400;
+ npc2.y = 1100;
+ npc2.name = "Child";
+ npc2.dialogue = ["Will you play with me? Or are you too busy remembering?", "Sometimes, forgetting is easier than facing the truth."];
+ npcs.push(npc2);
+ game.addChild(npc2);
+ // Memory Fragments
+ var frag1 = new MemoryFragment();
+ frag1.x = 400;
+ frag1.y = 800;
+ memoryFragments.push(frag1);
+ game.addChild(frag1);
+ var frag2 = new MemoryFragment();
+ frag2.x = 1700;
+ frag2.y = 1800;
+ memoryFragments.push(frag2);
+ game.addChild(frag2);
+ var frag3 = new MemoryFragment();
+ frag3.x = 1200;
+ frag3.y = 2500;
+ memoryFragments.push(frag3);
+ game.addChild(frag3);
+ // Door to ending
+ var door = new Door();
+ door.x = 1024;
+ door.y = 400;
+ door.targetScene = "ending";
+ doors.push(door);
+ game.addChild(door);
+ // Show info
+ showInfo("Explore the town. Tap to move. Find your memories.", 3000);
+}
+// --- Dialogue System ---
+function showDialogue(npc) {
+ canMove = false;
+ if (!dialogueBox) {
+ dialogueBox = new Container();
+ var box = LK.getAsset('bgTown', {
+ width: 1600,
+ height: 400,
+ color: 0xffffff,
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 1024,
+ y: 2200
+ });
+ box.alpha = 0.92;
+ dialogueBox.addChild(box);
+ dialogueText = new Text2("", {
+ size: 70,
+ fill: 0x222222
+ });
+ dialogueText.anchor.set(0.5, 0.5);
+ dialogueText.x = 1024;
+ dialogueText.y = 2200;
+ dialogueBox.addChild(dialogueText);
+ LK.gui.bottom.addChild(dialogueBox);
+ }
+ dialogueBox.visible = true;
+ dialogueText.setText(npc.name + ": " + npc.dialogue[npc.dialogueIndex]);
+ // Next dialogue on tap
+ dialogueBox.down = function (x, y, obj) {
+ npc.dialogueIndex++;
+ if (npc.dialogueIndex >= npc.dialogue.length) {
+ npc.dialogueIndex = 0;
+ dialogueBox.visible = false;
+ canMove = true;
+ } else {
+ dialogueText.setText(npc.name + ": " + npc.dialogue[npc.dialogueIndex]);
+ }
+ LK.getSound('choice').play();
+ };
+}
+// --- Choice System ---
+function showChoice(msg, choices, onSelect) {
+ canMove = false;
+ // Remove old
+ for (var i = 0; i < choiceButtons.length; ++i) {
+ if (choiceButtons[i].parent) choiceButtons[i].parent.removeChild(choiceButtons[i]);
+ }
+ choiceButtons = [];
+ // Message
+ if (!dialogueBox) {
+ dialogueBox = new Container();
+ var box = LK.getAsset('bgTown', {
+ width: 1600,
+ height: 400,
+ color: 0xffffff,
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 1024,
+ y: 2200
+ });
+ box.alpha = 0.92;
+ dialogueBox.addChild(box);
+ dialogueText = new Text2("", {
+ size: 70,
+ fill: 0x222222
+ });
+ dialogueText.anchor.set(0.5, 0.5);
+ dialogueText.x = 1024;
+ dialogueText.y = 2200;
+ dialogueBox.addChild(dialogueText);
+ LK.gui.bottom.addChild(dialogueBox);
+ }
+ dialogueBox.visible = true;
+ dialogueText.setText(msg);
+ // Buttons
+ for (var i = 0; i < choices.length; ++i) {
+ var btn = new Text2(choices[i], {
+ size: 70,
+ fill: 0x3A3A3A
+ });
+ btn.anchor.set(0.5, 0.5);
+ btn.x = 1024;
+ btn.y = 2400 + i * 120;
+ btn.interactive = true;
+ (function (idx) {
+ btn.down = function (x, y, obj) {
+ dialogueBox.visible = false;
+ for (var j = 0; j < choiceButtons.length; ++j) {
+ if (choiceButtons[j].parent) choiceButtons[j].parent.removeChild(choiceButtons[j]);
+ }
+ choiceButtons = [];
+ canMove = true;
+ LK.getSound('choice').play();
+ onSelect(idx);
+ };
+ })(i);
+ LK.gui.bottom.addChild(btn);
+ choiceButtons.push(btn);
+ }
+}
+// --- Memory Fragment Collection ---
+function collectFragment(fragment) {
+ if (fragment.collected) return;
+ fragment.collected = true;
+ foundFragments++;
+ storage.foundFragments = foundFragments;
+ LK.getSound('memoryFound').play();
+ tween(fragment, {
+ alpha: 0,
+ scaleX: 2,
+ scaleY: 2
+ }, {
+ duration: 600,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ if (fragment.parent) fragment.parent.removeChild(fragment);
+ }
+ });
+ showInfo("You found a memory fragment! (" + foundFragments + "/" + totalFragments + ")", 2000);
+ if (foundFragments === totalFragments) {
+ showInfo("All fragments found. The door is open.", 3000);
+ }
+}
+// --- Ending Scene ---
+function setupEndingScene() {
+ game.removeChildren();
+ if (dialogueBox) dialogueBox.visible = false;
+ for (var i = 0; i < choiceButtons.length; ++i) {
+ if (choiceButtons[i].parent) choiceButtons[i].parent.removeChild(choiceButtons[i]);
+ }
+ choiceButtons = [];
+ // Background
+ var bg = LK.getAsset('bgTown', {
+ anchorX: 0,
+ anchorY: 0,
+ x: 0,
+ y: 0,
+ color: 0xeaeaea
+ });
+ game.addChild(bg);
+ // Ending text
+ var endingText = new Text2("", {
+ size: 110,
+ fill: 0x222222
+ });
+ endingText.anchor.set(0.5, 0.5);
+ endingText.x = 1024;
+ endingText.y = 1200;
+ if (foundFragments === totalFragments) {
+ endingText.setText("You remember everything.\nThe town is at peace.\n\nThank you for playing.");
+ storage.ending = 2;
+ } else if (foundFragments > 0) {
+ endingText.setText("Some memories return, but many are lost.\nThe town remains a mystery.\n\nThank you for playing.");
+ storage.ending = 1;
+ } else {
+ endingText.setText("You leave, still lost.\nThe town fades behind you.\n\nThank you for playing.");
+ storage.ending = 0;
+ }
+ game.addChild(endingText);
+ // Show "You Win" after a short delay
+ LK.setTimeout(function () {
+ LK.showYouWin();
+ }, 2500);
+}
+// --- Music ---
+LK.playMusic('dream', {
+ fade: {
+ start: 0,
+ end: 0.7,
+ duration: 1200
+ }
+});
+// --- Start Scene ---
+setupTownScene();
+// --- Game Move Handler ---
+game.move = function (x, y, obj) {
+ if (!canMove) return;
+ // Prevent moving into top left menu area
+ if (x < 100 && y < 100) return;
+ // Move player
+ player.targetX = x;
+ player.targetY = y;
+ player.moving = true;
+};
+// --- Game Down Handler (for interaction) ---
+game.down = function (x, y, obj) {
+ if (!canMove) return;
+ // Check for nearby interactables
+ var nearObj = null;
+ // NPCs
+ for (var i = 0; i < npcs.length; ++i) {
+ var npc = npcs[i];
+ var dx = npc.x - player.x;
+ var dy = npc.y - player.y;
+ if (dx * dx + dy * dy < 300 * 300) {
+ nearObj = npc;
+ break;
+ }
+ }
+ // Memory Fragments
+ if (!nearObj) {
+ for (var i = 0; i < memoryFragments.length; ++i) {
+ var frag = memoryFragments[i];
+ if (frag.collected) continue;
+ var dx = frag.x - player.x;
+ var dy = frag.y - player.y;
+ if (dx * dx + dy * dy < 180 * 180) {
+ nearObj = frag;
+ break;
+ }
+ }
+ }
+ // Door
+ if (!nearObj && foundFragments === totalFragments) {
+ for (var i = 0; i < doors.length; ++i) {
+ var door = doors[i];
+ var dx = door.x - player.x;
+ var dy = door.y - player.y;
+ if (dx * dx + dy * dy < 220 * 220) {
+ nearObj = door;
+ break;
+ }
+ }
+ }
+ // Interact
+ if (nearObj) {
+ if (nearObj instanceof NPC) {
+ showDialogue(nearObj);
+ } else if (nearObj instanceof MemoryFragment) {
+ collectFragment(nearObj);
+ } else if (nearObj instanceof Door) {
+ // Ending
+ setupEndingScene();
+ }
+ }
+};
+// --- Game Update ---
+game.update = function () {
+ // Player update
+ if (player && player.update) player.update();
+ // Highlight nearby interactables
+ var nearest = null;
+ var minDist = 99999;
+ // NPCs
+ for (var i = 0; i < npcs.length; ++i) {
+ var npc = npcs[i];
+ var dx = npc.x - player.x;
+ var dy = npc.y - player.y;
+ var dist = dx * dx + dy * dy;
+ if (dist < 300 * 300 && dist < minDist) {
+ nearest = npc;
+ minDist = dist;
+ }
+ npc.hideHighlight();
+ }
+ // Memory Fragments
+ for (var i = 0; i < memoryFragments.length; ++i) {
+ var frag = memoryFragments[i];
+ if (frag.collected) continue;
+ var dx = frag.x - player.x;
+ var dy = frag.y - player.y;
+ var dist = dx * dx + dy * dy;
+ if (dist < 180 * 180 && dist < minDist) {
+ nearest = frag;
+ minDist = dist;
+ }
+ frag.hideHighlight();
+ }
+ // Door
+ if (foundFragments === totalFragments) {
+ for (var i = 0; i < doors.length; ++i) {
+ var door = doors[i];
+ var dx = door.x - player.x;
+ var dy = door.y - player.y;
+ var dist = dx * dx + dy * dy;
+ if (dist < 220 * 220 && dist < minDist) {
+ nearest = door;
+ minDist = dist;
+ }
+ door.hideHighlight();
+ }
+ }
+ // Show highlight
+ if (nearest && nearest.showHighlight) nearest.showHighlight();
+ // Store last near object
+ lastNearObject = nearest;
+};
\ No newline at end of file
a bullet. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
an angry character that has a soldier hat on his head. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a pixel art coin. In-Game asset. 2d. High contrast. No shadows
a pixel war background. In-Game asset. 2d. High contrast. No shadows
an enemy that smiles evilly. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat