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.85, 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 = 250; // Reduced visibility radius for more tension self.adjustLightRadius = function (playerNoiseLevel) { // Light shrinks when making noise (harder to see when noisy) var targetRadius = 250 - playerNoiseLevel * 80; // Smooth transition with tween tween(self, { lightRadius: targetRadius }, { duration: 500 }); }; 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, shape: 'ellipse' })); } // 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(); // Increase speed temporarily during initial chase self.speed = self.speed * 1.5; LK.setTimeout(function () { if (self.isChasing) { self.speed = self.speed / 1.5; } }, 3000); // 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; // Sometimes patrol near a locker if (Math.random() < 0.3 && lockers && lockers.length > 0) { // Target a random locker var randomLocker = lockers[Math.floor(Math.random() * lockers.length)]; self.targetX = randomLocker.x; self.targetY = randomLocker.y; // Move toward locker for a while LK.setTimeout(function () { // Reset after approaching self.targetX = 0; self.targetY = 0; }, 3000); } } // If targeting a specific location during wandering if (self.targetX !== 0 && self.targetY !== 0) { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 150) { // Move toward target at reduced speed self.x += dx / dist * (self.speed * 0.3); self.y += dy / dist * (self.speed * 0.3); } else { // Wander normally when close to target self.x += self.wanderDirection.x * (self.speed * 0.5); self.y += self.wanderDirection.y * (self.speed * 0.5); } } else { // Normal wandering 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; // Fade out effect tween(playerSprite, { alpha: 0.3, scaleX: 0.8, scaleY: 0.8 }, { duration: 300 }); LK.getSound('hide').play(); // Heavy breathing effect when monster is nearby if (monster && monster.isChasing) { // Trembling effect while hiding from monster var _tremble = function tremble() { if (self.isHidden && monster.isChasing) { var trembleAmt = 0.05; playerSprite.x = Math.random() * trembleAmt * 2 - trembleAmt; playerSprite.y = Math.random() * trembleAmt * 2 - trembleAmt; LK.setTimeout(_tremble, 100); } else { playerSprite.x = 0; playerSprite.y = 0; } }; _tremble(); } } }; 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); // Add subtle visual feedback for footsteps tween(playerSprite, { scaleX: 0.95, scaleY: 1.05, y: 5 }, { duration: 150, onFinish: function onFinish() { tween(playerSprite, { scaleX: 1, scaleY: 1, y: 0 }, { duration: 150 }); } }); } } }; 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; // Calculate speed based on noise level - more careful = less noise var speedMultiplier = distance > 30 ? 0.6 : 0.4; player.x += dx * speedMultiplier; player.y += dy * speedMultiplier; // If moving fast, generate more noise if (distance > 30) { player.makeNoise(0.01); } // 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); // Dramatic effect when monster gains sight LK.effects.flashScreen(0xFF0000, 800); // 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(); // Make a subtle pulsing effect to hint at correct exit LK.setTimeout(function () { tween(exits[exits.length - 1].children[0], { alpha: 0.7 }, { duration: 500, onFinish: function onFinish() { tween(exits[exits.length - 1].children[0], { alpha: 1 }, { duration: 500, onFinish: function onFinish() { if (gamePhase === "escaping") { this.onFinish(); } } }); } }); }, 1000); } 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); // Proximity warning - monster is getting close if (!player.isHidden && distMonster < monster.detectionRadius * 1.5 && !monster.isChasing) { // Visual proximity indicator if (LK.ticks % 60 === 0) { LK.effects.flashScreen(0x330000, 300); // Increase player fear based on proximity var proximityFear = 1 - distMonster / (monster.detectionRadius * 1.5); player.makeNoise(proximityFear * 0.1); // Fear increases noise level slightly } } // 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); // Also adjust light radius based on player noise game.children[i].adjustLightRadius(player.noiseLevel); 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
@@ -15,17 +15,27 @@
anchorX: 0.5,
anchorY: 0.5,
width: 2048,
height: 2732,
- alpha: 0.8,
+ alpha: 0.85,
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.lightRadius = 250; // Reduced visibility radius for more tension
+ self.adjustLightRadius = function (playerNoiseLevel) {
+ // Light shrinks when making noise (harder to see when noisy)
+ var targetRadius = 250 - playerNoiseLevel * 80;
+ // Smooth transition with tween
+ tween(self, {
+ lightRadius: targetRadius
+ }, {
+ duration: 500
+ });
+ };
self.updatePosition = function (playerX, playerY) {
self.x = 2048 / 2;
self.y = 2732 / 2;
// Create a mask using a circle asset at player's position
@@ -35,9 +45,10 @@
anchorX: 0.5,
anchorY: 0.5,
width: self.lightRadius * 2,
height: self.lightRadius * 2,
- tint: 0xFFFFFF
+ tint: 0xFFFFFF,
+ shape: 'ellipse'
}));
}
// Update mask position
self.mask.x = playerX - self.x;
@@ -130,8 +141,15 @@
self.isChasing = true;
self.targetX = x;
self.targetY = y;
LK.getSound('monster_detect').play();
+ // Increase speed temporarily during initial chase
+ self.speed = self.speed * 1.5;
+ LK.setTimeout(function () {
+ if (self.isChasing) {
+ self.speed = self.speed / 1.5;
+ }
+ }, 3000);
// Monster growls and bangs chest
function bangChest() {
tween(monsterSprite, {
scaleX: 1.3,
@@ -168,11 +186,41 @@
x: Math.cos(angle),
y: Math.sin(angle)
};
self.wanderTimer = 60 + Math.random() * 120;
+ // Sometimes patrol near a locker
+ if (Math.random() < 0.3 && lockers && lockers.length > 0) {
+ // Target a random locker
+ var randomLocker = lockers[Math.floor(Math.random() * lockers.length)];
+ self.targetX = randomLocker.x;
+ self.targetY = randomLocker.y;
+ // Move toward locker for a while
+ LK.setTimeout(function () {
+ // Reset after approaching
+ self.targetX = 0;
+ self.targetY = 0;
+ }, 3000);
+ }
}
- self.x += self.wanderDirection.x * (self.speed * 0.5);
- self.y += self.wanderDirection.y * (self.speed * 0.5);
+ // If targeting a specific location during wandering
+ if (self.targetX !== 0 && self.targetY !== 0) {
+ var dx = self.targetX - self.x;
+ var dy = self.targetY - self.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist > 150) {
+ // Move toward target at reduced speed
+ self.x += dx / dist * (self.speed * 0.3);
+ self.y += dy / dist * (self.speed * 0.3);
+ } else {
+ // Wander normally when close to target
+ self.x += self.wanderDirection.x * (self.speed * 0.5);
+ self.y += self.wanderDirection.y * (self.speed * 0.5);
+ }
+ } else {
+ // Normal wandering
+ 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;
@@ -245,10 +293,33 @@
};
self.hide = function () {
if (!self.isHidden) {
self.isHidden = true;
- playerSprite.alpha = 0.3;
+ // Fade out effect
+ tween(playerSprite, {
+ alpha: 0.3,
+ scaleX: 0.8,
+ scaleY: 0.8
+ }, {
+ duration: 300
+ });
LK.getSound('hide').play();
+ // Heavy breathing effect when monster is nearby
+ if (monster && monster.isChasing) {
+ // Trembling effect while hiding from monster
+ var _tremble = function tremble() {
+ if (self.isHidden && monster.isChasing) {
+ var trembleAmt = 0.05;
+ playerSprite.x = Math.random() * trembleAmt * 2 - trembleAmt;
+ playerSprite.y = Math.random() * trembleAmt * 2 - trembleAmt;
+ LK.setTimeout(_tremble, 100);
+ } else {
+ playerSprite.x = 0;
+ playerSprite.y = 0;
+ }
+ };
+ _tremble();
+ }
}
};
self.unhide = function () {
if (self.isHidden) {
@@ -261,8 +332,25 @@
if (self.isMoving && !self.isHidden) {
if (LK.ticks % 20 === 0) {
LK.getSound('footstep').play();
self.makeNoise(0.15);
+ // Add subtle visual feedback for footsteps
+ tween(playerSprite, {
+ scaleX: 0.95,
+ scaleY: 1.05,
+ y: 5
+ }, {
+ duration: 150,
+ onFinish: function onFinish() {
+ tween(playerSprite, {
+ scaleX: 1,
+ scaleY: 1,
+ y: 0
+ }, {
+ duration: 150
+ });
+ }
+ });
}
}
};
return self;
@@ -461,10 +549,16 @@
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;
+ // Calculate speed based on noise level - more careful = less noise
+ var speedMultiplier = distance > 30 ? 0.6 : 0.4;
+ player.x += dx * speedMultiplier;
+ player.y += dy * speedMultiplier;
+ // If moving fast, generate more noise
+ if (distance > 30) {
+ player.makeNoise(0.01);
+ }
// 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;
@@ -512,14 +606,36 @@
if (player.notebooksCollected >= notebooksRequired) {
gamePhase = "escaping";
instructionText.setText('All notebooks collected! Find an exit before Flumbo catches you!');
monster.setHasSight(true);
+ // Dramatic effect when monster gains sight
+ LK.effects.flashScreen(0xFF0000, 800);
// 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();
+ // Make a subtle pulsing effect to hint at correct exit
+ LK.setTimeout(function () {
+ tween(exits[exits.length - 1].children[0], {
+ alpha: 0.7
+ }, {
+ duration: 500,
+ onFinish: function onFinish() {
+ tween(exits[exits.length - 1].children[0], {
+ alpha: 1
+ }, {
+ duration: 500,
+ onFinish: function onFinish() {
+ if (gamePhase === "escaping") {
+ this.onFinish();
+ }
+ }
+ });
+ }
+ });
+ }, 1000);
} else {
// Make other exits visible but not usable
var exitSprite = exits[e].children[0];
exitSprite.alpha = 0.5;
@@ -619,8 +735,18 @@
// Monster detection
var dxMonster = monster.x - player.x;
var dyMonster = monster.y - player.y;
var distMonster = Math.sqrt(dxMonster * dxMonster + dyMonster * dyMonster);
+ // Proximity warning - monster is getting close
+ if (!player.isHidden && distMonster < monster.detectionRadius * 1.5 && !monster.isChasing) {
+ // Visual proximity indicator
+ if (LK.ticks % 60 === 0) {
+ LK.effects.flashScreen(0x330000, 300);
+ // Increase player fear based on proximity
+ var proximityFear = 1 - distMonster / (monster.detectionRadius * 1.5);
+ player.makeNoise(proximityFear * 0.1); // Fear increases noise level slightly
+ }
+ }
// 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
@@ -649,8 +775,10 @@
// 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);
+ // Also adjust light radius based on player noise
+ game.children[i].adjustLightRadius(player.noiseLevel);
break;
}
}
// Check for player caught by monster
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