User prompt
Now finish the game until it’s done
User prompt
Just add things that you think are good for the game until it’s done
User prompt
And that’s it
User prompt
and make the school dark but as light as the player can see the hallways
Code edit (1 edits merged)
Please save this source code
User prompt
Escape from Flumbo Jumbo
Initial prompt
Make a horror game where there is a monster named flumbo jumbo and you are in a school a abandoned one you have to collect 7 notebooks scattered around the school to escape when you escape there will be a cutscene of you going to the soft place center and that will be the end of the chapter’ and flumbo jumbo is blind’ if you make ANY sudden noise he will growl bang his chest and run to the noise when he growls there will be an adjective saying RUN AND GO FIND A LOCKER!! You have to go to the locker and hide in it and at the end flumbo jumbo will growl and suddenly his vision is better and he can see and when that happens the adjective will say HE IS NOT BLIND!!’ And you have to run to 6 exits of the school every exit will close except for the last one which is the 6th one and you slide through and then another cutscene comes and it shows him running and getting crushed by the exit door.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); var facekit = LK.import("@upit/facekit.v1"); /**** * Classes ****/ var DarknessMask = Container.expand(function () { var self = Container.call(this); // Create a dark overlay that covers the entire screen var darkness = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, width: 2048, height: 2732, alpha: 0.8, tint: 0x000000 }); // Scale to cover the entire screen darkness.width = 2048; darkness.height = 2732; self.addChild(darkness); // Create a visible circle around player (light effect) self.lightRadius = 300; // Visibility radius around player self.updatePosition = function (playerX, playerY) { self.x = 2048 / 2; self.y = 2732 / 2; // Create a mask using a circle asset at player's position if (!self.mask) { // Create a circle mask using a shape asset instead of Graphics self.mask = self.addChild(LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, width: self.lightRadius * 2, height: self.lightRadius * 2, tint: 0xFFFFFF })); } // Update mask position self.mask.x = playerX - self.x; self.mask.y = playerY - self.y; // Ensure mask size matches the desired light radius self.mask.width = self.lightRadius * 2; self.mask.height = self.lightRadius * 2; }; return self; }); var Exit = Container.expand(function () { var self = Container.call(this); var exitSprite = self.attachAsset('exit', { anchorX: 0.5, anchorY: 0.5 }); // Initially exits are inactive exitSprite.alpha = 0.3; self.activate = function () { exitSprite.alpha = 1; // Make the exit slightly pulse to draw attention function pulse() { tween(exitSprite, { scaleX: 1.2, scaleY: 1.2 }, { duration: 700, easing: tween.easeInOut, onFinish: function onFinish() { tween(exitSprite, { scaleX: 1, scaleY: 1 }, { duration: 700, easing: tween.easeInOut, onFinish: pulse }); } }); } pulse(); }; return self; }); var Locker = Container.expand(function () { var self = Container.call(this); var lockerSprite = self.attachAsset('locker', { anchorX: 0.5, anchorY: 0.5 }); self.isOccupied = false; return self; }); var Monster = Container.expand(function () { var self = Container.call(this); var monsterSprite = self.attachAsset('monster', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 2; self.detectionRadius = 400; self.hasSight = false; self.targetX = 0; self.targetY = 0; self.isChasing = false; self.wanderTimer = 0; self.wanderDirection = { x: 0, y: 0 }; self.setHasSight = function (value) { self.hasSight = value; if (value) { tween(monsterSprite, { tint: 0xFF00FF }, { duration: 1000 }); self.speed = 3; // Show "HE IS NOT BLIND!!" message when monster gains sight if (instructionText) { instructionText.setText('HE IS NOT BLIND!!'); instructionText.style.fill = "#FF0000"; // Flash the screen to indicate danger LK.effects.flashScreen(0xFF0000, 500); } } }; self.startChasing = function (x, y) { self.isChasing = true; self.targetX = x; self.targetY = y; LK.getSound('monster_detect').play(); // Monster growls and bangs chest function bangChest() { tween(monsterSprite, { scaleX: 1.3, scaleY: 1.3, tint: 0xFF3300 }, { duration: 200, onFinish: function onFinish() { tween(monsterSprite, { scaleX: 1.0, scaleY: 1.0, tint: 0xFF0000 }, { duration: 200, onFinish: function onFinish() { if (self.isChasing && LK.ticks % 2 === 0) { bangChest(); } } }); } }); } bangChest(); }; self.stopChasing = function () { self.isChasing = false; }; self.wander = function () { if (LK.ticks % 120 === 0 || self.wanderTimer <= 0) { // Pick a random direction var angle = Math.random() * Math.PI * 2; self.wanderDirection = { x: Math.cos(angle), y: Math.sin(angle) }; self.wanderTimer = 60 + Math.random() * 120; } self.x += self.wanderDirection.x * (self.speed * 0.5); self.y += self.wanderDirection.y * (self.speed * 0.5); // Boundary checks if (self.x < 100) self.x = 100; if (self.x > 2048 - 100) self.x = 2048 - 100; if (self.y < 100) self.y = 100; if (self.y > 2732 - 100) self.y = 2732 - 100; self.wanderTimer--; }; self.moveTowardsTarget = function () { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } }; self.update = function () { if (self.isChasing) { self.moveTowardsTarget(); } else { self.wander(); } }; return self; }); var Notebook = Container.expand(function () { var self = Container.call(this); var notebookSprite = self.attachAsset('notebook', { anchorX: 0.5, anchorY: 0.5 }); // Make the notebook slightly pulse to draw attention function pulse() { tween(notebookSprite, { scaleX: 1.1, scaleY: 1.1 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { tween(notebookSprite, { scaleX: 1, scaleY: 1 }, { duration: 1000, easing: tween.easeInOut, onFinish: pulse }); } }); } pulse(); return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerSprite = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 4; self.isHidden = false; self.noiseLevel = 0; self.notebooksCollected = 0; self.makeNoise = function (amount) { self.noiseLevel = Math.min(1, self.noiseLevel + amount); // Noise decreases over time LK.setTimeout(function () { self.noiseLevel = Math.max(0, self.noiseLevel - 0.1); }, 1000); }; self.hide = function () { if (!self.isHidden) { self.isHidden = true; playerSprite.alpha = 0.3; LK.getSound('hide').play(); } }; self.unhide = function () { if (self.isHidden) { self.isHidden = false; playerSprite.alpha = 1; } }; self.update = function () { // Player visibility logic is handled in the main game update if (self.isMoving && !self.isHidden) { if (LK.ticks % 20 === 0) { LK.getSound('footstep').play(); self.makeNoise(0.15); } } }; return self; }); var Wall = Container.expand(function () { var self = Container.call(this); self.attachAsset('wall', { anchorX: 0.5, anchorY: 0.5 }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x050505 }); /**** * Game Code ****/ // Game variables var player; var monster; var notebooks = []; var lockers = []; var exits = []; var walls = []; var notebooksRequired = 7; var lastTouchedLocker = null; var gamePhase = "collecting"; // collecting, escaping // UI elements var notebookCounter; var noiseIndicator; var instructionText; // Create the UI function setupUI() { // Notebook counter notebookCounter = new Text2('0/' + notebooksRequired, { size: 80, fill: 0xFFD700 }); notebookCounter.anchor.set(1, 0); LK.gui.topRight.addChild(notebookCounter); // Noise indicator noiseIndicator = new Text2('Noise: ●', { size: 60, fill: 0x00FF00 }); noiseIndicator.anchor.set(0, 0); LK.gui.topRight.addChild(noiseIndicator); noiseIndicator.y = 100; // Instruction text instructionText = new Text2('Find and collect 7 notebooks to escape!', { size: 50, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 0); LK.gui.top.addChild(instructionText); instructionText.y = 20; } // Generate a random position that isn't too close to existing objects function getRandomPosition(minDistance) { var x, y; var validPosition = false; while (!validPosition) { x = 150 + Math.random() * (2048 - 300); y = 150 + Math.random() * (2732 - 300); validPosition = true; // Check distance from player if (player) { var dxPlayer = x - player.x; var dyPlayer = y - player.y; var distPlayer = Math.sqrt(dxPlayer * dxPlayer + dyPlayer * dyPlayer); if (distPlayer < minDistance) { validPosition = false; continue; } } // Check distance from other notebooks for (var i = 0; i < notebooks.length; i++) { var dxNote = x - notebooks[i].x; var dyNote = y - notebooks[i].y; var distNote = Math.sqrt(dxNote * dxNote + dyNote * dyNote); if (distNote < minDistance) { validPosition = false; break; } } // Check distance from lockers for (var j = 0; j < lockers.length; j++) { var dxLocker = x - lockers[j].x; var dyLocker = y - lockers[j].y; var distLocker = Math.sqrt(dxLocker * dxLocker + dyLocker * dyLocker); if (distLocker < minDistance) { validPosition = false; break; } } } return { x: x, y: y }; } // Generate the game level function setupLevel() { // Create player player = new Player(); player.x = 2048 / 2; player.y = 2732 / 2; game.addChild(player); // Add darkness overlay with light around player var darknessMask = new DarknessMask(); darknessMask.updatePosition(player.x, player.y); game.addChild(darknessMask); // Create monster monster = new Monster(); monster.x = 300; monster.y = 300; game.addChild(monster); // Create notebooks for (var i = 0; i < notebooksRequired; i++) { var pos = getRandomPosition(300); var notebook = new Notebook(); notebook.x = pos.x; notebook.y = pos.y; notebooks.push(notebook); game.addChild(notebook); } // Create lockers var lockerCount = 12; for (var j = 0; j < lockerCount; j++) { var lockerPos = getRandomPosition(250); var locker = new Locker(); locker.x = lockerPos.x; locker.y = lockerPos.y; lockers.push(locker); game.addChild(locker); } // Create exits (initially inactive) var exitPositions = [{ x: 100, y: 100 }, { x: 2048 - 100, y: 100 }, { x: 2048 / 2, y: 100 }, { x: 100, y: 2732 - 100 }, { x: 2048 - 100, y: 2732 - 100 }, { x: 2048 / 2, y: 2732 - 100 }]; for (var k = 0; k < exitPositions.length; k++) { var exit = new Exit(); exit.x = exitPositions[k].x; exit.y = exitPositions[k].y; exits.push(exit); game.addChild(exit); } } // Start the game function startGame() { setupUI(); setupLevel(); // Play ambient music LK.playMusic('ambient'); } // Input handling var isDragging = false; var lastTouchX = 0; var lastTouchY = 0; game.down = function (x, y, obj) { isDragging = true; lastTouchX = x; lastTouchY = y; }; game.up = function (x, y, obj) { isDragging = false; player.isMoving = false; }; game.move = function (x, y, obj) { if (isDragging && !player.isHidden) { // Calculate direction and distance var dx = x - lastTouchX; var dy = y - lastTouchY; var distance = Math.sqrt(dx * dx + dy * dy); // Only move if there's significant movement if (distance > 5) { player.isMoving = true; player.x += dx * 0.5; player.y += dy * 0.5; // Keep player in bounds if (player.x < 50) player.x = 50; if (player.x > 2048 - 50) player.x = 2048 - 50; if (player.y < 50) player.y = 50; if (player.y > 2732 - 50) player.y = 2732 - 50; // Update last position lastTouchX = x; lastTouchY = y; } else { player.isMoving = false; } } }; // Update game state game.update = function () { if (!player) { startGame(); return; } // Update noise indicator if (player.noiseLevel < 0.3) { noiseIndicator.setText('Noise: ●'); noiseIndicator.style.fill = "#00FF00"; } else if (player.noiseLevel < 0.7) { noiseIndicator.setText('Noise: ●●'); noiseIndicator.style.fill = "#FFFF00"; } else { noiseIndicator.setText('Noise: ●●●'); noiseIndicator.style.fill = "#FF0000"; } // Check for notebook collection for (var i = notebooks.length - 1; i >= 0; i--) { var notebook = notebooks[i]; if (player.intersects(notebook) && !player.isHidden) { // Remove the notebook notebook.destroy(); notebooks.splice(i, 1); // Update player stats player.notebooksCollected++; notebookCounter.setText(player.notebooksCollected + '/' + notebooksRequired); // Play sound LK.getSound('pickup').play(); // Make some noise when collecting player.makeNoise(0.3); // Check if all notebooks are collected if (player.notebooksCollected >= notebooksRequired) { gamePhase = "escaping"; instructionText.setText('All notebooks collected! Find an exit before Flumbo catches you!'); monster.setHasSight(true); // Only activate the last exit (6th one) as instructed // The other exits should be visible but closed for (var e = 0; e < exits.length; e++) { if (e === exits.length - 1) { // Activate only the last exit exits[e].activate(); } else { // Make other exits visible but not usable var exitSprite = exits[e].children[0]; exitSprite.alpha = 0.5; exitSprite.tint = 0x880000; // Red tint to indicate closed } } } } } // Check for hiding in lockers var nearLocker = false; for (var j = 0; j < lockers.length; j++) { var locker = lockers[j]; var dxLocker = player.x - locker.x; var dyLocker = player.y - locker.y; var distLocker = Math.sqrt(dxLocker * dxLocker + dyLocker * dyLocker); if (distLocker < 100 && !locker.isOccupied) { nearLocker = true; lastTouchedLocker = locker; // Double tap or tap when monster is chasing to hide if (isDragging && (monster.isChasing || LK.ticks % 30 === 0)) { player.hide(); player.x = locker.x; player.y = locker.y; locker.isOccupied = true; break; } } } // Allow player to exit locker when not being chased if (player.isHidden && !monster.isChasing && isDragging) { player.unhide(); if (lastTouchedLocker) { lastTouchedLocker.isOccupied = false; } } // Check for reaching an exit in escape phase if (gamePhase === "escaping") { for (var k = 0; k < exits.length; k++) { var exit = exits[k]; if (player.intersects(exit) && !player.isHidden) { // Check if this is the last exit (the only open one) if (k === exits.length - 1) { // Play escape cutscene player.isHidden = true; // Prevent further interaction monster.isChasing = true; monster.targetX = player.x; monster.targetY = player.y; // Player slides through the exit tween(player, { x: exit.x, y: exit.y, alpha: 0.5, scaleX: 0.5, scaleY: 0.5 }, { duration: 1000, onFinish: function onFinish() { // Monster gets crushed by the door tween(monster, { x: exit.x, y: exit.y }, { duration: 800, onFinish: function onFinish() { LK.effects.flashScreen(0xFF0000, 300); // Flatten monster to show crushing tween(monster.children[0], { scaleY: 0.2, scaleX: 1.5, alpha: 0.5 }, { duration: 500, onFinish: function onFinish() { // Show "soft place center" message instructionText.setText("You've escaped to the soft place center! Chapter complete."); instructionText.style.fill = "#00FF00"; LK.setTimeout(function () { LK.showYouWin(); }, 2000); } }); } }); } }); return; } else { // Closed exit - monster gets angrier LK.effects.flashScreen(0xFF0000, 300); monster.speed += 0.5; monster.startChasing(player.x, player.y); } } } } // Monster detection var dxMonster = monster.x - player.x; var dyMonster = monster.y - player.y; var distMonster = Math.sqrt(dxMonster * dxMonster + dyMonster * dyMonster); // Monster detects player based on noise if (!player.isHidden && distMonster < monster.detectionRadius * player.noiseLevel) { monster.startChasing(player.x, player.y); // Show warning message as instructed instructionText.setText('RUN AND GO FIND A LOCKER!!'); instructionText.style.fill = "#FF0000"; } // Monster can see player in the final phase else if (gamePhase === "escaping" && monster.hasSight && !player.isHidden && distMonster < monster.detectionRadius * 1.5) { monster.startChasing(player.x, player.y); } // Update monster's target position if already chasing else if (monster.isChasing && !player.isHidden) { monster.targetX = player.x; monster.targetY = player.y; } // Stop chasing if player is hidden else if (player.isHidden && monster.isChasing) { LK.setTimeout(function () { monster.stopChasing(); }, 1500); } // Stop chasing if lost track for too long else if (monster.isChasing && LK.ticks % 180 === 0) { monster.stopChasing(); } // Update darkness mask to follow player for (var i = 0; i < game.children.length; i++) { if (game.children[i] instanceof DarknessMask) { game.children[i].updatePosition(player.x, player.y); break; } } // Check for player caught by monster if (!player.isHidden && player.intersects(monster)) { // Flash the screen red LK.effects.flashScreen(0xFF0000, 500); // Game over LK.showGameOver(); } };
===================================================================
--- original.js
+++ change.js
@@ -27,16 +27,25 @@
self.lightRadius = 300; // Visibility radius around player
self.updatePosition = function (playerX, playerY) {
self.x = 2048 / 2;
self.y = 2732 / 2;
- // Create a mask using a circle at player's position
+ // Create a mask using a circle asset at player's position
if (!self.mask) {
- self.mask = new Graphics();
+ // Create a circle mask using a shape asset instead of Graphics
+ self.mask = self.addChild(LK.getAsset('centerCircle', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: self.lightRadius * 2,
+ height: self.lightRadius * 2,
+ tint: 0xFFFFFF
+ }));
}
- self.mask.clear();
- self.mask.beginFill(0xFFFFFF);
- self.mask.drawCircle(playerX - self.x, playerY - self.y, self.lightRadius);
- self.mask.endFill();
+ // Update mask position
+ self.mask.x = playerX - self.x;
+ self.mask.y = playerY - self.y;
+ // Ensure mask size matches the desired light radius
+ self.mask.width = self.lightRadius * 2;
+ self.mask.height = self.lightRadius * 2;
};
return self;
});
var Exit = Container.expand(function () {
@@ -107,27 +116,47 @@
}, {
duration: 1000
});
self.speed = 3;
+ // Show "HE IS NOT BLIND!!" message when monster gains sight
+ if (instructionText) {
+ instructionText.setText('HE IS NOT BLIND!!');
+ instructionText.style.fill = "#FF0000";
+ // Flash the screen to indicate danger
+ LK.effects.flashScreen(0xFF0000, 500);
+ }
}
};
self.startChasing = function (x, y) {
self.isChasing = true;
self.targetX = x;
self.targetY = y;
LK.getSound('monster_detect').play();
- tween(monsterSprite, {
- tint: 0xFF3300
- }, {
- duration: 400,
- onFinish: function onFinish() {
- tween(monsterSprite, {
- tint: 0xFF0000
- }, {
- duration: 400
- });
- }
- });
+ // Monster growls and bangs chest
+ function bangChest() {
+ tween(monsterSprite, {
+ scaleX: 1.3,
+ scaleY: 1.3,
+ tint: 0xFF3300
+ }, {
+ duration: 200,
+ onFinish: function onFinish() {
+ tween(monsterSprite, {
+ scaleX: 1.0,
+ scaleY: 1.0,
+ tint: 0xFF0000
+ }, {
+ duration: 200,
+ onFinish: function onFinish() {
+ if (self.isChasing && LK.ticks % 2 === 0) {
+ bangChest();
+ }
+ }
+ });
+ }
+ });
+ }
+ bangChest();
};
self.stopChasing = function () {
self.isChasing = false;
};
@@ -483,11 +512,20 @@
if (player.notebooksCollected >= notebooksRequired) {
gamePhase = "escaping";
instructionText.setText('All notebooks collected! Find an exit before Flumbo catches you!');
monster.setHasSight(true);
- // Activate all exits
+ // Only activate the last exit (6th one) as instructed
+ // The other exits should be visible but closed
for (var e = 0; e < exits.length; e++) {
- exits[e].activate();
+ if (e === exits.length - 1) {
+ // Activate only the last exit
+ exits[e].activate();
+ } else {
+ // Make other exits visible but not usable
+ var exitSprite = exits[e].children[0];
+ exitSprite.alpha = 0.5;
+ exitSprite.tint = 0x880000; // Red tint to indicate closed
+ }
}
}
}
}
@@ -522,11 +560,60 @@
if (gamePhase === "escaping") {
for (var k = 0; k < exits.length; k++) {
var exit = exits[k];
if (player.intersects(exit) && !player.isHidden) {
- // Player has escaped!
- LK.showYouWin();
- return;
+ // Check if this is the last exit (the only open one)
+ if (k === exits.length - 1) {
+ // Play escape cutscene
+ player.isHidden = true; // Prevent further interaction
+ monster.isChasing = true;
+ monster.targetX = player.x;
+ monster.targetY = player.y;
+ // Player slides through the exit
+ tween(player, {
+ x: exit.x,
+ y: exit.y,
+ alpha: 0.5,
+ scaleX: 0.5,
+ scaleY: 0.5
+ }, {
+ duration: 1000,
+ onFinish: function onFinish() {
+ // Monster gets crushed by the door
+ tween(monster, {
+ x: exit.x,
+ y: exit.y
+ }, {
+ duration: 800,
+ onFinish: function onFinish() {
+ LK.effects.flashScreen(0xFF0000, 300);
+ // Flatten monster to show crushing
+ tween(monster.children[0], {
+ scaleY: 0.2,
+ scaleX: 1.5,
+ alpha: 0.5
+ }, {
+ duration: 500,
+ onFinish: function onFinish() {
+ // Show "soft place center" message
+ instructionText.setText("You've escaped to the soft place center! Chapter complete.");
+ instructionText.style.fill = "#00FF00";
+ LK.setTimeout(function () {
+ LK.showYouWin();
+ }, 2000);
+ }
+ });
+ }
+ });
+ }
+ });
+ return;
+ } else {
+ // Closed exit - monster gets angrier
+ LK.effects.flashScreen(0xFF0000, 300);
+ monster.speed += 0.5;
+ monster.startChasing(player.x, player.y);
+ }
}
}
}
// Monster detection
@@ -535,8 +622,11 @@
var distMonster = Math.sqrt(dxMonster * dxMonster + dyMonster * dyMonster);
// Monster detects player based on noise
if (!player.isHidden && distMonster < monster.detectionRadius * player.noiseLevel) {
monster.startChasing(player.x, player.y);
+ // Show warning message as instructed
+ instructionText.setText('RUN AND GO FIND A LOCKER!!');
+ instructionText.style.fill = "#FF0000";
}
// Monster can see player in the final phase
else if (gamePhase === "escaping" && monster.hasSight && !player.isHidden && distMonster < monster.detectionRadius * 1.5) {
monster.startChasing(player.x, player.y);
Make a mascot evil creature. In-Game asset. 2d. High contrast. No shadows
A dirty notebook like it was in a abandoned school. In-Game asset. 2d. High contrast. No shadows
Make a scary dark locker that is blue and make it like it was in a abandoned school. In-Game asset. 2d. High contrast. No shadows
Make a wall like it was in a abandoned school. In-Game asset. 2d. High contrast. No shadows
Make a door with a white wall like it was in an abandoned school on top of the door is a glowing red exit sign. In-Game asset. 2d. High contrast. No shadows
Make a centercircle in an abandoned school. In-Game asset. 2d. High contrast. No shadows