User prompt
ama biz dolaba saklandığımızda bizi görmesin ama biz saklanmazsak bize saldırıp canımızı azaltsın ve yukarda can barımız olsun
User prompt
her 15 saniyede bir giriş kapısından hayalet gelsin, kapı açılıp geri kapansın ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
üst katta bir dolap olsun ve dolaba basınca karakter dolabın içine saklansın
User prompt
karakter sadece merdivenden yukarı çıkabilsin başka türlü çıkamasın
User prompt
karakterimiz merdiven hariç hiç bir şekilde üst kata çıkamasın ve üst kata iki oda olsun
User prompt
iki katın arasındaki boşluk olmasın ve merdiven üzerinde yürüyebiliceğimiz bir merdiven olsun
User prompt
şimdi öncelikle karakter evin duvarlarından dışarıya çıkamasın ve birinci kattan ikinci kata bir merdiven olsun
User prompt
ev ekranı kaplayacak büyüklükte olsun
User prompt
hava sisli olmasın ama ev daha büyük olsun
User prompt
öncelikle bir ev olsun ev bodrum katı hariç 2 katlı olsun bodrum katının kapısı kilitli olsun evin çıkış kapısı da kilitli olsun korku oyunu yapacağım için hava biraz sisli olsun
User prompt
Dark House Explorer
Initial prompt
bana bir ev yap ev iki katı olsun ha bide korku oyunu yapacağım için biraz karanlık olsun
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var BasementGhost = Container.expand(function () { var self = Container.call(this); var ghostGraphics = self.attachAsset('ghost', { anchorX: 0.5, anchorY: 0.5 }); self.speed = currentGhostSpeed; self.alpha = 0.8; ghostGraphics.alpha = 0.8; self.lastAttackTime = 0; self.update = function () { // Only update if in basement scene if (currentScene !== 'basement') { return; } // Move towards player var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } // Attack player if close enough if (distance < 70) { var currentTime = LK.ticks; if (currentTime - self.lastAttackTime > 60) { // Attack once per second playerHealth -= 10; self.lastAttackTime = currentTime; updateHealthBar(); // Flash player red when damaged LK.effects.flashObject(player, 0xff0000, 500); // Create blood effect at player position createBloodEffect(player.x, player.y); // Check if player is dead if (playerHealth <= 0) { LK.showGameOver(); return; } } } }; return self; }); var BloodEffect = Container.expand(function () { var self = Container.call(this); var bloodGraphics = self.attachAsset('blood', { anchorX: 0.5, anchorY: 0.5 }); self.lifeTime = 300; // 5 seconds at 60fps self.currentLife = 0; self.update = function () { self.currentLife++; // Fade out over time self.alpha = 1 - self.currentLife / self.lifeTime; // Remove after lifetime if (self.currentLife >= self.lifeTime) { self.destroy(); for (var i = bloodEffects.length - 1; i >= 0; i--) { if (bloodEffects[i] === self) { bloodEffects.splice(i, 1); break; } } } }; return self; }); var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.direction = { x: 0, y: 0 }; self.update = function () { // Only update if in basement scene if (currentScene !== 'basement') { return; } // Move bullet in direction self.x += self.direction.x * self.speed; self.y += self.direction.y * self.speed; // Remove bullet if it goes off screen if (self.x < 0 || self.x > 2048 || self.y < 1800 || self.y > 2480) { self.destroy(); for (var i = bullets.length - 1; i >= 0; i--) { if (bullets[i] === self) { bullets.splice(i, 1); break; } } } // Check collision with basement ghosts for (var i = basementGhosts.length - 1; i >= 0; i--) { var ghost = basementGhosts[i]; if (self.intersects(ghost)) { // Create blood effect at ghost position createBloodEffect(ghost.x, ghost.y); // Increment kill count ghostKillCount++; // Increase speed every 20 kills if (ghostKillCount % 20 === 0) { currentGhostSpeed += 1; } // Remove ghost ghost.destroy(); basementGhosts.splice(i, 1); // Remove bullet self.destroy(); for (var j = bullets.length - 1; j >= 0; j--) { if (bullets[j] === self) { bullets.splice(j, 1); break; } } break; } } // Check collision with regular house ghosts for (var i = ghosts.length - 1; i >= 0; i--) { var ghost = ghosts[i]; if (self.intersects(ghost)) { // Create blood effect at ghost position createBloodEffect(ghost.x, ghost.y); // Increment kill count ghostKillCount++; // Increase speed every 20 kills if (ghostKillCount % 20 === 0) { currentGhostSpeed += 1; } // Remove ghost ghost.destroy(); ghosts.splice(i, 1); currentGhost = null; ghostSpawnTimer = 0; // Remove bullet self.destroy(); for (var j = bullets.length - 1; j >= 0; j--) { if (bullets[j] === self) { bullets.splice(j, 1); break; } } break; } } // Check collision with final boss if (finalBoss && finalBossActive && self.intersects(finalBoss)) { // Create blood effect at boss position createBloodEffect(finalBoss.x, finalBoss.y); // Increment player shot count playerShotCount++; // Damage boss finalBoss.health--; // Check if boss is defeated if (playerShotCount >= 25) { // Boss defeated - drop exit key if (!exitKey) { exitKey = game.addChild(LK.getAsset('key', { anchorX: 0.5, anchorY: 0.5 })); exitKey.x = finalBoss.x; exitKey.y = finalBoss.y; exitKey.visible = true; } finalBoss.destroy(); finalBoss = null; finalBossActive = false; // Flash green to indicate boss defeated LK.effects.flashScreen(0x00ff00, 1000); } // Remove bullet self.destroy(); for (var j = bullets.length - 1; j >= 0; j--) { if (bullets[j] === self) { bullets.splice(j, 1); break; } } } }; return self; }); var FinalBoss = Container.expand(function () { var self = Container.call(this); var bossGraphics = self.attachAsset('monster', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; // Very fast boss self.health = 40; self.lastAttackTime = 0; self.update = function () { // Only update if boss is active if (!finalBossActive || currentScene !== 'basement') { return; } // Move towards player var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } // Attack player if close enough - deal 50 damage if (distance < 80) { var currentTime = LK.ticks; if (currentTime - self.lastAttackTime > 60) { // Attack once per second - deal 50 damage playerHealth -= 50; self.lastAttackTime = currentTime; updateHealthBar(); // Flash player red when damaged LK.effects.flashObject(player, 0xff0000, 500); // Create blood effect at player position createBloodEffect(player.x, player.y); // Check if player is dead if (playerHealth <= 0) { LK.showGameOver(); return; } } } }; return self; }); var Ghost = Container.expand(function () { var self = Container.call(this); var ghostGraphics = self.attachAsset('ghost', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 2; self.alpha = 0.7; ghostGraphics.alpha = 0.7; self.searchTimer = 0; self.maxSearchTime = 300; // 5 seconds at 60fps self.isLeaving = false; self.update = function () { // Don't update ghost if player is in room scene if (currentScene === 'room') { return; } // Only increment search timer when player is hidden if (playerHidden) { self.searchTimer++; } // Move ghost towards player if not leaving if (!self.isLeaving) { var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (!playerHidden && distance > 0) { // Chase player if not hidden self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } else if (playerHidden && distance > 0) { // Move randomly when player is hidden self.x += (Math.random() - 0.5) * 4; self.y += (Math.random() - 0.5) * 4; } // Attack player if close enough and player is not hidden if (distance < 80 && !playerHidden) { // Damage player if (self.lastAttackTime === undefined) self.lastAttackTime = 0; var currentTime = LK.ticks; if (currentTime - self.lastAttackTime > 60) { // Attack once per second playerHealth -= 10; self.lastAttackTime = currentTime; updateHealthBar(); // Flash player red when damaged LK.effects.flashObject(player, 0xff0000, 500); // Create blood effect at player position createBloodEffect(player.x, player.y); // Check if player is dead if (playerHealth <= 0) { LK.showGameOver(); return; } // After dealing damage, ghost starts leaving self.isLeaving = true; } } } // If ghost hasn't found player after 5 seconds of searching (while player is hidden), start leaving if (self.searchTimer >= self.maxSearchTime && playerHidden && !self.isLeaving) { self.isLeaving = true; self.speed = 3; // Move faster when leaving } // If leaving, move towards entrance door if (self.isLeaving) { var doorX = house.entranceDoor.x + 40; var doorY = house.entranceDoor.y + 60; var dx = doorX - self.x; var dy = doorY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } // Remove ghost when it reaches the door if (distance < 30) { self.destroy(); currentGhost = null; ghostSpawnTimer = 0; for (var i = ghosts.length - 1; i >= 0; i--) { if (ghosts[i] === self) { ghosts.splice(i, 1); break; } } } } // Remove ghost if it goes off screen if (self.x < -100 || self.x > 2148 || self.y < -100 || self.y > 2832) { self.destroy(); currentGhost = null; ghostSpawnTimer = 0; for (var i = ghosts.length - 1; i >= 0; i--) { if (ghosts[i] === self) { ghosts.splice(i, 1); break; } } } }; return self; }); var House = Container.expand(function () { var self = Container.call(this); // Basement floor var basementWall = self.attachAsset('houseWall', { x: 0, y: 1800 }); var basementFloor = self.attachAsset('houseFloor', { x: 0, y: 2400 }); // Ground floor var groundFloorWall = self.attachAsset('houseWall', { x: 0, y: 1200 }); var groundFloor = self.attachAsset('houseFloor', { x: 0, y: 1800 }); // Second floor var secondFloorWall = self.attachAsset('houseWall', { x: 0, y: 600 }); var secondFloor = self.attachAsset('houseFloor', { x: 0, y: 1200 }); // Stairs connecting floors - make them walkable var stairway = self.attachAsset('stairs', { x: 974, y: 1200, width: 100, height: 600 }); // Second floor room dividers var roomWall1 = self.attachAsset('houseWall', { x: 1024, y: 600, width: 20, height: 600 }); var roomWall2 = self.attachAsset('houseWall', { x: 0, y: 900, width: 1024, height: 20 }); var roomWall3 = self.attachAsset('houseWall', { x: 1044, y: 900, width: 1004, height: 20 }); // Floor barriers to prevent jumping between floors (except stairs) var floorBarrierLeft = self.attachAsset('houseWall', { x: 0, y: 1200, width: 974, height: 20 }); var floorBarrierRight = self.attachAsset('houseWall', { x: 1074, y: 1200, width: 974, height: 20 }); // Store barrier references for collision detection self.roomWall1 = roomWall1; self.roomWall2 = roomWall2; self.roomWall3 = roomWall3; self.floorBarrierLeft = floorBarrierLeft; self.floorBarrierRight = floorBarrierRight; // Windows var window1 = self.attachAsset('window', { x: 300, y: 700 }); var window2 = self.attachAsset('window', { x: 800, y: 700 }); var window3 = self.attachAsset('window', { x: 1200, y: 700 }); var window4 = self.attachAsset('window', { x: 1600, y: 700 }); var window5 = self.attachAsset('window', { x: 300, y: 1300 }); var window6 = self.attachAsset('window', { x: 800, y: 1300 }); var window7 = self.attachAsset('window', { x: 1200, y: 1300 }); var window8 = self.attachAsset('window', { x: 1600, y: 1300 }); // Exit door (locked) var exitDoor = self.attachAsset('door', { x: 1900, y: 1620 }); var exitLock = self.attachAsset('lock', { x: 1970, y: 1660 }); // Basement door (locked) var basementDoor = self.attachAsset('door', { x: 100, y: 1620 }); var basementLock = self.attachAsset('lock', { x: 170, y: 1660 }); // Closet on second floor var closet = self.attachAsset('closet', { x: 1800, y: 680 }); // Upper floor door on the ground var upperDoor = self.attachAsset('door', { x: 500, y: 1120 }); // Entrance door var entranceDoor = self.attachAsset('door', { x: 50, y: 1620 }); // Store door and closet references for game logic self.exitDoor = exitDoor; self.basementDoor = basementDoor; self.entranceDoor = entranceDoor; self.upperDoor = upperDoor; self.closet = closet; self.exitLocked = true; self.basementLocked = true; return self; }); var Monster = Container.expand(function () { var self = Container.call(this); var monsterGraphics = self.attachAsset('monster', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3; self.lastAttackTime = 0; self.update = function () { // Only update if in room scene if (currentScene !== 'room') { return; } // Move towards player var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } // Attack player if close enough if (distance < 60) { var currentTime = LK.ticks; if (currentTime - self.lastAttackTime > 120) { // Attack every 2 seconds playerHealth -= 50; self.lastAttackTime = currentTime; updateHealthBar(); // Flash player red when damaged LK.effects.flashObject(player, 0xff0000, 500); // Create blood effect at player position createBloodEffect(player.x, player.y); // Check if player is dead if (playerHealth <= 0) { LK.showGameOver(); return; } } } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3; return self; }); var Room = Container.expand(function () { var self = Container.call(this); // Create room floor var roomFloor = self.attachAsset('houseFloor', { x: 0, y: 1200 }); // Create room walls var roomWallLeft = self.attachAsset('houseWall', { x: 0, y: 600, width: 20, height: 600 }); var roomWallRight = self.attachAsset('houseWall', { x: 2028, y: 600, width: 20, height: 600 }); var roomWallTop = self.attachAsset('houseWall', { x: 0, y: 600, width: 2048, height: 20 }); var roomWallBottom = self.attachAsset('houseWall', { x: 0, y: 1200, width: 2048, height: 20 }); // Exit door back to house var exitDoor = self.attachAsset('door', { x: 1000, y: 1120 }); // Basement key in bottom corner var basementKey = self.attachAsset('key', { x: 50, y: 1150, anchorX: 0.5, anchorY: 0.5 }); // Store door and key references self.exitDoor = exitDoor; self.basementKey = basementKey; return self; }); /**** * Initialize Game ****/ // Set dark atmospheric background var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // House structure assets // Set dark atmospheric background game.setBackgroundColor(0x0a0a0a); // Create the two-story house var house = game.addChild(new House()); // Position house to fill entire screen house.x = 0; house.y = 0; // Create player var player = game.addChild(new Player()); player.x = 2048 / 2; player.y = 1750; // Start on ground floor // Variables for player movement var dragNode = null; // Game state variables var gameStarted = false; var playerHidden = false; var originalPlayerAlpha = 1; var ghosts = []; var ghostSpawnTimer = 0; var currentGhost = null; var ghostSearchTimer = 0; var playerHealth = 100; var maxHealth = 100; var currentScene = 'house'; // 'house' or 'room' var roomScene = null; var roomMonster = null; var hasBasementKey = false; var playerWeapon = null; var basementGhosts = []; var totalBasementGhosts = 120; var spawnedBasementGhosts = 0; var basementGhostSpawnTimer = 0; var ghostsPerWave = 5; var bullets = []; var bloodEffects = []; var lastShootTime = 0; var ghostKillCount = 0; var currentGhostSpeed = 2; var finalBoss = null; var finalBossHealth = 40; var finalBossActive = false; var playerShotCount = 0; var hasExitKey = false; var exitKey = null; // Create health bar var healthBarBg = new Text2('', { size: 25, fill: 0x333333 }); healthBarBg.anchor.set(0.5, 0); healthBarBg.x = 0; healthBarBg.y = 150; LK.gui.top.addChild(healthBarBg); var healthBarFill = new Text2('', { size: 25, fill: 0xff0000 }); healthBarFill.anchor.set(0, 0); healthBarFill.x = -125; healthBarFill.y = 150; LK.gui.top.addChild(healthBarFill); var healthText = new Text2('Health: 100/100', { size: 25, fill: 0xffffff }); healthText.anchor.set(0.5, 0); healthText.x = 0; healthText.y = 175; LK.gui.top.addChild(healthText); // Function to update health bar function updateHealthBar() { var healthPercent = Math.max(0, playerHealth / maxHealth); var barWidth = Math.floor(250 * healthPercent); healthBarBg.setText('█████████████████████████'); healthBarFill.setText('█'.repeat(Math.max(0, Math.floor(25 * healthPercent)))); healthText.setText('Health: ' + Math.max(0, playerHealth) + '/' + maxHealth); } // Initialize health bar updateHealthBar(); // Touch controls for player movement game.down = function (x, y, obj) { // Check if we're in the house scene and clicked on upper floor door if (currentScene === 'house') { var upperDoorBounds = { x: house.upperDoor.x, y: house.upperDoor.y, width: 80, height: 120 }; if (x >= upperDoorBounds.x && x <= upperDoorBounds.x + upperDoorBounds.width && y >= upperDoorBounds.y && y <= upperDoorBounds.y + upperDoorBounds.height) { // Check if player is standing near the door var playerDistance = Math.sqrt((player.x - (house.upperDoor.x + 40)) * (player.x - (house.upperDoor.x + 40)) + (player.y - (house.upperDoor.y + 60)) * (player.y - (house.upperDoor.y + 60))); if (playerDistance < 60) { // Switch to room scene switchToRoom(); } return; } } // Check if we're in the room scene and clicked on exit door if (currentScene === 'room' && roomScene) { var roomExitBounds = { x: roomScene.exitDoor.x, y: roomScene.exitDoor.y, width: 80, height: 120 }; if (x >= roomExitBounds.x && x <= roomExitBounds.x + roomExitBounds.width && y >= roomExitBounds.y && y <= roomExitBounds.y + roomExitBounds.height) { // Check if player is standing near the door var playerDistance = Math.sqrt((player.x - (roomScene.exitDoor.x + 40)) * (player.x - (roomScene.exitDoor.x + 40)) + (player.y - (roomScene.exitDoor.y + 60)) * (player.y - (roomScene.exitDoor.y + 60))); if (playerDistance < 60) { // Switch back to house scene switchToHouse(); } return; } // Check if clicked on basement key if (roomScene.basementKey && roomScene.basementKey.visible) { var keyBounds = { x: roomScene.basementKey.x - 20, y: roomScene.basementKey.y - 10, width: 40, height: 20 }; if (x >= keyBounds.x && x <= keyBounds.x + keyBounds.width && y >= keyBounds.y && y <= keyBounds.y + keyBounds.height) { // Check if player is standing on the key var playerDistance = Math.sqrt((player.x - roomScene.basementKey.x) * (player.x - roomScene.basementKey.x) + (player.y - roomScene.basementKey.y) * (player.y - roomScene.basementKey.y)); if (playerDistance < 50) { // Collect the key hasBasementKey = true; roomScene.basementKey.visible = false; // Flash key collected effect LK.effects.flashScreen(0x00ff00, 500); } return; } } } // Check if clicked on basement door var basementDoorBounds = { x: house.basementDoor.x, y: house.basementDoor.y, width: 80, height: 120 }; if (x >= basementDoorBounds.x && x <= basementDoorBounds.x + basementDoorBounds.width && y >= basementDoorBounds.y && y <= basementDoorBounds.y + basementDoorBounds.height) { // Check if player has basement key and is close to door if (hasBasementKey) { var playerDistance = Math.sqrt((player.x - (house.basementDoor.x + 40)) * (player.x - (house.basementDoor.x + 40)) + (player.y - (house.basementDoor.y + 60)) * (player.y - (house.basementDoor.y + 60))); if (playerDistance < 60) { // Open basement door - unlock it and make lock invisible house.basementLocked = false; // Find and hide the basement lock for (var i = 0; i < house.children.length; i++) { if (house.children[i] === house.basementDoor.parent.children.find(function (child) { return child.x === 170 && child.y === 1660; })) { house.children[i].visible = false; break; } } // Flash green to indicate door is now open LK.effects.flashScreen(0x00ff00, 1000); // Use the key (remove it from inventory) hasBasementKey = false; } } else if (!house.basementLocked) { // Door is already unlocked, allow entry to basement var playerDistance = Math.sqrt((player.x - (house.basementDoor.x + 40)) * (player.x - (house.basementDoor.x + 40)) + (player.y - (house.basementDoor.y + 60)) * (player.y - (house.basementDoor.y + 60))); if (playerDistance < 60) { // Enter basement - move player down to basement level switchToBasement(); } } return; // Don't allow dragging when interacting with door } // Check if clicked on exit key (if it exists) if (exitKey && exitKey.visible) { var keyBounds = { x: exitKey.x - 20, y: exitKey.y - 10, width: 40, height: 20 }; if (x >= keyBounds.x && x <= keyBounds.x + keyBounds.width && y >= keyBounds.y && y <= keyBounds.y + keyBounds.height) { // Check if player is standing on the key var playerDistance = Math.sqrt((player.x - exitKey.x) * (player.x - exitKey.x) + (player.y - exitKey.y) * (player.y - exitKey.y)); if (playerDistance < 50) { // Collect the exit key hasExitKey = true; exitKey.visible = false; // Flash key collected effect LK.effects.flashScreen(0x00ff00, 500); } return; } } // Check if clicked on exit door var exitDoorBounds = { x: house.exitDoor.x, y: house.exitDoor.y, width: 80, height: 120 }; if (x >= exitDoorBounds.x && x <= exitDoorBounds.x + exitDoorBounds.width && y >= exitDoorBounds.y && y <= exitDoorBounds.y + exitDoorBounds.height) { // Check if player has exit key and is close to door if (hasExitKey) { var playerDistance = Math.sqrt((player.x - (house.exitDoor.x + 40)) * (player.x - (house.exitDoor.x + 40)) + (player.y - (house.exitDoor.y + 60)) * (player.y - (house.exitDoor.y + 60))); if (playerDistance < 60) { // Open exit door and win the game LK.effects.flashScreen(0x00ff00, 1000); LK.showYouWin(); } } return; } // Check if clicked on closet var closetBounds = { x: house.closet.x, y: house.closet.y, width: 80, height: 120 }; if (x >= closetBounds.x && x <= closetBounds.x + closetBounds.width && y >= closetBounds.y && y <= closetBounds.y + closetBounds.height) { // Check if player is standing near the closet var playerDistance = Math.sqrt((player.x - (house.closet.x + 40)) * (player.x - (house.closet.x + 40)) + (player.y - (house.closet.y + 60)) * (player.y - (house.closet.y + 60))); if (playerDistance < 60) { // Toggle hiding in closet if (!playerHidden) { // Hide player in closet player.x = closetBounds.x + closetBounds.width / 2; player.y = closetBounds.y + closetBounds.height / 2; player.alpha = 0.3; // Make player semi-transparent playerHidden = true; return; // Don't set drag node when hiding } else { // Come out of closet player.alpha = originalPlayerAlpha; playerHidden = false; return; // Don't set drag node when coming out } } } // Check if player has weapon - shoot bullet if (playerWeapon && playerWeapon.visible) { var currentTime = LK.ticks; if (currentTime - lastShootTime > 15) { // Limit shooting rate lastShootTime = currentTime; shootBullet(x, y); } } // Only allow dragging if not hidden if (!playerHidden) { dragNode = player; } // Apply collision boundaries to keep player inside house walls var newX = x; var newY = y; // Horizontal boundaries (house walls at x=0 and x=2048) if (newX < 20) newX = 20; // Left wall boundary if (newX > 2028) newX = 2028; // Right wall boundary // Vertical boundaries if (newY < 620) newY = 620; // Top of second floor if (newY > 2480) newY = 2480; // Bottom of basement // Prevent basement access if door is still locked if (newY > 1800 && house.basementLocked) newY = 1800; // Bottom of ground floor - prevent basement access if locked // Restrict basement movement - only allow going up through door area if (currentScene === 'basement' && newY < 1800) { // Only allow going up if player is near basement door var doorX = house.basementDoor.x + 40; if (newX < doorX - 60 || newX > doorX + 60) { newY = 1800; // Keep in basement if not near door } } // Floor barrier collision - prevent jumping between floors except via stairs // Strict floor separation - only allow movement between floors in stairs area if (player.y <= 1200 && newY > 1200) { // Player trying to move from second floor to ground floor if (newX < 974 || newX > 1074) { // Not in stairs area - block movement newY = 1200; // Keep on second floor } } else if (player.y > 1200 && newY <= 1200) { // Player trying to move from ground floor to second floor if (newX < 974 || newX > 1074) { // Not in stairs area - block movement newY = 1201; // Keep on ground floor } } // Second floor room wall collisions if (newY >= 600 && newY <= 1200) { // Vertical room divider at x=1024 if (newX > 1024 && newX < 1044 && newY >= 600 && newY <= 1200) { if (player.x <= 1024) { newX = 1024; } else { newX = 1044; } } // Horizontal room dividers at y=900 if (newY > 900 && newY < 920) { if (newX < 1024 || newX > 1044) { if (player.y <= 900) { newY = 900; } else { newY = 920; } } } } player.x = newX; player.y = newY; }; game.move = function (x, y, obj) { if (dragNode && !playerHidden) { // Apply collision boundaries to keep player inside house walls var newX = x; var newY = y; // Horizontal boundaries (house walls at x=0 and x=2048) if (newX < 20) newX = 20; // Left wall boundary if (newX > 2028) newX = 2028; // Right wall boundary // Vertical boundaries if (newY < 620) newY = 620; // Top of second floor if (newY > 2480) newY = 2480; // Bottom of basement // Prevent basement access if door is still locked if (newY > 1800 && house.basementLocked) newY = 1800; // Bottom of ground floor - prevent basement access if locked // Restrict basement movement - only allow going up through door area if (currentScene === 'basement' && newY < 1800) { // Only allow going up if player is near basement door var doorX = house.basementDoor.x + 40; if (newX < doorX - 60 || newX > doorX + 60) { newY = 1800; // Keep in basement if not near door } } // Floor barrier collision - prevent jumping between floors except via stairs // Strict floor separation - only allow movement between floors in stairs area if (dragNode.y <= 1200 && newY > 1200) { // Player trying to move from second floor to ground floor if (newX < 974 || newX > 1074) { // Not in stairs area - block movement newY = 1200; // Keep on second floor } } else if (dragNode.y > 1200 && newY <= 1200) { // Player trying to move from ground floor to second floor if (newX < 974 || newX > 1074) { // Not in stairs area - block movement newY = 1201; // Keep on ground floor } } // Second floor room wall collisions if (newY >= 600 && newY <= 1200) { // Vertical room divider at x=1024 if (newX > 1024 && newX < 1044 && newY >= 600 && newY <= 1200) { if (dragNode.x <= 1024) { newX = 1024; } else { newX = 1044; } } // Horizontal room dividers at y=900 if (newY > 900 && newY < 920) { if (newX < 1024 || newX > 1044) { if (dragNode.y <= 900) { newY = 900; } else { newY = 920; } } } } dragNode.x = newX; dragNode.y = newY; } }; game.up = function (x, y, obj) { dragNode = null; }; // Player floor tracking var playerFloor = 1; // 1 = ground floor, 2 = second floor // Game update loop for stair interaction game.update = function () { // Check if player is on stairs area (walkable stairs) var stairLeft = 974; var stairRight = 974 + 100; var stairTop = 1200; var stairBottom = 1800; // Determine current floor based on Y position if (player.y <= 1200) { playerFloor = 2; // Second floor } else if (player.y >= 1800) { playerFloor = 0; // Basement } else if (player.y >= 1200) { playerFloor = 1; // Ground floor } // Allow player to walk freely on stairs - no special collision needed // as stairs are now part of the walkable area between floors // Update collision boundaries - allow movement between floors via stairs if (player.y > 2480) player.y = 2480; // Bottom boundary - basement floor // Prevent basement access if door is still locked if (player.y > 1800 && house.basementLocked) player.y = 1800; // Bottom of ground floor - prevent basement access if locked if (player.y < 620) player.y = 620; // Top boundary // Update weapon position to follow player if (playerWeapon && playerWeapon.visible) { playerWeapon.x = player.x + 40; playerWeapon.y = player.y; // Auto-shoot at nearby ghosts var currentTime = LK.ticks; if (currentTime - lastShootTime > 30) { // Limit shooting rate // Find closest ghost within shooting range var closestGhost = null; var closestDistance = 300; // Detection range // Check basement ghosts for (var i = 0; i < basementGhosts.length; i++) { var ghost = basementGhosts[i]; var dx = ghost.x - player.x; var dy = ghost.y - player.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < closestDistance) { closestGhost = ghost; closestDistance = distance; } } // Check regular house ghosts for (var i = 0; i < ghosts.length; i++) { var ghost = ghosts[i]; var dx = ghost.x - player.x; var dy = ghost.y - player.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < closestDistance) { closestGhost = ghost; closestDistance = distance; } } // Check final boss if (finalBoss && finalBossActive) { var dx = finalBoss.x - player.x; var dy = finalBoss.y - player.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < closestDistance) { closestGhost = finalBoss; closestDistance = distance; } } // Shoot at closest ghost if found if (closestGhost) { lastShootTime = currentTime; shootBullet(closestGhost.x, closestGhost.y); } } } // Ghost spawning system - every 15 seconds (900 ticks at 60fps) - only if boss not active if (!finalBossActive) { ghostSpawnTimer++; if (ghostSpawnTimer >= 900) { ghostSpawnTimer = 0; spawnGhost(); } } // Basement ghost spawning - spawn 5 ghosts every 8 seconds if in basement - only if boss not active if (currentScene === 'basement' && spawnedBasementGhosts < totalBasementGhosts && !finalBossActive) { basementGhostSpawnTimer++; if (basementGhostSpawnTimer >= 480) { // 8 seconds at 60fps basementGhostSpawnTimer = 0; spawnBasementGhosts(); } } // Spawn final boss when 120 ghosts are killed if (ghostKillCount >= 120 && !finalBossActive && !finalBoss) { spawnFinalBoss(); } }; // Ghost spawning function function spawnGhost() { // Only spawn if no ghost currently exists if (currentGhost === null) { // Animate door opening tween(house.entranceDoor, { scaleX: 0.1 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { // Create ghost at entrance door var ghost = new Ghost(); ghost.x = house.entranceDoor.x + 40; ghost.y = house.entranceDoor.y + 60; ghosts.push(ghost); game.addChild(ghost); currentGhost = ghost; // Close door after ghost spawns tween(house.entranceDoor, { scaleX: 1 }, { duration: 300, easing: tween.easeIn }); } }); } } // Scene switching functions function switchToRoom() { currentScene = 'room'; // Hide house house.visible = false; // Create and show room if it doesn't exist if (!roomScene) { roomScene = game.addChild(new Room()); } roomScene.visible = true; // Create monster if it doesn't exist if (!roomMonster) { roomMonster = game.addChild(new Monster()); roomMonster.x = 100; roomMonster.y = 1150; } roomMonster.visible = true; // Position player in the room player.x = 1024; player.y = 900; } function switchToHouse() { currentScene = 'house'; // Hide room if (roomScene) { roomScene.visible = false; } // Hide monster if (roomMonster) { roomMonster.visible = false; } // Hide weapon when leaving basement if (playerWeapon) { playerWeapon.visible = false; } // Show house house.visible = true; // Position player back at upper floor door player.x = 500; player.y = 1050; } function switchToBasement() { currentScene = 'basement'; // Move player down to basement level player.y = 2300; // Position player in basement area // Give player a weapon if (!playerWeapon) { playerWeapon = game.addChild(LK.getAsset('weapon', { anchorX: 0.5, anchorY: 0.5 })); } playerWeapon.visible = true; // Initialize basement ghost spawning spawnedBasementGhosts = 0; basementGhostSpawnTimer = 0; basementGhosts = []; // Flash screen to indicate transition LK.effects.flashScreen(0x444444, 500); } // Function to spawn basement ghosts in waves function spawnBasementGhosts() { var ghostsToSpawn = Math.min(ghostsPerWave, totalBasementGhosts - spawnedBasementGhosts); for (var i = 0; i < ghostsToSpawn; i++) { var ghost = new BasementGhost(); // Spawn ghosts only from the front (top side) - directly in front of player ghost.x = 100 + Math.random() * 1848; ghost.y = 1850; basementGhosts.push(ghost); game.addChild(ghost); spawnedBasementGhosts++; } } // Function to shoot bullet towards target position function shootBullet(targetX, targetY) { var bullet = new Bullet(); bullet.x = player.x; bullet.y = player.y; // Calculate direction to target var dx = targetX - player.x; var dy = targetY - player.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { bullet.direction.x = dx / distance; bullet.direction.y = dy / distance; } bullets.push(bullet); game.addChild(bullet); } // Function to create blood effect function createBloodEffect(x, y) { var blood = new BloodEffect(); blood.x = x; blood.y = y; bloodEffects.push(blood); game.addChild(blood); } // Function to spawn final boss function spawnFinalBoss() { // Kill all existing ghosts for (var i = basementGhosts.length - 1; i >= 0; i--) { basementGhosts[i].destroy(); basementGhosts.splice(i, 1); } for (var i = ghosts.length - 1; i >= 0; i--) { ghosts[i].destroy(); ghosts.splice(i, 1); } currentGhost = null; ghostSpawnTimer = 0; // Force switch to basement scene switchToBasement(); // Create final boss finalBoss = game.addChild(new FinalBoss()); finalBoss.x = 200; finalBoss.y = 2200; finalBossActive = true; playerShotCount = 0; // Flash screen red to indicate boss arrival LK.effects.flashScreen(0xff0000, 1000); // Make sure player has weapon if (!playerWeapon) { playerWeapon = game.addChild(LK.getAsset('weapon', { anchorX: 0.5, anchorY: 0.5 })); } playerWeapon.visible = true; } // Display instructions var instructionText = new Text2('Explore the haunted house\nUse stairs to move between floors\nExit and basement doors are locked', { size: 50, fill: 0xCCCCCC }); instructionText.anchor.set(0.5, 0); LK.gui.top.addChild(instructionText); ;
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BasementGhost = Container.expand(function () {
var self = Container.call(this);
var ghostGraphics = self.attachAsset('ghost', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = currentGhostSpeed;
self.alpha = 0.8;
ghostGraphics.alpha = 0.8;
self.lastAttackTime = 0;
self.update = function () {
// Only update if in basement scene
if (currentScene !== 'basement') {
return;
}
// Move towards player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
// Attack player if close enough
if (distance < 70) {
var currentTime = LK.ticks;
if (currentTime - self.lastAttackTime > 60) {
// Attack once per second
playerHealth -= 10;
self.lastAttackTime = currentTime;
updateHealthBar();
// Flash player red when damaged
LK.effects.flashObject(player, 0xff0000, 500);
// Create blood effect at player position
createBloodEffect(player.x, player.y);
// Check if player is dead
if (playerHealth <= 0) {
LK.showGameOver();
return;
}
}
}
};
return self;
});
var BloodEffect = Container.expand(function () {
var self = Container.call(this);
var bloodGraphics = self.attachAsset('blood', {
anchorX: 0.5,
anchorY: 0.5
});
self.lifeTime = 300; // 5 seconds at 60fps
self.currentLife = 0;
self.update = function () {
self.currentLife++;
// Fade out over time
self.alpha = 1 - self.currentLife / self.lifeTime;
// Remove after lifetime
if (self.currentLife >= self.lifeTime) {
self.destroy();
for (var i = bloodEffects.length - 1; i >= 0; i--) {
if (bloodEffects[i] === self) {
bloodEffects.splice(i, 1);
break;
}
}
}
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.direction = {
x: 0,
y: 0
};
self.update = function () {
// Only update if in basement scene
if (currentScene !== 'basement') {
return;
}
// Move bullet in direction
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
// Remove bullet if it goes off screen
if (self.x < 0 || self.x > 2048 || self.y < 1800 || self.y > 2480) {
self.destroy();
for (var i = bullets.length - 1; i >= 0; i--) {
if (bullets[i] === self) {
bullets.splice(i, 1);
break;
}
}
}
// Check collision with basement ghosts
for (var i = basementGhosts.length - 1; i >= 0; i--) {
var ghost = basementGhosts[i];
if (self.intersects(ghost)) {
// Create blood effect at ghost position
createBloodEffect(ghost.x, ghost.y);
// Increment kill count
ghostKillCount++;
// Increase speed every 20 kills
if (ghostKillCount % 20 === 0) {
currentGhostSpeed += 1;
}
// Remove ghost
ghost.destroy();
basementGhosts.splice(i, 1);
// Remove bullet
self.destroy();
for (var j = bullets.length - 1; j >= 0; j--) {
if (bullets[j] === self) {
bullets.splice(j, 1);
break;
}
}
break;
}
}
// Check collision with regular house ghosts
for (var i = ghosts.length - 1; i >= 0; i--) {
var ghost = ghosts[i];
if (self.intersects(ghost)) {
// Create blood effect at ghost position
createBloodEffect(ghost.x, ghost.y);
// Increment kill count
ghostKillCount++;
// Increase speed every 20 kills
if (ghostKillCount % 20 === 0) {
currentGhostSpeed += 1;
}
// Remove ghost
ghost.destroy();
ghosts.splice(i, 1);
currentGhost = null;
ghostSpawnTimer = 0;
// Remove bullet
self.destroy();
for (var j = bullets.length - 1; j >= 0; j--) {
if (bullets[j] === self) {
bullets.splice(j, 1);
break;
}
}
break;
}
}
// Check collision with final boss
if (finalBoss && finalBossActive && self.intersects(finalBoss)) {
// Create blood effect at boss position
createBloodEffect(finalBoss.x, finalBoss.y);
// Increment player shot count
playerShotCount++;
// Damage boss
finalBoss.health--;
// Check if boss is defeated
if (playerShotCount >= 25) {
// Boss defeated - drop exit key
if (!exitKey) {
exitKey = game.addChild(LK.getAsset('key', {
anchorX: 0.5,
anchorY: 0.5
}));
exitKey.x = finalBoss.x;
exitKey.y = finalBoss.y;
exitKey.visible = true;
}
finalBoss.destroy();
finalBoss = null;
finalBossActive = false;
// Flash green to indicate boss defeated
LK.effects.flashScreen(0x00ff00, 1000);
}
// Remove bullet
self.destroy();
for (var j = bullets.length - 1; j >= 0; j--) {
if (bullets[j] === self) {
bullets.splice(j, 1);
break;
}
}
}
};
return self;
});
var FinalBoss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('monster', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8; // Very fast boss
self.health = 40;
self.lastAttackTime = 0;
self.update = function () {
// Only update if boss is active
if (!finalBossActive || currentScene !== 'basement') {
return;
}
// Move towards player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
// Attack player if close enough - deal 50 damage
if (distance < 80) {
var currentTime = LK.ticks;
if (currentTime - self.lastAttackTime > 60) {
// Attack once per second - deal 50 damage
playerHealth -= 50;
self.lastAttackTime = currentTime;
updateHealthBar();
// Flash player red when damaged
LK.effects.flashObject(player, 0xff0000, 500);
// Create blood effect at player position
createBloodEffect(player.x, player.y);
// Check if player is dead
if (playerHealth <= 0) {
LK.showGameOver();
return;
}
}
}
};
return self;
});
var Ghost = Container.expand(function () {
var self = Container.call(this);
var ghostGraphics = self.attachAsset('ghost', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.alpha = 0.7;
ghostGraphics.alpha = 0.7;
self.searchTimer = 0;
self.maxSearchTime = 300; // 5 seconds at 60fps
self.isLeaving = false;
self.update = function () {
// Don't update ghost if player is in room scene
if (currentScene === 'room') {
return;
}
// Only increment search timer when player is hidden
if (playerHidden) {
self.searchTimer++;
}
// Move ghost towards player if not leaving
if (!self.isLeaving) {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (!playerHidden && distance > 0) {
// Chase player if not hidden
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else if (playerHidden && distance > 0) {
// Move randomly when player is hidden
self.x += (Math.random() - 0.5) * 4;
self.y += (Math.random() - 0.5) * 4;
}
// Attack player if close enough and player is not hidden
if (distance < 80 && !playerHidden) {
// Damage player
if (self.lastAttackTime === undefined) self.lastAttackTime = 0;
var currentTime = LK.ticks;
if (currentTime - self.lastAttackTime > 60) {
// Attack once per second
playerHealth -= 10;
self.lastAttackTime = currentTime;
updateHealthBar();
// Flash player red when damaged
LK.effects.flashObject(player, 0xff0000, 500);
// Create blood effect at player position
createBloodEffect(player.x, player.y);
// Check if player is dead
if (playerHealth <= 0) {
LK.showGameOver();
return;
}
// After dealing damage, ghost starts leaving
self.isLeaving = true;
}
}
}
// If ghost hasn't found player after 5 seconds of searching (while player is hidden), start leaving
if (self.searchTimer >= self.maxSearchTime && playerHidden && !self.isLeaving) {
self.isLeaving = true;
self.speed = 3; // Move faster when leaving
}
// If leaving, move towards entrance door
if (self.isLeaving) {
var doorX = house.entranceDoor.x + 40;
var doorY = house.entranceDoor.y + 60;
var dx = doorX - self.x;
var dy = doorY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
// Remove ghost when it reaches the door
if (distance < 30) {
self.destroy();
currentGhost = null;
ghostSpawnTimer = 0;
for (var i = ghosts.length - 1; i >= 0; i--) {
if (ghosts[i] === self) {
ghosts.splice(i, 1);
break;
}
}
}
}
// Remove ghost if it goes off screen
if (self.x < -100 || self.x > 2148 || self.y < -100 || self.y > 2832) {
self.destroy();
currentGhost = null;
ghostSpawnTimer = 0;
for (var i = ghosts.length - 1; i >= 0; i--) {
if (ghosts[i] === self) {
ghosts.splice(i, 1);
break;
}
}
}
};
return self;
});
var House = Container.expand(function () {
var self = Container.call(this);
// Basement floor
var basementWall = self.attachAsset('houseWall', {
x: 0,
y: 1800
});
var basementFloor = self.attachAsset('houseFloor', {
x: 0,
y: 2400
});
// Ground floor
var groundFloorWall = self.attachAsset('houseWall', {
x: 0,
y: 1200
});
var groundFloor = self.attachAsset('houseFloor', {
x: 0,
y: 1800
});
// Second floor
var secondFloorWall = self.attachAsset('houseWall', {
x: 0,
y: 600
});
var secondFloor = self.attachAsset('houseFloor', {
x: 0,
y: 1200
});
// Stairs connecting floors - make them walkable
var stairway = self.attachAsset('stairs', {
x: 974,
y: 1200,
width: 100,
height: 600
});
// Second floor room dividers
var roomWall1 = self.attachAsset('houseWall', {
x: 1024,
y: 600,
width: 20,
height: 600
});
var roomWall2 = self.attachAsset('houseWall', {
x: 0,
y: 900,
width: 1024,
height: 20
});
var roomWall3 = self.attachAsset('houseWall', {
x: 1044,
y: 900,
width: 1004,
height: 20
});
// Floor barriers to prevent jumping between floors (except stairs)
var floorBarrierLeft = self.attachAsset('houseWall', {
x: 0,
y: 1200,
width: 974,
height: 20
});
var floorBarrierRight = self.attachAsset('houseWall', {
x: 1074,
y: 1200,
width: 974,
height: 20
});
// Store barrier references for collision detection
self.roomWall1 = roomWall1;
self.roomWall2 = roomWall2;
self.roomWall3 = roomWall3;
self.floorBarrierLeft = floorBarrierLeft;
self.floorBarrierRight = floorBarrierRight;
// Windows
var window1 = self.attachAsset('window', {
x: 300,
y: 700
});
var window2 = self.attachAsset('window', {
x: 800,
y: 700
});
var window3 = self.attachAsset('window', {
x: 1200,
y: 700
});
var window4 = self.attachAsset('window', {
x: 1600,
y: 700
});
var window5 = self.attachAsset('window', {
x: 300,
y: 1300
});
var window6 = self.attachAsset('window', {
x: 800,
y: 1300
});
var window7 = self.attachAsset('window', {
x: 1200,
y: 1300
});
var window8 = self.attachAsset('window', {
x: 1600,
y: 1300
});
// Exit door (locked)
var exitDoor = self.attachAsset('door', {
x: 1900,
y: 1620
});
var exitLock = self.attachAsset('lock', {
x: 1970,
y: 1660
});
// Basement door (locked)
var basementDoor = self.attachAsset('door', {
x: 100,
y: 1620
});
var basementLock = self.attachAsset('lock', {
x: 170,
y: 1660
});
// Closet on second floor
var closet = self.attachAsset('closet', {
x: 1800,
y: 680
});
// Upper floor door on the ground
var upperDoor = self.attachAsset('door', {
x: 500,
y: 1120
});
// Entrance door
var entranceDoor = self.attachAsset('door', {
x: 50,
y: 1620
});
// Store door and closet references for game logic
self.exitDoor = exitDoor;
self.basementDoor = basementDoor;
self.entranceDoor = entranceDoor;
self.upperDoor = upperDoor;
self.closet = closet;
self.exitLocked = true;
self.basementLocked = true;
return self;
});
var Monster = Container.expand(function () {
var self = Container.call(this);
var monsterGraphics = self.attachAsset('monster', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.lastAttackTime = 0;
self.update = function () {
// Only update if in room scene
if (currentScene !== 'room') {
return;
}
// Move towards player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
// Attack player if close enough
if (distance < 60) {
var currentTime = LK.ticks;
if (currentTime - self.lastAttackTime > 120) {
// Attack every 2 seconds
playerHealth -= 50;
self.lastAttackTime = currentTime;
updateHealthBar();
// Flash player red when damaged
LK.effects.flashObject(player, 0xff0000, 500);
// Create blood effect at player position
createBloodEffect(player.x, player.y);
// Check if player is dead
if (playerHealth <= 0) {
LK.showGameOver();
return;
}
}
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
return self;
});
var Room = Container.expand(function () {
var self = Container.call(this);
// Create room floor
var roomFloor = self.attachAsset('houseFloor', {
x: 0,
y: 1200
});
// Create room walls
var roomWallLeft = self.attachAsset('houseWall', {
x: 0,
y: 600,
width: 20,
height: 600
});
var roomWallRight = self.attachAsset('houseWall', {
x: 2028,
y: 600,
width: 20,
height: 600
});
var roomWallTop = self.attachAsset('houseWall', {
x: 0,
y: 600,
width: 2048,
height: 20
});
var roomWallBottom = self.attachAsset('houseWall', {
x: 0,
y: 1200,
width: 2048,
height: 20
});
// Exit door back to house
var exitDoor = self.attachAsset('door', {
x: 1000,
y: 1120
});
// Basement key in bottom corner
var basementKey = self.attachAsset('key', {
x: 50,
y: 1150,
anchorX: 0.5,
anchorY: 0.5
});
// Store door and key references
self.exitDoor = exitDoor;
self.basementKey = basementKey;
return self;
});
/****
* Initialize Game
****/
// Set dark atmospheric background
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// House structure assets
// Set dark atmospheric background
game.setBackgroundColor(0x0a0a0a);
// Create the two-story house
var house = game.addChild(new House());
// Position house to fill entire screen
house.x = 0;
house.y = 0;
// Create player
var player = game.addChild(new Player());
player.x = 2048 / 2;
player.y = 1750; // Start on ground floor
// Variables for player movement
var dragNode = null;
// Game state variables
var gameStarted = false;
var playerHidden = false;
var originalPlayerAlpha = 1;
var ghosts = [];
var ghostSpawnTimer = 0;
var currentGhost = null;
var ghostSearchTimer = 0;
var playerHealth = 100;
var maxHealth = 100;
var currentScene = 'house'; // 'house' or 'room'
var roomScene = null;
var roomMonster = null;
var hasBasementKey = false;
var playerWeapon = null;
var basementGhosts = [];
var totalBasementGhosts = 120;
var spawnedBasementGhosts = 0;
var basementGhostSpawnTimer = 0;
var ghostsPerWave = 5;
var bullets = [];
var bloodEffects = [];
var lastShootTime = 0;
var ghostKillCount = 0;
var currentGhostSpeed = 2;
var finalBoss = null;
var finalBossHealth = 40;
var finalBossActive = false;
var playerShotCount = 0;
var hasExitKey = false;
var exitKey = null;
// Create health bar
var healthBarBg = new Text2('', {
size: 25,
fill: 0x333333
});
healthBarBg.anchor.set(0.5, 0);
healthBarBg.x = 0;
healthBarBg.y = 150;
LK.gui.top.addChild(healthBarBg);
var healthBarFill = new Text2('', {
size: 25,
fill: 0xff0000
});
healthBarFill.anchor.set(0, 0);
healthBarFill.x = -125;
healthBarFill.y = 150;
LK.gui.top.addChild(healthBarFill);
var healthText = new Text2('Health: 100/100', {
size: 25,
fill: 0xffffff
});
healthText.anchor.set(0.5, 0);
healthText.x = 0;
healthText.y = 175;
LK.gui.top.addChild(healthText);
// Function to update health bar
function updateHealthBar() {
var healthPercent = Math.max(0, playerHealth / maxHealth);
var barWidth = Math.floor(250 * healthPercent);
healthBarBg.setText('█████████████████████████');
healthBarFill.setText('█'.repeat(Math.max(0, Math.floor(25 * healthPercent))));
healthText.setText('Health: ' + Math.max(0, playerHealth) + '/' + maxHealth);
}
// Initialize health bar
updateHealthBar();
// Touch controls for player movement
game.down = function (x, y, obj) {
// Check if we're in the house scene and clicked on upper floor door
if (currentScene === 'house') {
var upperDoorBounds = {
x: house.upperDoor.x,
y: house.upperDoor.y,
width: 80,
height: 120
};
if (x >= upperDoorBounds.x && x <= upperDoorBounds.x + upperDoorBounds.width && y >= upperDoorBounds.y && y <= upperDoorBounds.y + upperDoorBounds.height) {
// Check if player is standing near the door
var playerDistance = Math.sqrt((player.x - (house.upperDoor.x + 40)) * (player.x - (house.upperDoor.x + 40)) + (player.y - (house.upperDoor.y + 60)) * (player.y - (house.upperDoor.y + 60)));
if (playerDistance < 60) {
// Switch to room scene
switchToRoom();
}
return;
}
}
// Check if we're in the room scene and clicked on exit door
if (currentScene === 'room' && roomScene) {
var roomExitBounds = {
x: roomScene.exitDoor.x,
y: roomScene.exitDoor.y,
width: 80,
height: 120
};
if (x >= roomExitBounds.x && x <= roomExitBounds.x + roomExitBounds.width && y >= roomExitBounds.y && y <= roomExitBounds.y + roomExitBounds.height) {
// Check if player is standing near the door
var playerDistance = Math.sqrt((player.x - (roomScene.exitDoor.x + 40)) * (player.x - (roomScene.exitDoor.x + 40)) + (player.y - (roomScene.exitDoor.y + 60)) * (player.y - (roomScene.exitDoor.y + 60)));
if (playerDistance < 60) {
// Switch back to house scene
switchToHouse();
}
return;
}
// Check if clicked on basement key
if (roomScene.basementKey && roomScene.basementKey.visible) {
var keyBounds = {
x: roomScene.basementKey.x - 20,
y: roomScene.basementKey.y - 10,
width: 40,
height: 20
};
if (x >= keyBounds.x && x <= keyBounds.x + keyBounds.width && y >= keyBounds.y && y <= keyBounds.y + keyBounds.height) {
// Check if player is standing on the key
var playerDistance = Math.sqrt((player.x - roomScene.basementKey.x) * (player.x - roomScene.basementKey.x) + (player.y - roomScene.basementKey.y) * (player.y - roomScene.basementKey.y));
if (playerDistance < 50) {
// Collect the key
hasBasementKey = true;
roomScene.basementKey.visible = false;
// Flash key collected effect
LK.effects.flashScreen(0x00ff00, 500);
}
return;
}
}
}
// Check if clicked on basement door
var basementDoorBounds = {
x: house.basementDoor.x,
y: house.basementDoor.y,
width: 80,
height: 120
};
if (x >= basementDoorBounds.x && x <= basementDoorBounds.x + basementDoorBounds.width && y >= basementDoorBounds.y && y <= basementDoorBounds.y + basementDoorBounds.height) {
// Check if player has basement key and is close to door
if (hasBasementKey) {
var playerDistance = Math.sqrt((player.x - (house.basementDoor.x + 40)) * (player.x - (house.basementDoor.x + 40)) + (player.y - (house.basementDoor.y + 60)) * (player.y - (house.basementDoor.y + 60)));
if (playerDistance < 60) {
// Open basement door - unlock it and make lock invisible
house.basementLocked = false;
// Find and hide the basement lock
for (var i = 0; i < house.children.length; i++) {
if (house.children[i] === house.basementDoor.parent.children.find(function (child) {
return child.x === 170 && child.y === 1660;
})) {
house.children[i].visible = false;
break;
}
}
// Flash green to indicate door is now open
LK.effects.flashScreen(0x00ff00, 1000);
// Use the key (remove it from inventory)
hasBasementKey = false;
}
} else if (!house.basementLocked) {
// Door is already unlocked, allow entry to basement
var playerDistance = Math.sqrt((player.x - (house.basementDoor.x + 40)) * (player.x - (house.basementDoor.x + 40)) + (player.y - (house.basementDoor.y + 60)) * (player.y - (house.basementDoor.y + 60)));
if (playerDistance < 60) {
// Enter basement - move player down to basement level
switchToBasement();
}
}
return; // Don't allow dragging when interacting with door
}
// Check if clicked on exit key (if it exists)
if (exitKey && exitKey.visible) {
var keyBounds = {
x: exitKey.x - 20,
y: exitKey.y - 10,
width: 40,
height: 20
};
if (x >= keyBounds.x && x <= keyBounds.x + keyBounds.width && y >= keyBounds.y && y <= keyBounds.y + keyBounds.height) {
// Check if player is standing on the key
var playerDistance = Math.sqrt((player.x - exitKey.x) * (player.x - exitKey.x) + (player.y - exitKey.y) * (player.y - exitKey.y));
if (playerDistance < 50) {
// Collect the exit key
hasExitKey = true;
exitKey.visible = false;
// Flash key collected effect
LK.effects.flashScreen(0x00ff00, 500);
}
return;
}
}
// Check if clicked on exit door
var exitDoorBounds = {
x: house.exitDoor.x,
y: house.exitDoor.y,
width: 80,
height: 120
};
if (x >= exitDoorBounds.x && x <= exitDoorBounds.x + exitDoorBounds.width && y >= exitDoorBounds.y && y <= exitDoorBounds.y + exitDoorBounds.height) {
// Check if player has exit key and is close to door
if (hasExitKey) {
var playerDistance = Math.sqrt((player.x - (house.exitDoor.x + 40)) * (player.x - (house.exitDoor.x + 40)) + (player.y - (house.exitDoor.y + 60)) * (player.y - (house.exitDoor.y + 60)));
if (playerDistance < 60) {
// Open exit door and win the game
LK.effects.flashScreen(0x00ff00, 1000);
LK.showYouWin();
}
}
return;
}
// Check if clicked on closet
var closetBounds = {
x: house.closet.x,
y: house.closet.y,
width: 80,
height: 120
};
if (x >= closetBounds.x && x <= closetBounds.x + closetBounds.width && y >= closetBounds.y && y <= closetBounds.y + closetBounds.height) {
// Check if player is standing near the closet
var playerDistance = Math.sqrt((player.x - (house.closet.x + 40)) * (player.x - (house.closet.x + 40)) + (player.y - (house.closet.y + 60)) * (player.y - (house.closet.y + 60)));
if (playerDistance < 60) {
// Toggle hiding in closet
if (!playerHidden) {
// Hide player in closet
player.x = closetBounds.x + closetBounds.width / 2;
player.y = closetBounds.y + closetBounds.height / 2;
player.alpha = 0.3; // Make player semi-transparent
playerHidden = true;
return; // Don't set drag node when hiding
} else {
// Come out of closet
player.alpha = originalPlayerAlpha;
playerHidden = false;
return; // Don't set drag node when coming out
}
}
}
// Check if player has weapon - shoot bullet
if (playerWeapon && playerWeapon.visible) {
var currentTime = LK.ticks;
if (currentTime - lastShootTime > 15) {
// Limit shooting rate
lastShootTime = currentTime;
shootBullet(x, y);
}
}
// Only allow dragging if not hidden
if (!playerHidden) {
dragNode = player;
}
// Apply collision boundaries to keep player inside house walls
var newX = x;
var newY = y;
// Horizontal boundaries (house walls at x=0 and x=2048)
if (newX < 20) newX = 20; // Left wall boundary
if (newX > 2028) newX = 2028; // Right wall boundary
// Vertical boundaries
if (newY < 620) newY = 620; // Top of second floor
if (newY > 2480) newY = 2480; // Bottom of basement
// Prevent basement access if door is still locked
if (newY > 1800 && house.basementLocked) newY = 1800; // Bottom of ground floor - prevent basement access if locked
// Restrict basement movement - only allow going up through door area
if (currentScene === 'basement' && newY < 1800) {
// Only allow going up if player is near basement door
var doorX = house.basementDoor.x + 40;
if (newX < doorX - 60 || newX > doorX + 60) {
newY = 1800; // Keep in basement if not near door
}
}
// Floor barrier collision - prevent jumping between floors except via stairs
// Strict floor separation - only allow movement between floors in stairs area
if (player.y <= 1200 && newY > 1200) {
// Player trying to move from second floor to ground floor
if (newX < 974 || newX > 1074) {
// Not in stairs area - block movement
newY = 1200; // Keep on second floor
}
} else if (player.y > 1200 && newY <= 1200) {
// Player trying to move from ground floor to second floor
if (newX < 974 || newX > 1074) {
// Not in stairs area - block movement
newY = 1201; // Keep on ground floor
}
}
// Second floor room wall collisions
if (newY >= 600 && newY <= 1200) {
// Vertical room divider at x=1024
if (newX > 1024 && newX < 1044 && newY >= 600 && newY <= 1200) {
if (player.x <= 1024) {
newX = 1024;
} else {
newX = 1044;
}
}
// Horizontal room dividers at y=900
if (newY > 900 && newY < 920) {
if (newX < 1024 || newX > 1044) {
if (player.y <= 900) {
newY = 900;
} else {
newY = 920;
}
}
}
}
player.x = newX;
player.y = newY;
};
game.move = function (x, y, obj) {
if (dragNode && !playerHidden) {
// Apply collision boundaries to keep player inside house walls
var newX = x;
var newY = y;
// Horizontal boundaries (house walls at x=0 and x=2048)
if (newX < 20) newX = 20; // Left wall boundary
if (newX > 2028) newX = 2028; // Right wall boundary
// Vertical boundaries
if (newY < 620) newY = 620; // Top of second floor
if (newY > 2480) newY = 2480; // Bottom of basement
// Prevent basement access if door is still locked
if (newY > 1800 && house.basementLocked) newY = 1800; // Bottom of ground floor - prevent basement access if locked
// Restrict basement movement - only allow going up through door area
if (currentScene === 'basement' && newY < 1800) {
// Only allow going up if player is near basement door
var doorX = house.basementDoor.x + 40;
if (newX < doorX - 60 || newX > doorX + 60) {
newY = 1800; // Keep in basement if not near door
}
}
// Floor barrier collision - prevent jumping between floors except via stairs
// Strict floor separation - only allow movement between floors in stairs area
if (dragNode.y <= 1200 && newY > 1200) {
// Player trying to move from second floor to ground floor
if (newX < 974 || newX > 1074) {
// Not in stairs area - block movement
newY = 1200; // Keep on second floor
}
} else if (dragNode.y > 1200 && newY <= 1200) {
// Player trying to move from ground floor to second floor
if (newX < 974 || newX > 1074) {
// Not in stairs area - block movement
newY = 1201; // Keep on ground floor
}
}
// Second floor room wall collisions
if (newY >= 600 && newY <= 1200) {
// Vertical room divider at x=1024
if (newX > 1024 && newX < 1044 && newY >= 600 && newY <= 1200) {
if (dragNode.x <= 1024) {
newX = 1024;
} else {
newX = 1044;
}
}
// Horizontal room dividers at y=900
if (newY > 900 && newY < 920) {
if (newX < 1024 || newX > 1044) {
if (dragNode.y <= 900) {
newY = 900;
} else {
newY = 920;
}
}
}
}
dragNode.x = newX;
dragNode.y = newY;
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Player floor tracking
var playerFloor = 1; // 1 = ground floor, 2 = second floor
// Game update loop for stair interaction
game.update = function () {
// Check if player is on stairs area (walkable stairs)
var stairLeft = 974;
var stairRight = 974 + 100;
var stairTop = 1200;
var stairBottom = 1800;
// Determine current floor based on Y position
if (player.y <= 1200) {
playerFloor = 2; // Second floor
} else if (player.y >= 1800) {
playerFloor = 0; // Basement
} else if (player.y >= 1200) {
playerFloor = 1; // Ground floor
}
// Allow player to walk freely on stairs - no special collision needed
// as stairs are now part of the walkable area between floors
// Update collision boundaries - allow movement between floors via stairs
if (player.y > 2480) player.y = 2480; // Bottom boundary - basement floor
// Prevent basement access if door is still locked
if (player.y > 1800 && house.basementLocked) player.y = 1800; // Bottom of ground floor - prevent basement access if locked
if (player.y < 620) player.y = 620; // Top boundary
// Update weapon position to follow player
if (playerWeapon && playerWeapon.visible) {
playerWeapon.x = player.x + 40;
playerWeapon.y = player.y;
// Auto-shoot at nearby ghosts
var currentTime = LK.ticks;
if (currentTime - lastShootTime > 30) {
// Limit shooting rate
// Find closest ghost within shooting range
var closestGhost = null;
var closestDistance = 300; // Detection range
// Check basement ghosts
for (var i = 0; i < basementGhosts.length; i++) {
var ghost = basementGhosts[i];
var dx = ghost.x - player.x;
var dy = ghost.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < closestDistance) {
closestGhost = ghost;
closestDistance = distance;
}
}
// Check regular house ghosts
for (var i = 0; i < ghosts.length; i++) {
var ghost = ghosts[i];
var dx = ghost.x - player.x;
var dy = ghost.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < closestDistance) {
closestGhost = ghost;
closestDistance = distance;
}
}
// Check final boss
if (finalBoss && finalBossActive) {
var dx = finalBoss.x - player.x;
var dy = finalBoss.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < closestDistance) {
closestGhost = finalBoss;
closestDistance = distance;
}
}
// Shoot at closest ghost if found
if (closestGhost) {
lastShootTime = currentTime;
shootBullet(closestGhost.x, closestGhost.y);
}
}
}
// Ghost spawning system - every 15 seconds (900 ticks at 60fps) - only if boss not active
if (!finalBossActive) {
ghostSpawnTimer++;
if (ghostSpawnTimer >= 900) {
ghostSpawnTimer = 0;
spawnGhost();
}
}
// Basement ghost spawning - spawn 5 ghosts every 8 seconds if in basement - only if boss not active
if (currentScene === 'basement' && spawnedBasementGhosts < totalBasementGhosts && !finalBossActive) {
basementGhostSpawnTimer++;
if (basementGhostSpawnTimer >= 480) {
// 8 seconds at 60fps
basementGhostSpawnTimer = 0;
spawnBasementGhosts();
}
}
// Spawn final boss when 120 ghosts are killed
if (ghostKillCount >= 120 && !finalBossActive && !finalBoss) {
spawnFinalBoss();
}
};
// Ghost spawning function
function spawnGhost() {
// Only spawn if no ghost currently exists
if (currentGhost === null) {
// Animate door opening
tween(house.entranceDoor, {
scaleX: 0.1
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Create ghost at entrance door
var ghost = new Ghost();
ghost.x = house.entranceDoor.x + 40;
ghost.y = house.entranceDoor.y + 60;
ghosts.push(ghost);
game.addChild(ghost);
currentGhost = ghost;
// Close door after ghost spawns
tween(house.entranceDoor, {
scaleX: 1
}, {
duration: 300,
easing: tween.easeIn
});
}
});
}
}
// Scene switching functions
function switchToRoom() {
currentScene = 'room';
// Hide house
house.visible = false;
// Create and show room if it doesn't exist
if (!roomScene) {
roomScene = game.addChild(new Room());
}
roomScene.visible = true;
// Create monster if it doesn't exist
if (!roomMonster) {
roomMonster = game.addChild(new Monster());
roomMonster.x = 100;
roomMonster.y = 1150;
}
roomMonster.visible = true;
// Position player in the room
player.x = 1024;
player.y = 900;
}
function switchToHouse() {
currentScene = 'house';
// Hide room
if (roomScene) {
roomScene.visible = false;
}
// Hide monster
if (roomMonster) {
roomMonster.visible = false;
}
// Hide weapon when leaving basement
if (playerWeapon) {
playerWeapon.visible = false;
}
// Show house
house.visible = true;
// Position player back at upper floor door
player.x = 500;
player.y = 1050;
}
function switchToBasement() {
currentScene = 'basement';
// Move player down to basement level
player.y = 2300; // Position player in basement area
// Give player a weapon
if (!playerWeapon) {
playerWeapon = game.addChild(LK.getAsset('weapon', {
anchorX: 0.5,
anchorY: 0.5
}));
}
playerWeapon.visible = true;
// Initialize basement ghost spawning
spawnedBasementGhosts = 0;
basementGhostSpawnTimer = 0;
basementGhosts = [];
// Flash screen to indicate transition
LK.effects.flashScreen(0x444444, 500);
}
// Function to spawn basement ghosts in waves
function spawnBasementGhosts() {
var ghostsToSpawn = Math.min(ghostsPerWave, totalBasementGhosts - spawnedBasementGhosts);
for (var i = 0; i < ghostsToSpawn; i++) {
var ghost = new BasementGhost();
// Spawn ghosts only from the front (top side) - directly in front of player
ghost.x = 100 + Math.random() * 1848;
ghost.y = 1850;
basementGhosts.push(ghost);
game.addChild(ghost);
spawnedBasementGhosts++;
}
}
// Function to shoot bullet towards target position
function shootBullet(targetX, targetY) {
var bullet = new Bullet();
bullet.x = player.x;
bullet.y = player.y;
// Calculate direction to target
var dx = targetX - player.x;
var dy = targetY - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
bullet.direction.x = dx / distance;
bullet.direction.y = dy / distance;
}
bullets.push(bullet);
game.addChild(bullet);
}
// Function to create blood effect
function createBloodEffect(x, y) {
var blood = new BloodEffect();
blood.x = x;
blood.y = y;
bloodEffects.push(blood);
game.addChild(blood);
}
// Function to spawn final boss
function spawnFinalBoss() {
// Kill all existing ghosts
for (var i = basementGhosts.length - 1; i >= 0; i--) {
basementGhosts[i].destroy();
basementGhosts.splice(i, 1);
}
for (var i = ghosts.length - 1; i >= 0; i--) {
ghosts[i].destroy();
ghosts.splice(i, 1);
}
currentGhost = null;
ghostSpawnTimer = 0;
// Force switch to basement scene
switchToBasement();
// Create final boss
finalBoss = game.addChild(new FinalBoss());
finalBoss.x = 200;
finalBoss.y = 2200;
finalBossActive = true;
playerShotCount = 0;
// Flash screen red to indicate boss arrival
LK.effects.flashScreen(0xff0000, 1000);
// Make sure player has weapon
if (!playerWeapon) {
playerWeapon = game.addChild(LK.getAsset('weapon', {
anchorX: 0.5,
anchorY: 0.5
}));
}
playerWeapon.visible = true;
}
// Display instructions
var instructionText = new Text2('Explore the haunted house\nUse stairs to move between floors\nExit and basement doors are locked', {
size: 50,
fill: 0xCCCCCC
});
instructionText.anchor.set(0.5, 0);
LK.gui.top.addChild(instructionText);
;
merdiven. In-Game asset. 2d. High contrast. No shadows
pencere. In-Game asset. 2d. High contrast. No shadows
pikselli bir karakter ama kız. In-Game asset. 2d. High contrast. No shadows
siyah sade uzun duvar. In-Game asset. 2d. High contrast. No shadows
hayalet. In-Game asset. 2d. High contrast. No shadows
kapı ama eskimiş. In-Game asset. 2d. High contrast. No shadows
silah gerçek. In-Game asset. 2d. High contrast. No shadows
anahtar. In-Game asset. 2d. High contrast. No shadows