User prompt
Make the doors open when the first night starts
User prompt
The power will go out quicker when the doors are closed and or if the light are on
User prompt
I can't use the lights at the door please make it so I can see outside the doors
User prompt
Make the power go out slower
User prompt
Make the doors black when they're open ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
I can't tell when the doors are open or closed
User prompt
The lights don't work please fix the lights
Code edit (1 edits merged)
Please save this source code
User prompt
Midnight Meow Terror
Initial prompt
Let make a 2D point and click horror game inspired by Five nights at freddy's with a green and blue cat as the theat
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { currentNight: 1, highestNight: 1 }); /**** * Classes ****/ var AnimatronicCorridor = Container.expand(function (side) { var self = Container.call(this); self.side = side; // "left" or "right" // Create the animatronic for the corridor var animatronic = self.attachAsset('animatronic', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); self.setVisible = function (visible) { self.visible = visible; if (visible) { // Animation for appearing in corridor animatronic.alpha = 0; tween(animatronic, { alpha: 1 }, { duration: 500 }); // Add a creepy movement animation tween(animatronic, { y: animatronic.y + 30 }, { duration: 2000, yoyo: true, repeat: -1 }); } }; // Make initially visible self.visible = true; return self; }); var CameraButton = Container.expand(function (id, x, y) { var self = Container.call(this); self.roomId = id; var button = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5 }); var text = new Text2('CAM ' + id, { size: 60, fill: 0xFFFFFF }); text.anchor.set(0.5, 0.5); self.addChild(text); self.x = x; self.y = y; self.interactive = true; self.down = function () { tween(button, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100 }); LK.getSound('camera').play(); }; self.up = function () { tween(button, { scaleX: 1, scaleY: 1 }, { duration: 100 }); if (currentCamera !== self.roomId) { currentCamera = self.roomId; showCamera(self.roomId); } }; return self; }); var DoorButton = Container.expand(function (side) { var self = Container.call(this); self.side = side; // "left" or "right" self.isOpen = true; var button = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5, width: 150, height: 150 }); var text = new Text2('DOOR', { size: 40, fill: 0xFFFFFF }); text.anchor.set(0.5, 0.5); self.addChild(text); self.interactive = true; self.down = function () { tween(button, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100 }); }; self.up = function () { tween(button, { scaleX: 1, scaleY: 1 }, { duration: 100 }); self.toggleDoor(); LK.getSound('door').play(); }; self.toggleDoor = function () { self.isOpen = !self.isOpen; if (self.isOpen) { text.setText("DOOR"); button.tint = 0x333333; powerDrain -= 5; // Reduce power drain when door is opened if (doors[self.side]) { tween(doors[self.side], { y: 2732 - doors[self.side].height / 2, tint: 0x000000 }, { duration: 300 }); } } else { text.setText("OPEN"); button.tint = 0x555555; powerDrain += 5; // Increase power drain when door is closed if (doors[self.side]) { tween(doors[self.side], { y: 2732 - doors[self.side].height, tint: 0xFFFFFF }, { duration: 300 }); } // Check if animatronic is at this door's corridor, and if so, send it back to entrance if (animatronicController && animatronicController.inCorridor && animatronicController.corridorSide === self.side) { // Hide from corridor if (corridorAnimatronics[self.side]) { corridorAnimatronics[self.side].setVisible(false); } // Turn off corridor light if (corridorLights[self.side]) { corridorLights[self.side].visible = false; } // Reset animatronic back to camera 1 (entrance) animatronicController.inCorridor = false; animatronicController.currentRoomIndex = 0; // Camera 1 animatronicRoom = 1; animatronicAtDoor = null; // Record the time when animatronic was sent back to enforce cooldown animatronicController.lastAttackTime = gameTime; // Show in camera 1 if (rooms[0]) { rooms[0].setAnimatronic(true); } // Play movement sound LK.getSound('footstep').play({ volume: 0.7 }); // Reset timer for next move animatronicController.moveTime = 0; } } }; return self; }); var LightButton = Container.expand(function (side) { var self = Container.call(this); self.side = side; // "left" or "right" self.isOn = false; var button = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5, width: 150, height: 150 }); var text = new Text2('LIGHT', { size: 40, fill: 0xFFFFFF }); text.anchor.set(0.5, 0.5); self.addChild(text); self.interactive = true; self.down = function () { tween(button, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100 }); if (!self.isOn) { self.isOn = true; text.setText("OFF"); powerDrain += 1; if (warnings[self.side]) { warnings[self.side].visible = animatronicAtDoor === self.side; if (animatronicAtDoor === self.side) { LK.getSound('warning').play(); } } // Make corridor visible when light is on if (corridorLights[self.side]) { corridorLights[self.side].visible = true; } } }; self.up = function () { tween(button, { scaleX: 1, scaleY: 1 }, { duration: 100 }); if (self.isOn) { self.isOn = false; text.setText("LIGHT"); powerDrain -= 1; if (warnings[self.side]) { warnings[self.side].visible = false; } // Hide corridor when light is off if (corridorLights[self.side]) { corridorLights[self.side].visible = false; } } }; return self; }); var Room = Container.expand(function (roomId, hasAnimatronic) { var self = Container.call(this); self.roomId = roomId; self.hasAnimatronic = hasAnimatronic || false; var background = self.attachAsset('cameraBg', { anchorX: 0.5, anchorY: 0.5 }); // Special code for Camera 1 if (roomId === 1) { // Camera 1: Entrance/Main Area - brighter, security desk background.tint = 0xd0d0d0; // Brighter area var desk = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5, x: -200, y: 100, width: 300, height: 150, tint: 0x553300 // Brown desk }); } else if (roomId === 2) { // Camera 2: Hallway - darker, narrow space background.tint = 0x707070; // Darker hallway var hallLight = self.attachAsset('warningLight', { anchorX: 0.5, anchorY: 0.5, x: 300, y: -200, width: 50, height: 50, tint: 0xffffaa // Dimmed hallway light }); } else if (roomId === 3) { // Camera 3: Storage Room - messy with boxes background.tint = 0x606060; // Add some storage boxes for (var i = 0; i < 3; i++) { var box = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5, x: -300 + i * 200, y: 200, width: 150, height: 150, tint: 0x855500 // Brown boxes }); } } else if (roomId === 4) { // Camera 4: Kitchen area - with counter background.tint = 0x505050; var counter = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 200, width: 500, height: 100, tint: 0x888888 // Metal counter }); } else if (roomId === 5) { // Camera 5: Back Room - very dark, closest to player background.tint = 0x404040; // Very dark // Add some creepy elements var backLight = self.attachAsset('warningLight', { anchorX: 0.5, anchorY: 0.5, x: -200, y: -250, width: 30, height: 30, tint: 0xff3300 // Red warning light }); // Flicker the light in the back room if (LK.ticks % 120 < 10) { backLight.visible = false; } else { backLight.visible = true; } } // Custom room names instead of generic "Room X" var roomNames = ["Main Entrance", "West Hallway", "Storage Room", "Kitchen Area", "Back Room"]; var roomText = new Text2(roomNames[roomId - 1], { size: 80, fill: 0xFFFFFF }); roomText.anchor.set(0.5, 0); roomText.y = -background.height / 2 + 50; self.addChild(roomText); // Add camera ID indicator in corner var camIdText = new Text2('CAM ' + roomId, { size: 60, fill: 0xFF0000 }); camIdText.anchor.set(0, 0); camIdText.x = -background.width / 2 + 50; camIdText.y = -background.height / 2 + 50; self.addChild(camIdText); // Always create animatronic, but set visibility based on hasAnimatronic var animatronic = self.attachAsset('animatronic', { anchorX: 0.5, anchorY: 1, y: background.height / 2 - 100 }); self.animatronic = animatronic; animatronic.visible = true; // Make animatronic always visible // Position animatronic differently in each room if (roomId === 1) { animatronic.x = -100; // Near the entrance animatronic.scaleX = 1.0; animatronic.scaleY = 1.0; } else if (roomId === 2) { animatronic.x = 200; // Coming down the hallway animatronic.scaleX = 0.9; animatronic.scaleY = 0.9; } else if (roomId === 3) { animatronic.x = -150; // Behind boxes animatronic.scaleX = 0.8; animatronic.scaleY = 0.8; } else if (roomId === 4) { animatronic.x = 50; // By the counter animatronic.scaleX = 1.1; animatronic.scaleY = 1.1; } else if (roomId === 5) { animatronic.x = 0; // In center, closer to camera animatronic.scaleX = 1.3; animatronic.scaleY = 1.3; } // Add method to update animatronic - properly handle visibility self.setAnimatronic = function (visible) { self.hasAnimatronic = visible; if (self.animatronic) { self.animatronic.visible = visible; // Force the update to take effect immediately to prevent glitching self.animatronic.alpha = visible ? 1 : 0; } }; // Add static effect to camera feed self.update = function () { // Skip static effect for Camera 1 (main entrance) if (roomId === 1) { return; } // Greatly reduced static effect when animatronic is in the room var staticProbability = self.hasAnimatronic ? 0.02 : 0.005; // Random static effect on the camera if (Math.random() < staticProbability) { // Occasionally add subtle static effect - less severe when animatronic present var staticTint = self.hasAnimatronic ? 0xffeeee : 0xeeeeee; // Very light tint background.tint = staticTint; // Avoid making animatronic temporarily invisible during static if (self.hasAnimatronic && self.animatronic) { // Keep animatronic visible, just slight movement var originalX = self.animatronic.x; var originalY = self.animatronic.y; // Very subtle movement self.animatronic.x = originalX + (Math.random() * 20 - 10); self.animatronic.y = originalY + (Math.random() * 20 - 10); // Reset position after a brief moment LK.setTimeout(function () { if (self.animatronic) { self.animatronic.x = originalX; self.animatronic.y = originalY; } }, 100); } // Reset the tint back to the room's normal tint after a short delay LK.setTimeout(function () { // Reset the tint back to the room's normal tint if (roomId === 1) { background.tint = 0xd0d0d0; } else if (roomId === 2) { background.tint = 0x707070; } else if (roomId === 3) { background.tint = 0x606060; } else if (roomId === 4) { background.tint = 0x505050; } else if (roomId === 5) { background.tint = 0x404040; } }, 100); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Game constants var AnimatronicController = function AnimatronicController() { // Make these properties accessible outside the function this.moveTime = 0; this.initialDelay = 20000; // Initial delay before animatronic starts moving (20 seconds) this.gameStartTime = 0; this.hasStartedMoving = false; this.moveDuration = 20000; // Move every 20 seconds this.currentRoomIndex = 0; // Start at room 1 this.lastAttackTime = 0; // Track when the animatronic last attacked this.attackCooldown = 60000; // One in-game hour cooldown (in ms) var movementPath = [0, 1, 2, 3, 4]; // Room indices (0-based) var atDoorProbability = 0.3; // Probability to go to door when at rooms 3 or 4 this.inCorridor = false; // Make inCorridor a property of the controller this.corridorSide = null; // Make corridorSide a property of the controller rather than a local variable function moveAnimatronic() { // First, set all rooms' animatronic visibility to false for (var i = 0; i < rooms.length; i++) { if (rooms[i]) { rooms[i].setAnimatronic(false); } } // Make sure to hide the standalone cat animatronic as well if (catAnimatronic) { catAnimatronic.visible = false; } // Hide animatronic from corridor as well if (corridorAnimatronics["left"]) { corridorAnimatronics["left"].setVisible(false); } if (corridorAnimatronics["right"]) { corridorAnimatronics["right"].setVisible(false); } // Create a subtle camera disruption effect when animatronic moves if (isCameraActive) { LK.effects.flashScreen(0xcccccc, 200); // Add mild screen shake effect if (cameraView) { var origX = cameraView.x; var origY = cameraView.y; cameraView.x += Math.random() * 20 - 10; cameraView.y += Math.random() * 20 - 10; LK.setTimeout(function () { cameraView.x = origX; cameraView.y = origY; }, 100); } } // Play footstep sound for every move LK.getSound('footstep').play({ volume: 0.7 }); // If the animatronic was in camera 5 (index 4), it should appear in corridor if (currentRoomIndex === 4) { // Check if enough time has passed since last attack (1 in-game hour) var currentTime = gameTime; if (currentTime - this.lastAttackTime < this.attackCooldown) { // Not enough time passed, retreat to camera 1 currentRoomIndex = 0; // Camera 1 animatronicRoom = 1; // Show in camera 1 if (rooms[0]) { rooms[0].hasAnimatronic = true; if (rooms[0].animatronic) { rooms[0].animatronic.visible = true; } } // Reset timer for next move moveTime = 0; return; // Skip attack attempt } // Coming from camera 5 - show in corridor before going to door this.inCorridor = true; corridorSide = Math.random() < 0.5 ? "left" : "right"; this.corridorSide = corridorSide; // Show the animatronic in corridor if (corridorAnimatronics[corridorSide]) { corridorAnimatronics[corridorSide].setVisible(true); } // Turn on corridor light automatically to show the threat if (corridorLights[corridorSide]) { corridorLights[corridorSide].visible = true; } // Play a warning sound to alert player LK.getSound('warning').play({ volume: 0.7 }); // Start a 5-second door timer var doorTimer = LK.setTimeout(function () { // Check if the door is closed var doorObj = corridorSide === "left" ? doorLeft : doorRight; if (doorObj.isOpen) { // Door still open after 5 seconds - trigger jumpscare game.triggerJumpscare(); } else { // Door was closed in time // Hide from corridor if (corridorAnimatronics[corridorSide]) { corridorAnimatronics[corridorSide].setVisible(false); } // Turn off corridor light if (corridorLights[corridorSide]) { corridorLights[corridorSide].visible = false; } // Reset animatronic back to camera 1 after 3 seconds LK.setTimeout(function () { animatronicController.inCorridor = false; currentRoomIndex = 0; // Camera 1 animatronicRoom = 1; animatronicAtDoor = null; // Show in camera 1 if (rooms[0]) { rooms[0].hasAnimatronic = true; if (rooms[0].animatronic) { rooms[0].animatronic.visible = true; } } // Play movement sound LK.getSound('footstep').play({ volume: 0.7 }); // Reset timer for next move moveTime = 0; }, 3000); // Reset back to camera 1 after 3 seconds } }, 5000); // Player has 5 seconds to close the door return; // Early return to handle special corridor case } // Decide next location based on current room var nextIndex = getNextRoom(); currentRoomIndex = nextIndex; // Check if animatronic should go to a door if (currentRoomIndex === -1) { // Animatronic is at door animatronicRoom = -1; animatronicAtDoor = Math.random() < 0.5 ? "left" : "right"; // Play door approach sound (louder to indicate danger) LK.getSound('footstep').play({ volume: 0.9 }); // Also play warning sound when approaching door LK.getSound('warning').play({ volume: 0.7 }); } else { // Normal room movement animatronicRoom = currentRoomIndex + 1; // Show animatronic in new room with a dramatic effect if (rooms[currentRoomIndex]) { rooms[currentRoomIndex].hasAnimatronic = true; if (rooms[currentRoomIndex].animatronic) { rooms[currentRoomIndex].animatronic.visible = true; // Add a sudden scaling effect to make the cat appear more threatening var originalScaleX = rooms[currentRoomIndex].animatronic.scaleX; var originalScaleY = rooms[currentRoomIndex].animatronic.scaleY; rooms[currentRoomIndex].animatronic.scaleX *= 1.2; rooms[currentRoomIndex].animatronic.scaleY *= 1.2; LK.setTimeout(function () { if (rooms[currentRoomIndex] && rooms[currentRoomIndex].animatronic) { rooms[currentRoomIndex].animatronic.scaleX = originalScaleX; rooms[currentRoomIndex].animatronic.scaleY = originalScaleY; } }, 500); } } // Play movement sound LK.getSound('footstep').play(); } // Reset timer moveTime = 0; } function getNextRoom() { // Special logic when at door if (currentRoomIndex === -1) { // If at door, check if door is closed var doorObj = animatronicAtDoor === "left" ? doorLeft : doorRight; if (!doorObj.isOpen) { // Door closed, retreat to room 3 or 4 return Math.random() < 0.5 ? 2 : 3; // Room 3 or 4 (0-based) } else { // Door open, stay at door (will trigger jumpscare in main game code) return -1; } } // As time progresses, make cat more aggressive by increasing probability of going to door var baseAggressiveness = 0.2; // Base aggressiveness var timeAggressiveness = Math.min(0.3, gameTime / GAME_DURATION * 0.5); // Increases with time var totalAggressiveness = baseAggressiveness + timeAggressiveness; // Special case for rooms 3 and 4 - might go to door if (currentRoomIndex === 2 || currentRoomIndex === 3) { if (Math.random() < atDoorProbability + totalAggressiveness) { return -1; // Go to door with increasing probability } } // Sometimes allow cat to skip rooms (becoming more unpredictable) if (Math.random() < totalAggressiveness) { // Skip to a further room or back to beginning for surprise factor var possibleRooms = [0, 1, 2, 3, 4]; // Filter out current room possibleRooms = possibleRooms.filter(function (idx) { return idx !== currentRoomIndex; }); return possibleRooms[Math.floor(Math.random() * possibleRooms.length)]; } // Normal sequential movement return (currentRoomIndex + 1) % ROOM_COUNT; } this.update = function (dt) { if (!gameStarted || gameOver) { return; } // Set game start time when not initialized if (this.gameStartTime === 0) { this.gameStartTime = LK.ticks; } // Check if we should start animatronic movement if (!this.hasStartedMoving) { // Check if it's 12:50 AM to start the movement var gameProgress = Math.min(gameTime / GAME_DURATION, 1); var hour = Math.floor(gameProgress * 6); if (hour === 0) { hour = 12; // 12 AM } var minute = Math.floor(gameProgress * 6 % 1 * 60); // Start moving only when the clock hits exactly 12:50 AM if (hour === 12 && minute === 50) { this.hasStartedMoving = true; // Don't play warning sound initially - only play when first camera movement happens // Play footstep sound when animatronic starts moving LK.getSound('footstep').play({ volume: 0.7 }); console.log("Animatronic has started moving!"); // Visual cue for camera disruption during movement if (isCameraActive) { // No flashing screen effect when animatronic starts moving } // First move is specifically from camera 1 to camera 2 this.currentRoomIndex = 0; // Ensure we're at camera 1 rooms[0].hasAnimatronic = false; if (rooms[0].animatronic) { rooms[0].animatronic.visible = false; } // Set to camera 2 this.currentRoomIndex = 1; animatronicRoom = 2; if (rooms[1]) { rooms[1].hasAnimatronic = true; if (rooms[1].animatronic) { rooms[1].animatronic.visible = true; } } // Play warning sound only if cat is not on the main entrance (Camera 1) if (this.currentRoomIndex !== 0) { LK.getSound('warning').play({ volume: 0.7 }); } // Reset timer for next move after this this.moveTime = 0; } else { return; // Don't update movement time until exactly 12:50 AM } } this.moveTime += dt; // Make cat move more frequently between cameras var movementInterval = this.moveDuration * 0.7; // Faster movement speed // Move to next camera periodically and make cat advance more frequently toward player if (this.moveTime >= movementInterval) { // Cat reached camera 5 if (this.currentRoomIndex === 4) { // Check if enough time has passed since last attack (1 in-game hour) var currentTime = gameTime; if (currentTime - this.lastAttackTime < this.attackCooldown) { // Not enough time passed, retreat to camera 1 this.currentRoomIndex = 0; animatronicRoom = 1; // Show in camera 1 if (rooms[0]) { rooms[0].setAnimatronic(true); } // Reset timer for next move this.moveTime = 0; return; // Skip attack attempt } // Cat reached camera 5 - transition to corridor console.log("Cat reached camera 5, moving to corridor"); // Create a smooth transition out of camera 5 if (rooms[4] && rooms[4].animatronic) { // Fade out from camera 5 tween(rooms[4].animatronic, { alpha: 0 }, { duration: 800, onFinish: function onFinish() { // Hide from camera 5 rooms[4].setAnimatronic(false); // Appear in corridor after transition this.inCorridor = true; corridorSide = Math.random() < 0.5 ? "left" : "right"; animatronicController.corridorSide = corridorSide; // Show in corridor with a fade in effect if (corridorAnimatronics[corridorSide]) { corridorAnimatronics[corridorSide].setVisible(true); } // Play warning sound only if cat is not on the main entrance (Camera 1) if (this.currentRoomIndex !== 0) { LK.getSound('warning').play({ volume: 0.7 }); } // Start 5-second door timer LK.setTimeout(function () { // Check if door is closed var doorObj = corridorSide === "left" ? doorLeft : doorRight; if (doorObj.isOpen && animatronicController.inCorridor) { // Door still open after 5 seconds - trigger jumpscare game.triggerJumpscare(); } }, 5000); // Player has 5 seconds to close the door LK.setTimeout(function () { // Check if door is closed var doorObj = corridorSide === "left" ? doorLeft : doorRight; if (doorObj.isOpen && animatronicController.inCorridor) { // Door still open after 5 seconds - trigger jumpscare game.triggerJumpscare(); } }, 5000); // Player has 5 seconds to close the door LK.setTimeout(function () { // Check if door is closed var doorObj = corridorSide === "left" ? doorLeft : doorRight; if (doorObj.isOpen) { // Door still open after 5 seconds - trigger jumpscare game.triggerJumpscare(); } else { // Door closed in time - cat retreats to camera 1 if (corridorAnimatronics[corridorSide]) { // Fade out from corridor tween(corridorAnimatronics[corridorSide], { alpha: 0 }, { duration: 500, onFinish: function onFinish() { // Hide from corridor corridorAnimatronics[corridorSide].setVisible(false); // Turn off corridor light if (corridorLights[corridorSide]) { corridorLights[corridorSide].visible = false; } // Reset to camera 1 with a delay LK.setTimeout(function () { animatronicController.inCorridor = false; currentRoomIndex = 0; // Camera 1 animatronicRoom = 1; animatronicAtDoor = null; // Show in camera 1 with fade in if (rooms[0]) { rooms[0].setAnimatronic(true); if (rooms[0].animatronic) { rooms[0].animatronic.alpha = 0; tween(rooms[0].animatronic, { alpha: 1 }, { duration: 800 }); } } // Play movement sound LK.getSound('footstep').play({ volume: 0.7 }); // Reset timer for next move cycle moveTime = 0; }, 2000); } }); } } }, 5000); // 5 seconds to close the door } }); } } else { // Normal movement between cameras // Slowly move to next camera with transitions var currentRoom = this.currentRoomIndex; var nextRoom = currentRoom + 1; // Ensure next room is valid if (nextRoom >= 0 && nextRoom < ROOM_COUNT) { // Fade out from current room if (rooms[currentRoom] && rooms[currentRoom].animatronic) { tween(rooms[currentRoom].animatronic, { alpha: 0 }, { duration: 800, onFinish: function onFinish() { // Hide from current room rooms[currentRoom].setAnimatronic(false); // Update room indices animatronicController.currentRoomIndex = nextRoom; animatronicRoom = nextRoom + 1; // Show in next room with fade in if (rooms[nextRoom]) { rooms[nextRoom].setAnimatronic(true); if (rooms[nextRoom].animatronic) { rooms[nextRoom].animatronic.alpha = 0; tween(rooms[nextRoom].animatronic, { alpha: 1 }, { duration: 800 }); } } // Play subtle movement sound LK.getSound('footstep').play({ volume: 0.5 }); } }); } } } // Reset timer for next move this.moveTime = 0; } }; return this; }; var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var MAX_POWER = 100; var POWER_DRAIN_RATE = 0.003; // Reduced base drain rate var GAME_DURATION = 360000; // 6 minutes (6 game hours) var ROOM_COUNT = 5; // Game state variables var currentNight = storage.currentNight || 1; var power = MAX_POWER; var powerDrain = 1; // Base power drain var gameTime = 0; var currentCamera = 1; var isCameraActive = false; var gameStarted = false; var gameOver = false; var animatronicRoom = 1; var animatronicMoveProbability = 0.05 * currentNight; var animatronicAtDoor = null; // "left", "right", or null var lastAnimatronicMove = 0; var doorLeftOpen = true; var doorRightOpen = true; var animatronicController = new AnimatronicController(); var rooms = []; var cameraButtons = []; var doors = { left: null, right: null }; var warnings = { left: null, right: null }; var corridorLights = { left: null, right: null }; var corridorAnimatronics = { left: null, right: null }; // Initialize the office view var office = game.addChild(LK.getAsset('office', { anchorX: 0.5, anchorY: 0.5, x: GAME_WIDTH / 2, y: GAME_HEIGHT / 2, scaleX: 10, scaleY: 10 })); // We don't need a standalone cat animatronic since we already have animatronics in rooms and corridors // Creating a completely hidden reference for animatronic that will never be shown var catAnimatronic = new Container(); catAnimatronic.x = -9999; catAnimatronic.y = -9999; catAnimatronic.visible = false; catAnimatronic.alpha = 0; catAnimatronic.scaleX = 0; catAnimatronic.scaleY = 0; // Setup camera view var cameraView = new Container(); cameraView.x = GAME_WIDTH / 2; cameraView.y = GAME_HEIGHT / 2; cameraView.visible = false; game.addChild(cameraView); var cameraScreen = cameraView.addChild(LK.getAsset('cameraScreen', { anchorX: 0.5, anchorY: 0.5 })); // Create rooms for the camera system for (var i = 1; i <= ROOM_COUNT; i++) { var room = new Room(i, i === animatronicRoom); room.x = 0; room.y = 0; room.visible = false; cameraView.addChild(room); rooms.push(room); } // Make the first room visible initially and ensure animatronic is visible rooms[0].visible = true; rooms[0].hasAnimatronic = true; if (rooms[0].animatronic) { rooms[0].animatronic.visible = true; } // Create camera buttons panel var cameraPanel = new Container(); cameraPanel.x = GAME_WIDTH / 2; cameraPanel.y = GAME_HEIGHT - 300; cameraPanel.visible = false; game.addChild(cameraPanel); for (var i = 1; i <= ROOM_COUNT; i++) { var col = (i - 1) % 3; var row = Math.floor((i - 1) / 3); var button = new CameraButton(i, (col - 1) * 350, row * 220); cameraPanel.addChild(button); cameraButtons.push(button); } // Create camera toggle button var toggleCameraBtn = game.addChild(LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, x: GAME_WIDTH / 2, y: GAME_HEIGHT - 150 })); var cameraText = new Text2('CAMERAS', { size: 60, fill: 0xFFFFFF }); cameraText.anchor.set(0.5, 0.5); cameraText.x = toggleCameraBtn.x; cameraText.y = toggleCameraBtn.y; game.addChild(cameraText); // Create power indicator var powerBarBg = game.addChild(LK.getAsset('powerBar', { anchorX: 0, anchorY: 0.5, x: 150, y: 150, tint: 0x555555 })); var powerBarFg = game.addChild(LK.getAsset('powerBar', { anchorX: 0, anchorY: 0.5, x: 150, y: 150 })); var powerText = new Text2('Power: 100%', { size: 40, fill: 0xFFFFFF }); powerText.anchor.set(0, 0.5); powerText.x = 150; powerText.y = 200; game.addChild(powerText); // Create clock var clockBg = game.addChild(LK.getAsset('clockBg', { anchorX: 0.5, anchorY: 0.5, x: GAME_WIDTH - 200, y: 100 })); var clockText = new Text2('12:00 AM', { size: 50, fill: 0xFFFFFF }); clockText.anchor.set(0.5, 0.5); clockText.x = clockBg.x; clockText.y = clockBg.y; game.addChild(clockText); // Create night indicator var nightText = new Text2('Night ' + currentNight, { size: 70, fill: 0xFFFFFF }); nightText.anchor.set(0.5, 0.5); nightText.x = GAME_WIDTH / 2; nightText.y = 100; game.addChild(nightText); // Create door controls var doorLeft = new DoorButton("left"); doorLeft.x = 150; doorLeft.y = GAME_HEIGHT / 2; game.addChild(doorLeft); var doorRight = new DoorButton("right"); doorRight.x = GAME_WIDTH - 150; doorRight.y = GAME_HEIGHT / 2; game.addChild(doorRight); // Create light controls var lightLeft = new LightButton("left"); lightLeft.x = 150; lightLeft.y = GAME_HEIGHT / 2 + 200; game.addChild(lightLeft); var lightRight = new LightButton("right"); lightRight.x = GAME_WIDTH - 150; lightRight.y = GAME_HEIGHT / 2 + 200; game.addChild(lightRight); // Create door visuals var leftDoor = game.addChild(LK.getAsset('door', { anchorX: 0.5, anchorY: 0, x: 550, y: GAME_HEIGHT - 800 / 2 })); doors.left = leftDoor; var rightDoor = game.addChild(LK.getAsset('door', { anchorX: 0.5, anchorY: 0, x: GAME_WIDTH - 550, y: GAME_HEIGHT - 800 / 2 })); doors.right = rightDoor; // Create warning lights var warningLeft = game.addChild(LK.getAsset('warningLight', { anchorX: 0.5, anchorY: 0.5, x: 550, y: GAME_HEIGHT / 2 })); warningLeft.visible = false; warnings.left = warningLeft; var warningRight = game.addChild(LK.getAsset('warningLight', { anchorX: 0.5, anchorY: 0.5, x: GAME_WIDTH - 550, y: GAME_HEIGHT / 2 })); warningRight.visible = false; warnings.right = warningRight; // Create corridor light visuals as simple yellow rectangles var corridorLightLeft = game.addChild(LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, x: 550, y: GAME_HEIGHT / 2, width: 400, height: 800, tint: 0xffff00 })); corridorLightLeft.visible = false; corridorLights.left = corridorLightLeft; var corridorLightRight = game.addChild(LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, x: GAME_WIDTH - 550, y: GAME_HEIGHT / 2, width: 400, height: 800, tint: 0xffff00 })); corridorLightRight.visible = false; corridorLights.right = corridorLightRight; // Create corridor animatronics corridorAnimatronics.left = new AnimatronicCorridor("left"); corridorAnimatronics.left.x = 550; corridorAnimatronics.left.y = GAME_HEIGHT / 2; corridorAnimatronics.left.setVisible(false); game.addChild(corridorAnimatronics.left); corridorAnimatronics.right = new AnimatronicCorridor("right"); corridorAnimatronics.right.x = GAME_WIDTH - 550; corridorAnimatronics.right.y = GAME_HEIGHT / 2; corridorAnimatronics.right.setVisible(false); game.addChild(corridorAnimatronics.right); // Create start game instructions var instructionText = new Text2("Click to start Night " + currentNight, { size: 80, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 0.5); instructionText.x = GAME_WIDTH / 2; instructionText.y = GAME_HEIGHT / 2; game.addChild(instructionText); // Helper function to show camera function showCamera(roomId) { // Ensure camera view is visible cameraView.visible = true; // Make sure valid room is selected if (roomId < 1 || roomId > rooms.length) { roomId = 1; // Default to camera 1 if invalid } // Hide all rooms first for (var i = 0; i < rooms.length; i++) { rooms[i].visible = false; } // Hide corridor animatronics when switching cameras if (corridorAnimatronics["left"]) { corridorAnimatronics["left"].setVisible(false); } if (corridorAnimatronics["right"]) { corridorAnimatronics["right"].setVisible(false); } // Show the selected room rooms[roomId - 1].visible = true; // Make sure the animatronic is shown correctly in this room if (animatronicRoom === roomId) { rooms[roomId - 1].setAnimatronic(true); } else { rooms[roomId - 1].setAnimatronic(false); } } // Helper function to toggle camera view function toggleCamera() { isCameraActive = !isCameraActive; if (isCameraActive) { // Show camera view first cameraView.visible = true; cameraPanel.visible = true; LK.getSound('camera').play(); cameraText.setText("CLOSE"); // Hide corridor animatronics when camera is active if (corridorAnimatronics["left"]) { corridorAnimatronics["left"].setVisible(false); } if (corridorAnimatronics["right"]) { corridorAnimatronics["right"].setVisible(false); } // Show camera immediately to avoid black flash showCamera(currentCamera); powerDrain += 2; // Increased power drain for cameras // Hide doors when camera view is active if (doors.left) { doors.left.visible = false; } if (doors.right) { doors.right.visible = false; } } else { // Hide camera view immediately cameraView.visible = false; cameraPanel.visible = false; cameraText.setText("CAMERAS"); powerDrain -= 2; // Decreased by same amount when turning off // Make sure corridor animatronics are visible/hidden correctly if (corridorAnimatronics["left"]) { corridorAnimatronics["left"].setVisible(animatronicController.corridorSide === "left" && animatronicController.inCorridor); } if (corridorAnimatronics["right"]) { corridorAnimatronics["right"].setVisible(animatronicController.corridorSide === "right" && animatronicController.inCorridor); } // Show doors when returning to office view if (doors.left) { doors.left.visible = true; } if (doors.right) { doors.right.visible = true; } } } // Update animatronic location function has been replaced by the AnimatronicController // Handle power outage scenario game.powerOutage = function powerOutage() { if (gameOver) { return; } gameOver = true; // Turn off all lights if (corridorLights["left"]) { corridorLights["left"].visible = false; } if (corridorLights["right"]) { corridorLights["right"].visible = false; } // Turn off warnings if (warnings["left"]) { warnings["left"].visible = false; } if (warnings["right"]) { warnings["right"].visible = false; } // Hide camera view if active if (isCameraActive) { isCameraActive = false; cameraView.visible = false; cameraPanel.visible = false; cameraText.setText("CAMERAS"); } // Set screen to black LK.effects.flashScreen(0x000000, 500, false); // Play a sound if we have one for power outage // Wait a random time between 2-7 seconds before jumpscare var randomDelay = 2000 + Math.random() * 5000; LK.setTimeout(function () { // Make sure the blue and green cat appears for jumpscare // Place cat in corridor animatronicController.inCorridor = true; animatronicController.corridorSide = Math.random() < 0.5 ? "left" : "right"; // Trigger jumpscare with the power outage flag game.triggerJumpscare(true); }, randomDelay); }; // Trigger jumpscare - defined as a game method to be accessible from AnimatronicController game.triggerJumpscare = function triggerJumpscare(isPowerOutage) { if (gameOver && !isPowerOutage) { return; } // Only check corridor condition if not a power outage if (!isPowerOutage && !animatronicController.inCorridor) { return; } gameOver = true; // Record the time of successful attack for cooldown animatronicController.lastAttackTime = gameTime; LK.getSound('jumpscare').play(); // Make the blue and green cat appear in corridor before jumpscare var corridorSide = animatronicController.corridorSide || (Math.random() < 0.5 ? "left" : "right"); // Hide cat from all cameras for (var i = 0; i < rooms.length; i++) { if (rooms[i]) { rooms[i].setAnimatronic(false); } } // Make cat visible in corridor if (corridorAnimatronics[corridorSide]) { corridorAnimatronics[corridorSide].setVisible(true); // Force cat to be visible during jumpscare corridorAnimatronics[corridorSide].alpha = 1; // Turn on corridor light to make cat visible if (corridorLights[corridorSide]) { corridorLights[corridorSide].visible = true; } // Make sure the cat stays in corridor before jumpscare animatronicController.inCorridor = true; animatronicController.corridorSide = corridorSide; } // Deactivate cameras if they're active if (isCameraActive) { isCameraActive = false; cameraView.visible = false; cameraPanel.visible = false; cameraText.setText("CAMERAS"); // Show doors when returning to office view if (doors.left) { doors.left.visible = true; } if (doors.right) { doors.right.visible = true; } } // Open both doors when jumpscared if (doors.left && !doorLeft.isOpen) { doorLeft.isOpen = true; tween(doors.left, { y: 2732 - doors.left.height / 2, tint: 0x000000 }, { duration: 300 }); } if (doors.right && !doorRight.isOpen) { doorRight.isOpen = true; tween(doors.right, { y: 2732 - doors.right.height / 2, tint: 0x000000 }, { duration: 300 }); } // Create visible jumpscare animation with the animatronic var jumpscare = game.addChild(new Container()); jumpscare.x = GAME_WIDTH / 2; jumpscare.y = GAME_HEIGHT / 2; // Add the cat animatronic to the jumpscare var jumpscareAnimatronic = jumpscare.attachAsset('animatronic', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.0, scaleY: 2.0 }); // Make sure the jumpscare is visible jumpscare.visible = true; // Add jumpscare animation tween(jumpscare, { scaleX: 4.5, scaleY: 4.5, x: GAME_WIDTH / 2 + Math.random() * 100 - 50, // Random movement y: GAME_HEIGHT / 2 + Math.random() * 100 - 50 // Random movement }, { duration: 300, easing: tween.outQuad }); LK.effects.flashScreen(0xff0000, 500); LK.setTimeout(function () { // Reset night to 1 when player dies storage.currentNight = 1; LK.showGameOver(); }, 1500); }; // Handle winning the night function winNight() { if (gameOver) { return; } gameOver = true; // Save progress if (currentNight >= storage.highestNight) { storage.highestNight = currentNight + 1; } storage.currentNight = currentNight + 1; // Display winning message var winText = new Text2("You survived until 6:00 AM! Night " + currentNight + " complete!", { size: 80, fill: 0xFFFFFF }); winText.anchor.set(0.5, 0.5); winText.x = GAME_WIDTH / 2; winText.y = GAME_HEIGHT / 2; game.addChild(winText); LK.setTimeout(function () { LK.showYouWin(); }, 3000); } // Event handlers game.down = function (x, y, obj) { if (!gameStarted) { // Start game when clicked gameStarted = true; instructionText.visible = false; LK.getSound('ambience').play(); LK.playMusic('backgroundMusic'); // Open doors when first night starts if (doors.left) { tween(doors.left, { y: 2732 - doors.left.height / 2, tint: 0x000000 }, { duration: 300 }); doorLeft.isOpen = true; } if (doors.right) { tween(doors.right, { y: 2732 - doors.right.height / 2, tint: 0x000000 }, { duration: 300 }); doorRight.isOpen = true; } return; } // Handle camera toggle button if (x >= toggleCameraBtn.x - toggleCameraBtn.width / 2 && x <= toggleCameraBtn.x + toggleCameraBtn.width / 2 && y >= toggleCameraBtn.y - toggleCameraBtn.height / 2 && y <= toggleCameraBtn.y + toggleCameraBtn.height / 2) { toggleCamera(); } }; // Game update loop game.update = function () { if (!gameStarted || gameOver) { return; } // Update game time gameTime += 16.67; // Approximate milliseconds per frame at 60fps // Update clock (6 hours from 12AM to 6AM in game duration) var gameProgress = Math.min(gameTime / GAME_DURATION, 1); // Check if animatronic is about to start moving based on the controller's timing var nearInitialMove = animatronicController && !animatronicController.hasStartedMoving && LK.ticks - animatronicController.gameStartTime >= animatronicController.initialDelay - 300 && LK.ticks - animatronicController.gameStartTime < animatronicController.initialDelay; if (nearInitialMove) { // Force the clock to show 12:50 AM right before the first movement hour = 12; minute = 50; } else { var hour = Math.floor(gameProgress * 6); if (hour === 0) { hour = 12; // 12 AM } else { hour = hour % 12; if (hour === 0) { hour = 6; } // Cap at 6 AM } var minute = Math.floor(gameProgress * 6 % 1 * 60); } var ampm = "AM"; // Always AM between 12 AM and 6 AM clockText.setText(hour + ":" + (minute < 10 ? "0" + minute : minute) + " " + ampm); // Win condition - survive until 6AM if (hour === 6 && minute === 0) { winNight(); return; } // Update power var closedDoorMultiplier = 1; // Check if doors are closed and increase power drain if (!doorLeft.isOpen && !doorRight.isOpen) { closedDoorMultiplier = 2; // Both doors closed - double drain } else if (!doorLeft.isOpen || !doorRight.isOpen) { closedDoorMultiplier = 1.5; // One door closed - 50% more drain } // Check if lights are on and adjust power drain accordingly var lightMultiplier = 1; if (lightLeft.isOn && lightRight.isOn) { lightMultiplier = 1.5; // Both lights on - 50% more drain } else if (lightLeft.isOn || lightRight.isOn) { lightMultiplier = 1.2; // One light on - 20% more drain } // Add camera multiplier var cameraMultiplier = isCameraActive ? 1.3 : 1; // Camera uses 30% more power when active power -= POWER_DRAIN_RATE * powerDrain * closedDoorMultiplier * lightMultiplier * cameraMultiplier; power = Math.max(0, power); var powerPercent = Math.floor(power); powerText.setText("Power: " + powerPercent + "%"); powerBarFg.width = power / MAX_POWER * powerBarBg.width; // Game over if power runs out if (power <= 0) { game.powerOutage(); return; } // Update animatronic controller animatronicController.update(16.67); // Update warning lights visibility based on light button state if (animatronicAtDoor === "left" && lightLeft.isOn) { warningLeft.visible = true; // Play warning sound occasionally when animatronic is spotted if (LK.ticks % 120 === 0) { // Approximately every 2 seconds LK.getSound('warning').play({ volume: 0.5 }); } } else { warningLeft.visible = false; } if (animatronicAtDoor === "right" && lightRight.isOn) { warningRight.visible = true; // Play warning sound occasionally when animatronic is spotted if (LK.ticks % 120 === 0) { // Approximately every 2 seconds LK.getSound('warning').play({ volume: 0.5 }); } } else { warningRight.visible = false; } // Visual cue when animatronic is moving between cameras if (LK.ticks % 900 === 0 && isCameraActive) { // Every 15 seconds during camera view // No flashing effect } // Add special visual effects when player is viewing the camera that contains the animatronic // but only for cameras other than the main entrance (camera 1) if (isCameraActive && currentCamera === animatronicRoom && rooms[animatronicRoom - 1] && rooms[animatronicRoom - 1].hasAnimatronic && currentCamera !== 1) { // Create occasional glitching/interference effect when looking directly at the animatronic if (LK.ticks % 120 === 0) { // Every 2 seconds // Don't flash red on any camera to make them more usable // Don't play warning sounds on any camera } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
currentNight: 1,
highestNight: 1
});
/****
* Classes
****/
var AnimatronicCorridor = Container.expand(function (side) {
var self = Container.call(this);
self.side = side; // "left" or "right"
// Create the animatronic for the corridor
var animatronic = self.attachAsset('animatronic', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
self.setVisible = function (visible) {
self.visible = visible;
if (visible) {
// Animation for appearing in corridor
animatronic.alpha = 0;
tween(animatronic, {
alpha: 1
}, {
duration: 500
});
// Add a creepy movement animation
tween(animatronic, {
y: animatronic.y + 30
}, {
duration: 2000,
yoyo: true,
repeat: -1
});
}
};
// Make initially visible
self.visible = true;
return self;
});
var CameraButton = Container.expand(function (id, x, y) {
var self = Container.call(this);
self.roomId = id;
var button = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
var text = new Text2('CAM ' + id, {
size: 60,
fill: 0xFFFFFF
});
text.anchor.set(0.5, 0.5);
self.addChild(text);
self.x = x;
self.y = y;
self.interactive = true;
self.down = function () {
tween(button, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100
});
LK.getSound('camera').play();
};
self.up = function () {
tween(button, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
if (currentCamera !== self.roomId) {
currentCamera = self.roomId;
showCamera(self.roomId);
}
};
return self;
});
var DoorButton = Container.expand(function (side) {
var self = Container.call(this);
self.side = side; // "left" or "right"
self.isOpen = true;
var button = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
width: 150,
height: 150
});
var text = new Text2('DOOR', {
size: 40,
fill: 0xFFFFFF
});
text.anchor.set(0.5, 0.5);
self.addChild(text);
self.interactive = true;
self.down = function () {
tween(button, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100
});
};
self.up = function () {
tween(button, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
self.toggleDoor();
LK.getSound('door').play();
};
self.toggleDoor = function () {
self.isOpen = !self.isOpen;
if (self.isOpen) {
text.setText("DOOR");
button.tint = 0x333333;
powerDrain -= 5; // Reduce power drain when door is opened
if (doors[self.side]) {
tween(doors[self.side], {
y: 2732 - doors[self.side].height / 2,
tint: 0x000000
}, {
duration: 300
});
}
} else {
text.setText("OPEN");
button.tint = 0x555555;
powerDrain += 5; // Increase power drain when door is closed
if (doors[self.side]) {
tween(doors[self.side], {
y: 2732 - doors[self.side].height,
tint: 0xFFFFFF
}, {
duration: 300
});
}
// Check if animatronic is at this door's corridor, and if so, send it back to entrance
if (animatronicController && animatronicController.inCorridor && animatronicController.corridorSide === self.side) {
// Hide from corridor
if (corridorAnimatronics[self.side]) {
corridorAnimatronics[self.side].setVisible(false);
}
// Turn off corridor light
if (corridorLights[self.side]) {
corridorLights[self.side].visible = false;
}
// Reset animatronic back to camera 1 (entrance)
animatronicController.inCorridor = false;
animatronicController.currentRoomIndex = 0; // Camera 1
animatronicRoom = 1;
animatronicAtDoor = null;
// Record the time when animatronic was sent back to enforce cooldown
animatronicController.lastAttackTime = gameTime;
// Show in camera 1
if (rooms[0]) {
rooms[0].setAnimatronic(true);
}
// Play movement sound
LK.getSound('footstep').play({
volume: 0.7
});
// Reset timer for next move
animatronicController.moveTime = 0;
}
}
};
return self;
});
var LightButton = Container.expand(function (side) {
var self = Container.call(this);
self.side = side; // "left" or "right"
self.isOn = false;
var button = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
width: 150,
height: 150
});
var text = new Text2('LIGHT', {
size: 40,
fill: 0xFFFFFF
});
text.anchor.set(0.5, 0.5);
self.addChild(text);
self.interactive = true;
self.down = function () {
tween(button, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100
});
if (!self.isOn) {
self.isOn = true;
text.setText("OFF");
powerDrain += 1;
if (warnings[self.side]) {
warnings[self.side].visible = animatronicAtDoor === self.side;
if (animatronicAtDoor === self.side) {
LK.getSound('warning').play();
}
}
// Make corridor visible when light is on
if (corridorLights[self.side]) {
corridorLights[self.side].visible = true;
}
}
};
self.up = function () {
tween(button, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
if (self.isOn) {
self.isOn = false;
text.setText("LIGHT");
powerDrain -= 1;
if (warnings[self.side]) {
warnings[self.side].visible = false;
}
// Hide corridor when light is off
if (corridorLights[self.side]) {
corridorLights[self.side].visible = false;
}
}
};
return self;
});
var Room = Container.expand(function (roomId, hasAnimatronic) {
var self = Container.call(this);
self.roomId = roomId;
self.hasAnimatronic = hasAnimatronic || false;
var background = self.attachAsset('cameraBg', {
anchorX: 0.5,
anchorY: 0.5
});
// Special code for Camera 1
if (roomId === 1) {
// Camera 1: Entrance/Main Area - brighter, security desk
background.tint = 0xd0d0d0; // Brighter area
var desk = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
x: -200,
y: 100,
width: 300,
height: 150,
tint: 0x553300 // Brown desk
});
} else if (roomId === 2) {
// Camera 2: Hallway - darker, narrow space
background.tint = 0x707070; // Darker hallway
var hallLight = self.attachAsset('warningLight', {
anchorX: 0.5,
anchorY: 0.5,
x: 300,
y: -200,
width: 50,
height: 50,
tint: 0xffffaa // Dimmed hallway light
});
} else if (roomId === 3) {
// Camera 3: Storage Room - messy with boxes
background.tint = 0x606060;
// Add some storage boxes
for (var i = 0; i < 3; i++) {
var box = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
x: -300 + i * 200,
y: 200,
width: 150,
height: 150,
tint: 0x855500 // Brown boxes
});
}
} else if (roomId === 4) {
// Camera 4: Kitchen area - with counter
background.tint = 0x505050;
var counter = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 200,
width: 500,
height: 100,
tint: 0x888888 // Metal counter
});
} else if (roomId === 5) {
// Camera 5: Back Room - very dark, closest to player
background.tint = 0x404040; // Very dark
// Add some creepy elements
var backLight = self.attachAsset('warningLight', {
anchorX: 0.5,
anchorY: 0.5,
x: -200,
y: -250,
width: 30,
height: 30,
tint: 0xff3300 // Red warning light
});
// Flicker the light in the back room
if (LK.ticks % 120 < 10) {
backLight.visible = false;
} else {
backLight.visible = true;
}
}
// Custom room names instead of generic "Room X"
var roomNames = ["Main Entrance", "West Hallway", "Storage Room", "Kitchen Area", "Back Room"];
var roomText = new Text2(roomNames[roomId - 1], {
size: 80,
fill: 0xFFFFFF
});
roomText.anchor.set(0.5, 0);
roomText.y = -background.height / 2 + 50;
self.addChild(roomText);
// Add camera ID indicator in corner
var camIdText = new Text2('CAM ' + roomId, {
size: 60,
fill: 0xFF0000
});
camIdText.anchor.set(0, 0);
camIdText.x = -background.width / 2 + 50;
camIdText.y = -background.height / 2 + 50;
self.addChild(camIdText);
// Always create animatronic, but set visibility based on hasAnimatronic
var animatronic = self.attachAsset('animatronic', {
anchorX: 0.5,
anchorY: 1,
y: background.height / 2 - 100
});
self.animatronic = animatronic;
animatronic.visible = true; // Make animatronic always visible
// Position animatronic differently in each room
if (roomId === 1) {
animatronic.x = -100; // Near the entrance
animatronic.scaleX = 1.0;
animatronic.scaleY = 1.0;
} else if (roomId === 2) {
animatronic.x = 200; // Coming down the hallway
animatronic.scaleX = 0.9;
animatronic.scaleY = 0.9;
} else if (roomId === 3) {
animatronic.x = -150; // Behind boxes
animatronic.scaleX = 0.8;
animatronic.scaleY = 0.8;
} else if (roomId === 4) {
animatronic.x = 50; // By the counter
animatronic.scaleX = 1.1;
animatronic.scaleY = 1.1;
} else if (roomId === 5) {
animatronic.x = 0; // In center, closer to camera
animatronic.scaleX = 1.3;
animatronic.scaleY = 1.3;
}
// Add method to update animatronic - properly handle visibility
self.setAnimatronic = function (visible) {
self.hasAnimatronic = visible;
if (self.animatronic) {
self.animatronic.visible = visible;
// Force the update to take effect immediately to prevent glitching
self.animatronic.alpha = visible ? 1 : 0;
}
};
// Add static effect to camera feed
self.update = function () {
// Skip static effect for Camera 1 (main entrance)
if (roomId === 1) {
return;
}
// Greatly reduced static effect when animatronic is in the room
var staticProbability = self.hasAnimatronic ? 0.02 : 0.005;
// Random static effect on the camera
if (Math.random() < staticProbability) {
// Occasionally add subtle static effect - less severe when animatronic present
var staticTint = self.hasAnimatronic ? 0xffeeee : 0xeeeeee; // Very light tint
background.tint = staticTint;
// Avoid making animatronic temporarily invisible during static
if (self.hasAnimatronic && self.animatronic) {
// Keep animatronic visible, just slight movement
var originalX = self.animatronic.x;
var originalY = self.animatronic.y;
// Very subtle movement
self.animatronic.x = originalX + (Math.random() * 20 - 10);
self.animatronic.y = originalY + (Math.random() * 20 - 10);
// Reset position after a brief moment
LK.setTimeout(function () {
if (self.animatronic) {
self.animatronic.x = originalX;
self.animatronic.y = originalY;
}
}, 100);
}
// Reset the tint back to the room's normal tint after a short delay
LK.setTimeout(function () {
// Reset the tint back to the room's normal tint
if (roomId === 1) {
background.tint = 0xd0d0d0;
} else if (roomId === 2) {
background.tint = 0x707070;
} else if (roomId === 3) {
background.tint = 0x606060;
} else if (roomId === 4) {
background.tint = 0x505050;
} else if (roomId === 5) {
background.tint = 0x404040;
}
}, 100);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game constants
var AnimatronicController = function AnimatronicController() {
// Make these properties accessible outside the function
this.moveTime = 0;
this.initialDelay = 20000; // Initial delay before animatronic starts moving (20 seconds)
this.gameStartTime = 0;
this.hasStartedMoving = false;
this.moveDuration = 20000; // Move every 20 seconds
this.currentRoomIndex = 0; // Start at room 1
this.lastAttackTime = 0; // Track when the animatronic last attacked
this.attackCooldown = 60000; // One in-game hour cooldown (in ms)
var movementPath = [0, 1, 2, 3, 4]; // Room indices (0-based)
var atDoorProbability = 0.3; // Probability to go to door when at rooms 3 or 4
this.inCorridor = false; // Make inCorridor a property of the controller
this.corridorSide = null; // Make corridorSide a property of the controller rather than a local variable
function moveAnimatronic() {
// First, set all rooms' animatronic visibility to false
for (var i = 0; i < rooms.length; i++) {
if (rooms[i]) {
rooms[i].setAnimatronic(false);
}
}
// Make sure to hide the standalone cat animatronic as well
if (catAnimatronic) {
catAnimatronic.visible = false;
}
// Hide animatronic from corridor as well
if (corridorAnimatronics["left"]) {
corridorAnimatronics["left"].setVisible(false);
}
if (corridorAnimatronics["right"]) {
corridorAnimatronics["right"].setVisible(false);
}
// Create a subtle camera disruption effect when animatronic moves
if (isCameraActive) {
LK.effects.flashScreen(0xcccccc, 200);
// Add mild screen shake effect
if (cameraView) {
var origX = cameraView.x;
var origY = cameraView.y;
cameraView.x += Math.random() * 20 - 10;
cameraView.y += Math.random() * 20 - 10;
LK.setTimeout(function () {
cameraView.x = origX;
cameraView.y = origY;
}, 100);
}
}
// Play footstep sound for every move
LK.getSound('footstep').play({
volume: 0.7
});
// If the animatronic was in camera 5 (index 4), it should appear in corridor
if (currentRoomIndex === 4) {
// Check if enough time has passed since last attack (1 in-game hour)
var currentTime = gameTime;
if (currentTime - this.lastAttackTime < this.attackCooldown) {
// Not enough time passed, retreat to camera 1
currentRoomIndex = 0; // Camera 1
animatronicRoom = 1;
// Show in camera 1
if (rooms[0]) {
rooms[0].hasAnimatronic = true;
if (rooms[0].animatronic) {
rooms[0].animatronic.visible = true;
}
}
// Reset timer for next move
moveTime = 0;
return; // Skip attack attempt
}
// Coming from camera 5 - show in corridor before going to door
this.inCorridor = true;
corridorSide = Math.random() < 0.5 ? "left" : "right";
this.corridorSide = corridorSide;
// Show the animatronic in corridor
if (corridorAnimatronics[corridorSide]) {
corridorAnimatronics[corridorSide].setVisible(true);
}
// Turn on corridor light automatically to show the threat
if (corridorLights[corridorSide]) {
corridorLights[corridorSide].visible = true;
}
// Play a warning sound to alert player
LK.getSound('warning').play({
volume: 0.7
});
// Start a 5-second door timer
var doorTimer = LK.setTimeout(function () {
// Check if the door is closed
var doorObj = corridorSide === "left" ? doorLeft : doorRight;
if (doorObj.isOpen) {
// Door still open after 5 seconds - trigger jumpscare
game.triggerJumpscare();
} else {
// Door was closed in time
// Hide from corridor
if (corridorAnimatronics[corridorSide]) {
corridorAnimatronics[corridorSide].setVisible(false);
}
// Turn off corridor light
if (corridorLights[corridorSide]) {
corridorLights[corridorSide].visible = false;
}
// Reset animatronic back to camera 1 after 3 seconds
LK.setTimeout(function () {
animatronicController.inCorridor = false;
currentRoomIndex = 0; // Camera 1
animatronicRoom = 1;
animatronicAtDoor = null;
// Show in camera 1
if (rooms[0]) {
rooms[0].hasAnimatronic = true;
if (rooms[0].animatronic) {
rooms[0].animatronic.visible = true;
}
}
// Play movement sound
LK.getSound('footstep').play({
volume: 0.7
});
// Reset timer for next move
moveTime = 0;
}, 3000); // Reset back to camera 1 after 3 seconds
}
}, 5000); // Player has 5 seconds to close the door
return; // Early return to handle special corridor case
}
// Decide next location based on current room
var nextIndex = getNextRoom();
currentRoomIndex = nextIndex;
// Check if animatronic should go to a door
if (currentRoomIndex === -1) {
// Animatronic is at door
animatronicRoom = -1;
animatronicAtDoor = Math.random() < 0.5 ? "left" : "right";
// Play door approach sound (louder to indicate danger)
LK.getSound('footstep').play({
volume: 0.9
});
// Also play warning sound when approaching door
LK.getSound('warning').play({
volume: 0.7
});
} else {
// Normal room movement
animatronicRoom = currentRoomIndex + 1;
// Show animatronic in new room with a dramatic effect
if (rooms[currentRoomIndex]) {
rooms[currentRoomIndex].hasAnimatronic = true;
if (rooms[currentRoomIndex].animatronic) {
rooms[currentRoomIndex].animatronic.visible = true;
// Add a sudden scaling effect to make the cat appear more threatening
var originalScaleX = rooms[currentRoomIndex].animatronic.scaleX;
var originalScaleY = rooms[currentRoomIndex].animatronic.scaleY;
rooms[currentRoomIndex].animatronic.scaleX *= 1.2;
rooms[currentRoomIndex].animatronic.scaleY *= 1.2;
LK.setTimeout(function () {
if (rooms[currentRoomIndex] && rooms[currentRoomIndex].animatronic) {
rooms[currentRoomIndex].animatronic.scaleX = originalScaleX;
rooms[currentRoomIndex].animatronic.scaleY = originalScaleY;
}
}, 500);
}
}
// Play movement sound
LK.getSound('footstep').play();
}
// Reset timer
moveTime = 0;
}
function getNextRoom() {
// Special logic when at door
if (currentRoomIndex === -1) {
// If at door, check if door is closed
var doorObj = animatronicAtDoor === "left" ? doorLeft : doorRight;
if (!doorObj.isOpen) {
// Door closed, retreat to room 3 or 4
return Math.random() < 0.5 ? 2 : 3; // Room 3 or 4 (0-based)
} else {
// Door open, stay at door (will trigger jumpscare in main game code)
return -1;
}
}
// As time progresses, make cat more aggressive by increasing probability of going to door
var baseAggressiveness = 0.2; // Base aggressiveness
var timeAggressiveness = Math.min(0.3, gameTime / GAME_DURATION * 0.5); // Increases with time
var totalAggressiveness = baseAggressiveness + timeAggressiveness;
// Special case for rooms 3 and 4 - might go to door
if (currentRoomIndex === 2 || currentRoomIndex === 3) {
if (Math.random() < atDoorProbability + totalAggressiveness) {
return -1; // Go to door with increasing probability
}
}
// Sometimes allow cat to skip rooms (becoming more unpredictable)
if (Math.random() < totalAggressiveness) {
// Skip to a further room or back to beginning for surprise factor
var possibleRooms = [0, 1, 2, 3, 4];
// Filter out current room
possibleRooms = possibleRooms.filter(function (idx) {
return idx !== currentRoomIndex;
});
return possibleRooms[Math.floor(Math.random() * possibleRooms.length)];
}
// Normal sequential movement
return (currentRoomIndex + 1) % ROOM_COUNT;
}
this.update = function (dt) {
if (!gameStarted || gameOver) {
return;
}
// Set game start time when not initialized
if (this.gameStartTime === 0) {
this.gameStartTime = LK.ticks;
}
// Check if we should start animatronic movement
if (!this.hasStartedMoving) {
// Check if it's 12:50 AM to start the movement
var gameProgress = Math.min(gameTime / GAME_DURATION, 1);
var hour = Math.floor(gameProgress * 6);
if (hour === 0) {
hour = 12; // 12 AM
}
var minute = Math.floor(gameProgress * 6 % 1 * 60);
// Start moving only when the clock hits exactly 12:50 AM
if (hour === 12 && minute === 50) {
this.hasStartedMoving = true;
// Don't play warning sound initially - only play when first camera movement happens
// Play footstep sound when animatronic starts moving
LK.getSound('footstep').play({
volume: 0.7
});
console.log("Animatronic has started moving!");
// Visual cue for camera disruption during movement
if (isCameraActive) {
// No flashing screen effect when animatronic starts moving
}
// First move is specifically from camera 1 to camera 2
this.currentRoomIndex = 0; // Ensure we're at camera 1
rooms[0].hasAnimatronic = false;
if (rooms[0].animatronic) {
rooms[0].animatronic.visible = false;
}
// Set to camera 2
this.currentRoomIndex = 1;
animatronicRoom = 2;
if (rooms[1]) {
rooms[1].hasAnimatronic = true;
if (rooms[1].animatronic) {
rooms[1].animatronic.visible = true;
}
}
// Play warning sound only if cat is not on the main entrance (Camera 1)
if (this.currentRoomIndex !== 0) {
LK.getSound('warning').play({
volume: 0.7
});
}
// Reset timer for next move after this
this.moveTime = 0;
} else {
return; // Don't update movement time until exactly 12:50 AM
}
}
this.moveTime += dt;
// Make cat move more frequently between cameras
var movementInterval = this.moveDuration * 0.7; // Faster movement speed
// Move to next camera periodically and make cat advance more frequently toward player
if (this.moveTime >= movementInterval) {
// Cat reached camera 5
if (this.currentRoomIndex === 4) {
// Check if enough time has passed since last attack (1 in-game hour)
var currentTime = gameTime;
if (currentTime - this.lastAttackTime < this.attackCooldown) {
// Not enough time passed, retreat to camera 1
this.currentRoomIndex = 0;
animatronicRoom = 1;
// Show in camera 1
if (rooms[0]) {
rooms[0].setAnimatronic(true);
}
// Reset timer for next move
this.moveTime = 0;
return; // Skip attack attempt
}
// Cat reached camera 5 - transition to corridor
console.log("Cat reached camera 5, moving to corridor");
// Create a smooth transition out of camera 5
if (rooms[4] && rooms[4].animatronic) {
// Fade out from camera 5
tween(rooms[4].animatronic, {
alpha: 0
}, {
duration: 800,
onFinish: function onFinish() {
// Hide from camera 5
rooms[4].setAnimatronic(false);
// Appear in corridor after transition
this.inCorridor = true;
corridorSide = Math.random() < 0.5 ? "left" : "right";
animatronicController.corridorSide = corridorSide;
// Show in corridor with a fade in effect
if (corridorAnimatronics[corridorSide]) {
corridorAnimatronics[corridorSide].setVisible(true);
}
// Play warning sound only if cat is not on the main entrance (Camera 1)
if (this.currentRoomIndex !== 0) {
LK.getSound('warning').play({
volume: 0.7
});
}
// Start 5-second door timer
LK.setTimeout(function () {
// Check if door is closed
var doorObj = corridorSide === "left" ? doorLeft : doorRight;
if (doorObj.isOpen && animatronicController.inCorridor) {
// Door still open after 5 seconds - trigger jumpscare
game.triggerJumpscare();
}
}, 5000); // Player has 5 seconds to close the door
LK.setTimeout(function () {
// Check if door is closed
var doorObj = corridorSide === "left" ? doorLeft : doorRight;
if (doorObj.isOpen && animatronicController.inCorridor) {
// Door still open after 5 seconds - trigger jumpscare
game.triggerJumpscare();
}
}, 5000); // Player has 5 seconds to close the door
LK.setTimeout(function () {
// Check if door is closed
var doorObj = corridorSide === "left" ? doorLeft : doorRight;
if (doorObj.isOpen) {
// Door still open after 5 seconds - trigger jumpscare
game.triggerJumpscare();
} else {
// Door closed in time - cat retreats to camera 1
if (corridorAnimatronics[corridorSide]) {
// Fade out from corridor
tween(corridorAnimatronics[corridorSide], {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
// Hide from corridor
corridorAnimatronics[corridorSide].setVisible(false);
// Turn off corridor light
if (corridorLights[corridorSide]) {
corridorLights[corridorSide].visible = false;
}
// Reset to camera 1 with a delay
LK.setTimeout(function () {
animatronicController.inCorridor = false;
currentRoomIndex = 0; // Camera 1
animatronicRoom = 1;
animatronicAtDoor = null;
// Show in camera 1 with fade in
if (rooms[0]) {
rooms[0].setAnimatronic(true);
if (rooms[0].animatronic) {
rooms[0].animatronic.alpha = 0;
tween(rooms[0].animatronic, {
alpha: 1
}, {
duration: 800
});
}
}
// Play movement sound
LK.getSound('footstep').play({
volume: 0.7
});
// Reset timer for next move cycle
moveTime = 0;
}, 2000);
}
});
}
}
}, 5000); // 5 seconds to close the door
}
});
}
} else {
// Normal movement between cameras
// Slowly move to next camera with transitions
var currentRoom = this.currentRoomIndex;
var nextRoom = currentRoom + 1;
// Ensure next room is valid
if (nextRoom >= 0 && nextRoom < ROOM_COUNT) {
// Fade out from current room
if (rooms[currentRoom] && rooms[currentRoom].animatronic) {
tween(rooms[currentRoom].animatronic, {
alpha: 0
}, {
duration: 800,
onFinish: function onFinish() {
// Hide from current room
rooms[currentRoom].setAnimatronic(false);
// Update room indices
animatronicController.currentRoomIndex = nextRoom;
animatronicRoom = nextRoom + 1;
// Show in next room with fade in
if (rooms[nextRoom]) {
rooms[nextRoom].setAnimatronic(true);
if (rooms[nextRoom].animatronic) {
rooms[nextRoom].animatronic.alpha = 0;
tween(rooms[nextRoom].animatronic, {
alpha: 1
}, {
duration: 800
});
}
}
// Play subtle movement sound
LK.getSound('footstep').play({
volume: 0.5
});
}
});
}
}
}
// Reset timer for next move
this.moveTime = 0;
}
};
return this;
};
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var MAX_POWER = 100;
var POWER_DRAIN_RATE = 0.003; // Reduced base drain rate
var GAME_DURATION = 360000; // 6 minutes (6 game hours)
var ROOM_COUNT = 5;
// Game state variables
var currentNight = storage.currentNight || 1;
var power = MAX_POWER;
var powerDrain = 1; // Base power drain
var gameTime = 0;
var currentCamera = 1;
var isCameraActive = false;
var gameStarted = false;
var gameOver = false;
var animatronicRoom = 1;
var animatronicMoveProbability = 0.05 * currentNight;
var animatronicAtDoor = null; // "left", "right", or null
var lastAnimatronicMove = 0;
var doorLeftOpen = true;
var doorRightOpen = true;
var animatronicController = new AnimatronicController();
var rooms = [];
var cameraButtons = [];
var doors = {
left: null,
right: null
};
var warnings = {
left: null,
right: null
};
var corridorLights = {
left: null,
right: null
};
var corridorAnimatronics = {
left: null,
right: null
};
// Initialize the office view
var office = game.addChild(LK.getAsset('office', {
anchorX: 0.5,
anchorY: 0.5,
x: GAME_WIDTH / 2,
y: GAME_HEIGHT / 2,
scaleX: 10,
scaleY: 10
}));
// We don't need a standalone cat animatronic since we already have animatronics in rooms and corridors
// Creating a completely hidden reference for animatronic that will never be shown
var catAnimatronic = new Container();
catAnimatronic.x = -9999;
catAnimatronic.y = -9999;
catAnimatronic.visible = false;
catAnimatronic.alpha = 0;
catAnimatronic.scaleX = 0;
catAnimatronic.scaleY = 0;
// Setup camera view
var cameraView = new Container();
cameraView.x = GAME_WIDTH / 2;
cameraView.y = GAME_HEIGHT / 2;
cameraView.visible = false;
game.addChild(cameraView);
var cameraScreen = cameraView.addChild(LK.getAsset('cameraScreen', {
anchorX: 0.5,
anchorY: 0.5
}));
// Create rooms for the camera system
for (var i = 1; i <= ROOM_COUNT; i++) {
var room = new Room(i, i === animatronicRoom);
room.x = 0;
room.y = 0;
room.visible = false;
cameraView.addChild(room);
rooms.push(room);
}
// Make the first room visible initially and ensure animatronic is visible
rooms[0].visible = true;
rooms[0].hasAnimatronic = true;
if (rooms[0].animatronic) {
rooms[0].animatronic.visible = true;
}
// Create camera buttons panel
var cameraPanel = new Container();
cameraPanel.x = GAME_WIDTH / 2;
cameraPanel.y = GAME_HEIGHT - 300;
cameraPanel.visible = false;
game.addChild(cameraPanel);
for (var i = 1; i <= ROOM_COUNT; i++) {
var col = (i - 1) % 3;
var row = Math.floor((i - 1) / 3);
var button = new CameraButton(i, (col - 1) * 350, row * 220);
cameraPanel.addChild(button);
cameraButtons.push(button);
}
// Create camera toggle button
var toggleCameraBtn = game.addChild(LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
x: GAME_WIDTH / 2,
y: GAME_HEIGHT - 150
}));
var cameraText = new Text2('CAMERAS', {
size: 60,
fill: 0xFFFFFF
});
cameraText.anchor.set(0.5, 0.5);
cameraText.x = toggleCameraBtn.x;
cameraText.y = toggleCameraBtn.y;
game.addChild(cameraText);
// Create power indicator
var powerBarBg = game.addChild(LK.getAsset('powerBar', {
anchorX: 0,
anchorY: 0.5,
x: 150,
y: 150,
tint: 0x555555
}));
var powerBarFg = game.addChild(LK.getAsset('powerBar', {
anchorX: 0,
anchorY: 0.5,
x: 150,
y: 150
}));
var powerText = new Text2('Power: 100%', {
size: 40,
fill: 0xFFFFFF
});
powerText.anchor.set(0, 0.5);
powerText.x = 150;
powerText.y = 200;
game.addChild(powerText);
// Create clock
var clockBg = game.addChild(LK.getAsset('clockBg', {
anchorX: 0.5,
anchorY: 0.5,
x: GAME_WIDTH - 200,
y: 100
}));
var clockText = new Text2('12:00 AM', {
size: 50,
fill: 0xFFFFFF
});
clockText.anchor.set(0.5, 0.5);
clockText.x = clockBg.x;
clockText.y = clockBg.y;
game.addChild(clockText);
// Create night indicator
var nightText = new Text2('Night ' + currentNight, {
size: 70,
fill: 0xFFFFFF
});
nightText.anchor.set(0.5, 0.5);
nightText.x = GAME_WIDTH / 2;
nightText.y = 100;
game.addChild(nightText);
// Create door controls
var doorLeft = new DoorButton("left");
doorLeft.x = 150;
doorLeft.y = GAME_HEIGHT / 2;
game.addChild(doorLeft);
var doorRight = new DoorButton("right");
doorRight.x = GAME_WIDTH - 150;
doorRight.y = GAME_HEIGHT / 2;
game.addChild(doorRight);
// Create light controls
var lightLeft = new LightButton("left");
lightLeft.x = 150;
lightLeft.y = GAME_HEIGHT / 2 + 200;
game.addChild(lightLeft);
var lightRight = new LightButton("right");
lightRight.x = GAME_WIDTH - 150;
lightRight.y = GAME_HEIGHT / 2 + 200;
game.addChild(lightRight);
// Create door visuals
var leftDoor = game.addChild(LK.getAsset('door', {
anchorX: 0.5,
anchorY: 0,
x: 550,
y: GAME_HEIGHT - 800 / 2
}));
doors.left = leftDoor;
var rightDoor = game.addChild(LK.getAsset('door', {
anchorX: 0.5,
anchorY: 0,
x: GAME_WIDTH - 550,
y: GAME_HEIGHT - 800 / 2
}));
doors.right = rightDoor;
// Create warning lights
var warningLeft = game.addChild(LK.getAsset('warningLight', {
anchorX: 0.5,
anchorY: 0.5,
x: 550,
y: GAME_HEIGHT / 2
}));
warningLeft.visible = false;
warnings.left = warningLeft;
var warningRight = game.addChild(LK.getAsset('warningLight', {
anchorX: 0.5,
anchorY: 0.5,
x: GAME_WIDTH - 550,
y: GAME_HEIGHT / 2
}));
warningRight.visible = false;
warnings.right = warningRight;
// Create corridor light visuals as simple yellow rectangles
var corridorLightLeft = game.addChild(LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
x: 550,
y: GAME_HEIGHT / 2,
width: 400,
height: 800,
tint: 0xffff00
}));
corridorLightLeft.visible = false;
corridorLights.left = corridorLightLeft;
var corridorLightRight = game.addChild(LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
x: GAME_WIDTH - 550,
y: GAME_HEIGHT / 2,
width: 400,
height: 800,
tint: 0xffff00
}));
corridorLightRight.visible = false;
corridorLights.right = corridorLightRight;
// Create corridor animatronics
corridorAnimatronics.left = new AnimatronicCorridor("left");
corridorAnimatronics.left.x = 550;
corridorAnimatronics.left.y = GAME_HEIGHT / 2;
corridorAnimatronics.left.setVisible(false);
game.addChild(corridorAnimatronics.left);
corridorAnimatronics.right = new AnimatronicCorridor("right");
corridorAnimatronics.right.x = GAME_WIDTH - 550;
corridorAnimatronics.right.y = GAME_HEIGHT / 2;
corridorAnimatronics.right.setVisible(false);
game.addChild(corridorAnimatronics.right);
// Create start game instructions
var instructionText = new Text2("Click to start Night " + currentNight, {
size: 80,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = GAME_WIDTH / 2;
instructionText.y = GAME_HEIGHT / 2;
game.addChild(instructionText);
// Helper function to show camera
function showCamera(roomId) {
// Ensure camera view is visible
cameraView.visible = true;
// Make sure valid room is selected
if (roomId < 1 || roomId > rooms.length) {
roomId = 1; // Default to camera 1 if invalid
}
// Hide all rooms first
for (var i = 0; i < rooms.length; i++) {
rooms[i].visible = false;
}
// Hide corridor animatronics when switching cameras
if (corridorAnimatronics["left"]) {
corridorAnimatronics["left"].setVisible(false);
}
if (corridorAnimatronics["right"]) {
corridorAnimatronics["right"].setVisible(false);
}
// Show the selected room
rooms[roomId - 1].visible = true;
// Make sure the animatronic is shown correctly in this room
if (animatronicRoom === roomId) {
rooms[roomId - 1].setAnimatronic(true);
} else {
rooms[roomId - 1].setAnimatronic(false);
}
}
// Helper function to toggle camera view
function toggleCamera() {
isCameraActive = !isCameraActive;
if (isCameraActive) {
// Show camera view first
cameraView.visible = true;
cameraPanel.visible = true;
LK.getSound('camera').play();
cameraText.setText("CLOSE");
// Hide corridor animatronics when camera is active
if (corridorAnimatronics["left"]) {
corridorAnimatronics["left"].setVisible(false);
}
if (corridorAnimatronics["right"]) {
corridorAnimatronics["right"].setVisible(false);
}
// Show camera immediately to avoid black flash
showCamera(currentCamera);
powerDrain += 2; // Increased power drain for cameras
// Hide doors when camera view is active
if (doors.left) {
doors.left.visible = false;
}
if (doors.right) {
doors.right.visible = false;
}
} else {
// Hide camera view immediately
cameraView.visible = false;
cameraPanel.visible = false;
cameraText.setText("CAMERAS");
powerDrain -= 2; // Decreased by same amount when turning off
// Make sure corridor animatronics are visible/hidden correctly
if (corridorAnimatronics["left"]) {
corridorAnimatronics["left"].setVisible(animatronicController.corridorSide === "left" && animatronicController.inCorridor);
}
if (corridorAnimatronics["right"]) {
corridorAnimatronics["right"].setVisible(animatronicController.corridorSide === "right" && animatronicController.inCorridor);
}
// Show doors when returning to office view
if (doors.left) {
doors.left.visible = true;
}
if (doors.right) {
doors.right.visible = true;
}
}
}
// Update animatronic location function has been replaced by the AnimatronicController
// Handle power outage scenario
game.powerOutage = function powerOutage() {
if (gameOver) {
return;
}
gameOver = true;
// Turn off all lights
if (corridorLights["left"]) {
corridorLights["left"].visible = false;
}
if (corridorLights["right"]) {
corridorLights["right"].visible = false;
}
// Turn off warnings
if (warnings["left"]) {
warnings["left"].visible = false;
}
if (warnings["right"]) {
warnings["right"].visible = false;
}
// Hide camera view if active
if (isCameraActive) {
isCameraActive = false;
cameraView.visible = false;
cameraPanel.visible = false;
cameraText.setText("CAMERAS");
}
// Set screen to black
LK.effects.flashScreen(0x000000, 500, false);
// Play a sound if we have one for power outage
// Wait a random time between 2-7 seconds before jumpscare
var randomDelay = 2000 + Math.random() * 5000;
LK.setTimeout(function () {
// Make sure the blue and green cat appears for jumpscare
// Place cat in corridor
animatronicController.inCorridor = true;
animatronicController.corridorSide = Math.random() < 0.5 ? "left" : "right";
// Trigger jumpscare with the power outage flag
game.triggerJumpscare(true);
}, randomDelay);
};
// Trigger jumpscare - defined as a game method to be accessible from AnimatronicController
game.triggerJumpscare = function triggerJumpscare(isPowerOutage) {
if (gameOver && !isPowerOutage) {
return;
}
// Only check corridor condition if not a power outage
if (!isPowerOutage && !animatronicController.inCorridor) {
return;
}
gameOver = true;
// Record the time of successful attack for cooldown
animatronicController.lastAttackTime = gameTime;
LK.getSound('jumpscare').play();
// Make the blue and green cat appear in corridor before jumpscare
var corridorSide = animatronicController.corridorSide || (Math.random() < 0.5 ? "left" : "right");
// Hide cat from all cameras
for (var i = 0; i < rooms.length; i++) {
if (rooms[i]) {
rooms[i].setAnimatronic(false);
}
}
// Make cat visible in corridor
if (corridorAnimatronics[corridorSide]) {
corridorAnimatronics[corridorSide].setVisible(true);
// Force cat to be visible during jumpscare
corridorAnimatronics[corridorSide].alpha = 1;
// Turn on corridor light to make cat visible
if (corridorLights[corridorSide]) {
corridorLights[corridorSide].visible = true;
}
// Make sure the cat stays in corridor before jumpscare
animatronicController.inCorridor = true;
animatronicController.corridorSide = corridorSide;
}
// Deactivate cameras if they're active
if (isCameraActive) {
isCameraActive = false;
cameraView.visible = false;
cameraPanel.visible = false;
cameraText.setText("CAMERAS");
// Show doors when returning to office view
if (doors.left) {
doors.left.visible = true;
}
if (doors.right) {
doors.right.visible = true;
}
}
// Open both doors when jumpscared
if (doors.left && !doorLeft.isOpen) {
doorLeft.isOpen = true;
tween(doors.left, {
y: 2732 - doors.left.height / 2,
tint: 0x000000
}, {
duration: 300
});
}
if (doors.right && !doorRight.isOpen) {
doorRight.isOpen = true;
tween(doors.right, {
y: 2732 - doors.right.height / 2,
tint: 0x000000
}, {
duration: 300
});
}
// Create visible jumpscare animation with the animatronic
var jumpscare = game.addChild(new Container());
jumpscare.x = GAME_WIDTH / 2;
jumpscare.y = GAME_HEIGHT / 2;
// Add the cat animatronic to the jumpscare
var jumpscareAnimatronic = jumpscare.attachAsset('animatronic', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
// Make sure the jumpscare is visible
jumpscare.visible = true;
// Add jumpscare animation
tween(jumpscare, {
scaleX: 4.5,
scaleY: 4.5,
x: GAME_WIDTH / 2 + Math.random() * 100 - 50,
// Random movement
y: GAME_HEIGHT / 2 + Math.random() * 100 - 50 // Random movement
}, {
duration: 300,
easing: tween.outQuad
});
LK.effects.flashScreen(0xff0000, 500);
LK.setTimeout(function () {
// Reset night to 1 when player dies
storage.currentNight = 1;
LK.showGameOver();
}, 1500);
};
// Handle winning the night
function winNight() {
if (gameOver) {
return;
}
gameOver = true;
// Save progress
if (currentNight >= storage.highestNight) {
storage.highestNight = currentNight + 1;
}
storage.currentNight = currentNight + 1;
// Display winning message
var winText = new Text2("You survived until 6:00 AM! Night " + currentNight + " complete!", {
size: 80,
fill: 0xFFFFFF
});
winText.anchor.set(0.5, 0.5);
winText.x = GAME_WIDTH / 2;
winText.y = GAME_HEIGHT / 2;
game.addChild(winText);
LK.setTimeout(function () {
LK.showYouWin();
}, 3000);
}
// Event handlers
game.down = function (x, y, obj) {
if (!gameStarted) {
// Start game when clicked
gameStarted = true;
instructionText.visible = false;
LK.getSound('ambience').play();
LK.playMusic('backgroundMusic');
// Open doors when first night starts
if (doors.left) {
tween(doors.left, {
y: 2732 - doors.left.height / 2,
tint: 0x000000
}, {
duration: 300
});
doorLeft.isOpen = true;
}
if (doors.right) {
tween(doors.right, {
y: 2732 - doors.right.height / 2,
tint: 0x000000
}, {
duration: 300
});
doorRight.isOpen = true;
}
return;
}
// Handle camera toggle button
if (x >= toggleCameraBtn.x - toggleCameraBtn.width / 2 && x <= toggleCameraBtn.x + toggleCameraBtn.width / 2 && y >= toggleCameraBtn.y - toggleCameraBtn.height / 2 && y <= toggleCameraBtn.y + toggleCameraBtn.height / 2) {
toggleCamera();
}
};
// Game update loop
game.update = function () {
if (!gameStarted || gameOver) {
return;
}
// Update game time
gameTime += 16.67; // Approximate milliseconds per frame at 60fps
// Update clock (6 hours from 12AM to 6AM in game duration)
var gameProgress = Math.min(gameTime / GAME_DURATION, 1);
// Check if animatronic is about to start moving based on the controller's timing
var nearInitialMove = animatronicController && !animatronicController.hasStartedMoving && LK.ticks - animatronicController.gameStartTime >= animatronicController.initialDelay - 300 && LK.ticks - animatronicController.gameStartTime < animatronicController.initialDelay;
if (nearInitialMove) {
// Force the clock to show 12:50 AM right before the first movement
hour = 12;
minute = 50;
} else {
var hour = Math.floor(gameProgress * 6);
if (hour === 0) {
hour = 12; // 12 AM
} else {
hour = hour % 12;
if (hour === 0) {
hour = 6;
} // Cap at 6 AM
}
var minute = Math.floor(gameProgress * 6 % 1 * 60);
}
var ampm = "AM"; // Always AM between 12 AM and 6 AM
clockText.setText(hour + ":" + (minute < 10 ? "0" + minute : minute) + " " + ampm);
// Win condition - survive until 6AM
if (hour === 6 && minute === 0) {
winNight();
return;
}
// Update power
var closedDoorMultiplier = 1;
// Check if doors are closed and increase power drain
if (!doorLeft.isOpen && !doorRight.isOpen) {
closedDoorMultiplier = 2; // Both doors closed - double drain
} else if (!doorLeft.isOpen || !doorRight.isOpen) {
closedDoorMultiplier = 1.5; // One door closed - 50% more drain
}
// Check if lights are on and adjust power drain accordingly
var lightMultiplier = 1;
if (lightLeft.isOn && lightRight.isOn) {
lightMultiplier = 1.5; // Both lights on - 50% more drain
} else if (lightLeft.isOn || lightRight.isOn) {
lightMultiplier = 1.2; // One light on - 20% more drain
}
// Add camera multiplier
var cameraMultiplier = isCameraActive ? 1.3 : 1; // Camera uses 30% more power when active
power -= POWER_DRAIN_RATE * powerDrain * closedDoorMultiplier * lightMultiplier * cameraMultiplier;
power = Math.max(0, power);
var powerPercent = Math.floor(power);
powerText.setText("Power: " + powerPercent + "%");
powerBarFg.width = power / MAX_POWER * powerBarBg.width;
// Game over if power runs out
if (power <= 0) {
game.powerOutage();
return;
}
// Update animatronic controller
animatronicController.update(16.67);
// Update warning lights visibility based on light button state
if (animatronicAtDoor === "left" && lightLeft.isOn) {
warningLeft.visible = true;
// Play warning sound occasionally when animatronic is spotted
if (LK.ticks % 120 === 0) {
// Approximately every 2 seconds
LK.getSound('warning').play({
volume: 0.5
});
}
} else {
warningLeft.visible = false;
}
if (animatronicAtDoor === "right" && lightRight.isOn) {
warningRight.visible = true;
// Play warning sound occasionally when animatronic is spotted
if (LK.ticks % 120 === 0) {
// Approximately every 2 seconds
LK.getSound('warning').play({
volume: 0.5
});
}
} else {
warningRight.visible = false;
}
// Visual cue when animatronic is moving between cameras
if (LK.ticks % 900 === 0 && isCameraActive) {
// Every 15 seconds during camera view
// No flashing effect
}
// Add special visual effects when player is viewing the camera that contains the animatronic
// but only for cameras other than the main entrance (camera 1)
if (isCameraActive && currentCamera === animatronicRoom && rooms[animatronicRoom - 1] && rooms[animatronicRoom - 1].hasAnimatronic && currentCamera !== 1) {
// Create occasional glitching/interference effect when looking directly at the animatronic
if (LK.ticks % 120 === 0) {
// Every 2 seconds
// Don't flash red on any camera to make them more usable
// Don't play warning sounds on any camera
}
}
};
An anthropomorphic blue and green cat animatronic wearing rockstar attire. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Metal door. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Two doorways. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Pet store. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows