/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var DeathButton = Container.expand(function () {
var self = Container.call(this);
// Create button background
var btnBackground = self.attachAsset('safeZone', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.3,
tint: 0x000000
});
// Create button text
var btnText = new Text2('DEATH MODE', {
size: 60,
fill: 0xFFFFFF
});
btnText.anchor.set(0.5, 0.5);
self.addChild(btnText);
// Handle button press
self.down = function (x, y, obj) {
// Visual feedback
tween(btnBackground, {
scaleX: 0.75,
scaleY: 0.28
}, {
duration: 100
});
};
// Handle button release
self.up = function (x, y, obj) {
// Visual feedback
tween(btnBackground, {
scaleX: 0.8,
scaleY: 0.3
}, {
duration: 100,
onFinish: function onFinish() {
// Toggle death mode flag
window.deathMode = !window.deathMode;
// If turning on death mode, turn off other modes
if (window.deathMode) {
window.hardcoreMode = false;
window.extremeMode = false;
}
// Update button text and color
btnText.setText(window.deathMode ? 'NORMAL MODE' : 'DEATH MODE');
btnBackground.tint = window.deathMode ? 0xFF0000 : 0x000000;
// Play evil laugh when entering death mode
if (window.deathMode) {
LK.getSound('evilLaugh').play();
// Stop all music - no music in death mode
LK.stopMusic();
} else {
// Back to normal mode music
stopAllMusicAndPlay('bgMusic', {
fade: {
start: 0,
end: 1.0,
duration: 800
}
});
}
initGame();
}
});
};
return self;
});
var ExtremeButton = Container.expand(function () {
var self = Container.call(this);
// Create button background
var btnBackground = self.attachAsset('safeZone', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.3,
tint: 0xFF6600
});
// Create button text
var btnText = new Text2('EXTREME MODE', {
size: 60,
fill: 0xFFFFFF
});
btnText.anchor.set(0.5, 0.5);
self.addChild(btnText);
// Handle button press
self.down = function (x, y, obj) {
// Visual feedback
tween(btnBackground, {
scaleX: 0.75,
scaleY: 0.28
}, {
duration: 100
});
};
// Handle button release
self.up = function (x, y, obj) {
// Visual feedback
tween(btnBackground, {
scaleX: 0.8,
scaleY: 0.3
}, {
duration: 100,
onFinish: function onFinish() {
// Toggle extreme mode flag
window.extremeMode = !window.extremeMode;
// If turning off extreme mode, also turn off death mode
if (!window.extremeMode) {
window.deathMode = false;
}
// Update button text and color
btnText.setText(window.extremeMode ? 'HARDCORE MODE' : 'EXTREME MODE');
btnBackground.tint = window.extremeMode ? 0xFF0000 : 0xFF6600;
// Show/hide death button based on extreme mode
if (deathButton) {
tween(deathButton, {
alpha: window.extremeMode ? 1 : 0
}, {
duration: 300
});
}
// Play evil laugh when entering extreme mode
if (window.extremeMode) {
LK.getSound('evilLaugh').play();
// Stop all music first, then play extreme death music for extreme mode
LK.stopMusic();
stopAllMusicAndPlay('extremedeath', {
fade: {
start: 0,
end: 1.0,
duration: 800
}
});
} else {
// Back to hardcore mode music
stopAllMusicAndPlay('hardcorebg', {
fade: {
start: 0,
end: 1.0,
duration: 800
}
});
}
initGame();
}
});
};
return self;
});
var HardcoreButton = Container.expand(function () {
var self = Container.call(this);
// Create button background
var btnBackground = self.attachAsset('safeZone', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.3,
tint: 0xFF0000
});
// Create button text
var btnText = new Text2('HARDCORE MODE', {
size: 60,
fill: 0xFFFFFF
});
btnText.anchor.set(0.5, 0.5);
self.addChild(btnText);
// Handle button press
self.down = function (x, y, obj) {
// Visual feedback
tween(btnBackground, {
scaleX: 0.75,
scaleY: 0.28
}, {
duration: 100
});
};
// Handle button release
self.up = function (x, y, obj) {
// Visual feedback
tween(btnBackground, {
scaleX: 0.8,
scaleY: 0.3
}, {
duration: 100,
onFinish: function onFinish() {
// Toggle hardcore mode flag
window.hardcoreMode = !window.hardcoreMode;
// If turning off hardcore mode, also turn off extreme and death modes
if (!window.hardcoreMode) {
window.extremeMode = false;
window.deathMode = false;
}
// Update button text and color
btnText.setText(window.hardcoreMode ? 'NORMAL MODE' : 'HARDCORE MODE');
btnBackground.tint = window.hardcoreMode ? 0x00FF00 : 0xFF0000;
// Show/hide extreme button based on hardcore mode
if (extremeButton) {
tween(extremeButton, {
alpha: window.hardcoreMode ? 1 : 0
}, {
duration: 300
});
}
// Hide death button when hardcore is turned off
if (deathButton) {
tween(deathButton, {
alpha: 0
}, {
duration: 300
});
}
// Play evil laugh when entering hardcore mode
if (window.hardcoreMode) {
LK.getSound('evilLaugh').play();
// Play hardcore music
stopAllMusicAndPlay('hardcorebg', {
fade: {
start: 0,
end: 1.0,
duration: 800
}
});
} else {
// Play normal mode music
stopAllMusicAndPlay('bgMusic', {
fade: {
start: 0,
end: 1.0,
duration: 800
}
});
}
initGame();
}
});
};
return self;
});
var PlayerCircle = Container.expand(function () {
var self = Container.call(this);
var circleGraphics = self.attachAsset('playerCircle', {
anchorX: 0.5,
anchorY: 0.5
});
// Pulse animation for player
self.startPulse = function () {
tween(circleGraphics, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 400,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(circleGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 400,
easing: tween.easeInOut,
onFinish: self.startPulse
});
}
});
};
self.stopPulse = function () {
tween.stop(circleGraphics, {
scaleX: true,
scaleY: true
});
tween(circleGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 300
});
};
self.applyForce = function (angle, magnitude) {
var vx = Math.cos(angle) * magnitude;
var vy = Math.sin(angle) * magnitude;
self.vx = vx;
self.vy = vy;
};
self.vx = 0;
self.vy = 0;
self.friction = 0.95;
self.update = function () {
// Apply velocity
if (!self.isDragging) {
self.x += self.vx;
self.y += self.vy;
// Apply friction
self.vx *= self.friction;
self.vy *= self.friction;
// Stop if velocity is very small
if (Math.abs(self.vx) < 0.1) self.vx = 0;
if (Math.abs(self.vy) < 0.1) self.vy = 0;
// Add slow drift away from center - in both modes, drift away from safe zone
var dx = self.x - safeZone.x;
var dy = self.y - safeZone.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 10) {
// Only apply drift if not exactly at center
var angle = Math.atan2(dy, dx);
// Keep consistent drift force regardless of mode
var driftForce = 0.15;
self.vx += Math.cos(angle) * driftForce;
self.vy += Math.sin(angle) * driftForce;
}
}
// Constrain to screen bounds
if (self.x < 50) {
self.x = 50;
self.vx *= -0.5;
}
if (self.x > 2048 - 50) {
self.x = 2048 - 50;
self.vx *= -0.5;
}
if (self.y < 50) {
self.y = 50;
self.vy *= -0.5;
}
if (self.y > 2732 - 50) {
self.y = 2732 - 50;
self.vy *= -0.5;
}
};
self.isDragging = false;
// Set initial state
self.startPulse();
return self;
});
var SafeZone = Container.expand(function () {
var self = Container.call(this);
var zoneGraphics = self.attachAsset('safeZone', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
// Pulse animation for safe zone
self.startPulse = function () {
tween(zoneGraphics, {
alpha: 0.7
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(zoneGraphics, {
alpha: 0.4
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: self.startPulse
});
}
});
};
self.stopPulse = function () {
tween.stop(zoneGraphics, {
alpha: true
});
};
self.shrink = function () {
tween(zoneGraphics, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 1000,
easing: tween.easeOut
});
};
self.grow = function () {
tween(zoneGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.bounceOut
});
};
// Set initial state
self.startPulse();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x111111
});
/****
* Game Code
****/
// Hardcore mode flag
window.hardcoreMode = false;
// Extreme mode flag
window.extremeMode = false;
// Death mode flag
window.deathMode = false;
// Game constants
var GAME_DURATION = 120000; // 2 minutes
var DANGER_TIMEOUT = 7000; // 7 seconds
var MIN_BUMP_INTERVAL = 5000; // 5 seconds
var MAX_BUMP_INTERVAL = 11000; // 11 seconds
var MAX_BUMP_FORCE = 40; // Increased from 25 for stronger bumps
// Extreme mode constants - much more chaotic
var EXTREME_MIN_BUMP_INTERVAL = 800; // Much faster bumps
var EXTREME_MAX_BUMP_INTERVAL = 2000; // Much faster bumps
var EXTREME_DANGER_TIMEOUT = 3000; // Less time outside safe zone
// Death mode constants - 5 minutes of extreme chaos
var DEATH_GAME_DURATION = 300000; // 5 minutes
var DEATH_MIN_BUMP_INTERVAL = 400; // Even faster than extreme
var DEATH_MAX_BUMP_INTERVAL = 1000; // Even faster than extreme
var DEATH_DANGER_TIMEOUT = 2000; // Even less time outside safe zone
// Define safe teleportation zones that avoid buttons
var SAFE_TELEPORT_ZONES = [
// Left side zones
{
x: 200,
y: 400,
width: 300,
height: 300
}, {
x: 200,
y: 800,
width: 300,
height: 300
}, {
x: 200,
y: 1200,
width: 300,
height: 300
}, {
x: 200,
y: 1600,
width: 300,
height: 300
}, {
x: 200,
y: 2000,
width: 300,
height: 300
},
// Center zones
{
x: 600,
y: 400,
width: 300,
height: 300
}, {
x: 600,
y: 800,
width: 300,
height: 300
}, {
x: 600,
y: 1600,
width: 300,
height: 300
}, {
x: 600,
y: 2000,
width: 300,
height: 300
}, {
x: 1024,
y: 400,
width: 300,
height: 300
}, {
x: 1024,
y: 800,
width: 300,
height: 300
}, {
x: 1024,
y: 1600,
width: 300,
height: 300
}, {
x: 1024,
y: 2000,
width: 300,
height: 300
},
// Right side zones (avoiding button area at top right)
{
x: 1400,
y: 600,
width: 300,
height: 300
}, {
x: 1400,
y: 1000,
width: 300,
height: 300
}, {
x: 1400,
y: 1400,
width: 300,
height: 300
}, {
x: 1400,
y: 1800,
width: 300,
height: 300
}];
// Add hardcore button
var hardcoreButton = new HardcoreButton();
hardcoreButton.x = 2048 - 150;
hardcoreButton.y = 120;
// Update button text based on current mode
hardcoreButton.children[1].setText(window.hardcoreMode ? 'NORMAL MODE' : 'HARDCORE MODE');
hardcoreButton.children[0].tint = window.hardcoreMode ? 0x00FF00 : 0xFF0000;
game.addChild(hardcoreButton);
// Add extreme mode button (only visible when hardcore is enabled)
var extremeButton = new ExtremeButton();
extremeButton.x = 2048 - 150;
extremeButton.y = 250;
extremeButton.alpha = window.hardcoreMode ? 1 : 0;
game.addChild(extremeButton);
// Add death mode button (only visible when extreme is enabled)
var deathButton = new DeathButton();
deathButton.x = 2048 - 150;
deathButton.y = 380;
deathButton.alpha = window.extremeMode ? 1 : 0;
game.addChild(deathButton);
// Universal music management function
function stopAllMusicAndPlay(musicId, options) {
// Stop any currently playing music first
LK.stopMusic();
// Play the new music
LK.playMusic(musicId, options);
}
// Game state variables
var gameTimer = 0;
var outOfSafeZoneTimer = 0;
var isPlayerInSafeZone = true;
var lastBumpTime = 0;
var nextBumpTime = 0;
var dragNode = null;
// Create the safe zone
var safeZone = new SafeZone();
safeZone.x = 2048 / 2;
safeZone.y = 2732 / 2;
game.addChild(safeZone);
// Create the player circle
var player = new PlayerCircle();
player.x = 2048 / 2;
player.y = 2732 / 2;
game.addChild(player);
// UI Elements
var timerText = new Text2('2:00', {
size: 100,
fill: 0xFFFFFF
});
timerText.anchor.set(0.5, 0);
LK.gui.top.addChild(timerText);
var instructionText = new Text2('KEEP THE CIRCLE IN THE MIDDLE', {
size: 70,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
instructionText.y = 120;
LK.gui.top.addChild(instructionText);
// Add pulsing animation to instruction text synchronized with beat
function pulseInstructionText() {
tween(instructionText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(instructionText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 300,
easing: tween.easeIn,
onFinish: pulseInstructionText
});
}
});
}
pulseInstructionText();
var warningText = new Text2('WARNING: RETURN TO SAFE ZONE!', {
size: 70,
fill: 0xFF3333
});
warningText.anchor.set(0.5, 0);
warningText.y = timerText.height + instructionText.height + 150;
warningText.alpha = 0;
LK.gui.top.addChild(warningText);
// Format time as MM:SS
function formatTime(ms) {
var seconds = Math.floor(ms / 1000);
var minutes = Math.floor(seconds / 60);
seconds = seconds % 60;
return minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
}
// Get random teleport position from safe zones
function getRandomTeleportPosition() {
var zone = SAFE_TELEPORT_ZONES[Math.floor(Math.random() * SAFE_TELEPORT_ZONES.length)];
var randomX = zone.x + Math.random() * zone.width;
var randomY = zone.y + Math.random() * zone.height;
return {
x: randomX,
y: randomY
};
}
// Schedule the next random bump
function scheduleNextBump() {
var minInterval, maxInterval;
if (window.deathMode) {
minInterval = DEATH_MIN_BUMP_INTERVAL;
maxInterval = DEATH_MAX_BUMP_INTERVAL;
} else if (window.extremeMode) {
minInterval = EXTREME_MIN_BUMP_INTERVAL;
maxInterval = EXTREME_MAX_BUMP_INTERVAL;
} else {
minInterval = MIN_BUMP_INTERVAL;
maxInterval = MAX_BUMP_INTERVAL;
}
var interval = minInterval + Math.random() * (maxInterval - minInterval);
nextBumpTime = lastBumpTime + interval;
}
// Apply a random force to push player away from center
function applyRandomBump() {
// Calculate angle away from center
var centerX = 2048 / 2;
var centerY = 2732 / 2;
var dx = player.x - centerX;
var dy = player.y - centerY;
var angle = Math.atan2(dy, dx);
// If player is at center, use a random angle
if (Math.abs(dx) < 10 && Math.abs(dy) < 10) {
angle = Math.random() * Math.PI * 2;
}
// Get current game progress (0 to 1)
var currentGameDuration = window.deathMode ? DEATH_GAME_DURATION : GAME_DURATION;
var gameProgress = Math.min(gameTimer / currentGameDuration, 1);
if (window.deathMode) {
// DEATH MODE: Ultimate chaos - 5 minutes of hell
var teleportPos = getRandomTeleportPosition();
// Teleport safe zone
safeZone.x = teleportPos.x;
safeZone.y = teleportPos.y;
// Apply massive force to player for ultimate chaos
var forceMagnitude = 80 + gameProgress * 60; // Even stronger than extreme
player.applyForce(angle, forceMagnitude);
// Add death visual effect
LK.effects.flashScreen(0x000000, 600);
// Display death message
instructionText.setText("DEATH MODE: 5 MINUTES OF HELL!");
} else if (window.extremeMode) {
// EXTREME MODE: Maximum chaos
var teleportPos = getRandomTeleportPosition();
// Teleport safe zone
safeZone.x = teleportPos.x;
safeZone.y = teleportPos.y;
// Also apply force to player in extreme mode for double chaos
var forceMagnitude = 60 + gameProgress * 40; // Much stronger force
player.applyForce(angle, forceMagnitude);
// Add extreme visual effect
LK.effects.flashScreen(0xFF0066, 500);
// Display extreme message
instructionText.setText("EXTREME MODE: 2 MINUTES OF CHAOS!");
} else if (window.hardcoreMode) {
// In hardcore mode, teleport the SAFE ZONE to a safe position
var teleportPos = getRandomTeleportPosition();
// Teleport safe zone
safeZone.x = teleportPos.x;
safeZone.y = teleportPos.y;
// Add stronger visual effect for hardcore mode
LK.effects.flashScreen(0xFF4400, 300);
// Display "Good Luck" message
instructionText.setText("HARDCORE MODE: GOOD LUCK.");
} else {
// Normal mode - apply force
// Increase force based on progress (more force as game goes on)
var forceMagnitude = 20 + (MAX_BUMP_FORCE - 20) * gameProgress; // Starting force increased from 10 to 20
// Apply the force
player.applyForce(angle, forceMagnitude);
}
// Play bump sound
LK.getSound('bump').play();
// Visual effect - flash screen slightly
LK.effects.flashScreen(0xFFFFFF, 200);
// Record time of bump and schedule next one
lastBumpTime = LK.ticks * (1000 / 60); // Convert ticks to ms
scheduleNextBump();
}
// Check if player is in safe zone
function checkPlayerInSafeZone() {
// In both modes, we need to check the distance to the safe zone
// In normal mode, safe zone is centered, but in hardcore, it could be anywhere
var dx = player.x - safeZone.x;
var dy = player.y - safeZone.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Safe zone radius is half the width of the safeZone asset
var safeZoneRadius = safeZone.children[0].width / 2;
return distance < safeZoneRadius;
}
// Handle warning display
function updateWarning() {
if (!isPlayerInSafeZone) {
// Danger progress (0 to 1)
var dangerProgress = outOfSafeZoneTimer / DANGER_TIMEOUT;
// Scale warning text based on danger progress
var scale = 1 + dangerProgress * 0.3;
warningText.scale.set(scale, scale);
// Fade in warning if it's not already visible
if (warningText.alpha < 1) {
tween(warningText, {
alpha: 1
}, {
duration: 300
});
}
// Change text color between red and white for urgency
if (dangerProgress > 0.7) {
if (LK.ticks % 15 === 0) {
// Flash every quarter second
warningText.setText(warningText.text); // Ensure text is refreshed
if (warningText.style && warningText.style.fill) {
warningText.style.fill = warningText.style.fill === "#FF3333" ? "#FFFFFF" : "#FF3333";
} else {
// Fallback if style is not properly initialized
warningText.setText(warningText.text, {
fill: warningText.style && warningText.style.fill === "#FF3333" ? "#FFFFFF" : "#FF3333"
});
}
}
}
} else {
// Fade out warning
if (warningText.alpha > 0) {
tween(warningText, {
alpha: 0
}, {
duration: 300
});
}
}
}
// Start the game
function initGame() {
// Initialize game state
gameTimer = 0;
outOfSafeZoneTimer = 0;
isPlayerInSafeZone = true;
lastBumpTime = 0;
scheduleNextBump();
// Reset positions
player.x = 2048 / 2;
player.y = 2732 / 2;
player.vx = 0;
player.vy = 0;
// Reset safe zone position to center
safeZone.x = 2048 / 2;
safeZone.y = 2732 / 2;
// Update UI based on current mode
if (window.deathMode) {
// Change title text to indicate death mode
instructionText.setText("DEATH MODE: 5 MINUTES OF HELL!");
if (!instructionText.style) instructionText.style = {};
instructionText.style.fill = "#000000";
// Make the safe zone extremely small in death mode
safeZone.children[0].scale.set(0.4, 0.4);
// Update death button text and color
if (deathButton) {
deathButton.children[1].setText('NORMAL MODE');
deathButton.children[0].tint = 0xFF0000;
}
} else if (window.extremeMode) {
// Change title text to indicate extreme mode
instructionText.setText("EXTREME MODE: 2 MINUTES OF CHAOS!");
if (!instructionText.style) instructionText.style = {};
instructionText.style.fill = "#FF0066";
// Make the safe zone even smaller in extreme mode
safeZone.children[0].scale.set(0.6, 0.6);
// Update extreme button text and color
if (extremeButton) {
extremeButton.children[1].setText('HARDCORE MODE');
extremeButton.children[0].tint = 0xFF0000;
}
} else if (window.hardcoreMode) {
// Change title text to indicate hardcore mode with "Good luck"
instructionText.setText("HARDCORE MODE: GOOD LUCK.");
if (!instructionText.style) instructionText.style = {};
instructionText.style.fill = "#FF3333";
// Make the safe zone smaller in hardcore mode
safeZone.children[0].scale.set(0.8, 0.8);
// Update hardcore button text and color
if (hardcoreButton) {
hardcoreButton.children[1].setText('NORMAL MODE');
hardcoreButton.children[0].tint = 0x00FF00;
}
// Update extreme button text and color
if (extremeButton) {
extremeButton.children[1].setText('EXTREME MODE');
extremeButton.children[0].tint = 0xFF6600;
}
} else {
// Reset to normal mode text
instructionText.setText("KEEP THE CIRCLE IN THE MIDDLE");
if (!instructionText.style) instructionText.style = {};
instructionText.style.fill = "#FFFFFF";
// Reset safe zone size
safeZone.children[0].scale.set(1, 1);
// Update hardcore button text and color
if (hardcoreButton) {
hardcoreButton.children[1].setText('HARDCORE MODE');
hardcoreButton.children[0].tint = 0xFF0000;
}
}
// Music is now handled by the hardcore button
// We don't need to start music here as it would cause duplicates
// when toggling modes via the button
// This section is kept for when the game is initially loaded
if (gameTimer === 0 && outOfSafeZoneTimer === 0) {
if (window.deathMode) {
// Death mode has no music - silence is part of the horror
LK.stopMusic();
} else if (window.extremeMode) {
// Extreme mode music
stopAllMusicAndPlay('extremedeath', {
fade: {
start: 0,
end: 1.0,
duration: 800
}
});
} else if (window.hardcoreMode) {
// Hardcore mode music - music is already playing from button press
// but ensure it's playing in case initGame is called directly
stopAllMusicAndPlay('hardcorebg', {
fade: {
start: 0,
end: 1.0,
duration: 800
}
});
} else {
// Normal mode music
stopAllMusicAndPlay('bgMusic', {
fade: {
start: 0,
end: 1.0,
// Set to full volume for intense beat
duration: 800
}
});
}
}
}
// Handle dragging
function handleMove(x, y, obj) {
if (dragNode) {
dragNode.x = x;
dragNode.y = y;
dragNode.isDragging = true;
// Reset velocity when dragging
dragNode.vx = 0;
dragNode.vy = 0;
}
}
// Mouse/touch handlers
game.down = function (x, y, obj) {
// Start dragging the player
dragNode = player;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
if (dragNode) {
dragNode.isDragging = false;
dragNode = null;
}
};
game.move = handleMove;
// Initialize the game
initGame();
// Game update loop
game.update = function () {
// Update game timer
gameTimer += 1000 / 60; // Increment by ms per frame
// Update timer display with correct duration based on mode
var currentGameDuration = window.deathMode ? DEATH_GAME_DURATION : GAME_DURATION;
var timeLeft = Math.max(0, currentGameDuration - gameTimer);
timerText.setText(formatTime(timeLeft));
// Check if player is in safe zone
var wasInSafeZone = isPlayerInSafeZone;
isPlayerInSafeZone = checkPlayerInSafeZone();
// Handle transitions between in/out of safe zone
if (wasInSafeZone && !isPlayerInSafeZone) {
// Just left safe zone
safeZone.shrink();
outOfSafeZoneTimer = 0;
} else if (!wasInSafeZone && isPlayerInSafeZone) {
// Just returned to safe zone
safeZone.grow();
}
// Update danger timer if outside safe zone
if (!isPlayerInSafeZone) {
outOfSafeZoneTimer += 1000 / 60;
// Use appropriate timeout based on mode
var currentDangerTimeout;
if (window.deathMode) {
currentDangerTimeout = DEATH_DANGER_TIMEOUT;
} else if (window.extremeMode) {
currentDangerTimeout = EXTREME_DANGER_TIMEOUT;
} else {
currentDangerTimeout = DANGER_TIMEOUT;
}
// Play warning sound at specific thresholds
if (outOfSafeZoneTimer >= currentDangerTimeout * 0.5 && LK.ticks % 30 === 0) {
LK.getSound('warning').play();
}
// Game over condition
if (outOfSafeZoneTimer >= currentDangerTimeout) {
LK.getSound('lose').play();
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
return;
}
} else {
outOfSafeZoneTimer = 0;
}
// Update warning display
updateWarning();
// Check for random bump time
var currentTime = LK.ticks * (1000 / 60);
if (nextBumpTime > 0 && currentTime >= nextBumpTime) {
applyRandomBump();
}
// Add visual beat pulse every second
if (LK.ticks % 60 === 0) {
// Flash safe zone with beat
LK.effects.flashObject(safeZone, 0x00FFFF, 200);
// Apply small "bump" to instruction text with beat
tween(instructionText, {
y: instructionText.y - 5
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(instructionText, {
y: 120
}, {
duration: 100,
easing: tween.easeIn
});
}
});
}
// Win condition
var currentGameDuration = window.deathMode ? DEATH_GAME_DURATION : GAME_DURATION;
if (gameTimer >= currentGameDuration) {
LK.getSound('win').play();
LK.effects.flashScreen(0x00FF00, 1000);
LK.showYouWin();
return;
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var DeathButton = Container.expand(function () {
var self = Container.call(this);
// Create button background
var btnBackground = self.attachAsset('safeZone', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.3,
tint: 0x000000
});
// Create button text
var btnText = new Text2('DEATH MODE', {
size: 60,
fill: 0xFFFFFF
});
btnText.anchor.set(0.5, 0.5);
self.addChild(btnText);
// Handle button press
self.down = function (x, y, obj) {
// Visual feedback
tween(btnBackground, {
scaleX: 0.75,
scaleY: 0.28
}, {
duration: 100
});
};
// Handle button release
self.up = function (x, y, obj) {
// Visual feedback
tween(btnBackground, {
scaleX: 0.8,
scaleY: 0.3
}, {
duration: 100,
onFinish: function onFinish() {
// Toggle death mode flag
window.deathMode = !window.deathMode;
// If turning on death mode, turn off other modes
if (window.deathMode) {
window.hardcoreMode = false;
window.extremeMode = false;
}
// Update button text and color
btnText.setText(window.deathMode ? 'NORMAL MODE' : 'DEATH MODE');
btnBackground.tint = window.deathMode ? 0xFF0000 : 0x000000;
// Play evil laugh when entering death mode
if (window.deathMode) {
LK.getSound('evilLaugh').play();
// Stop all music - no music in death mode
LK.stopMusic();
} else {
// Back to normal mode music
stopAllMusicAndPlay('bgMusic', {
fade: {
start: 0,
end: 1.0,
duration: 800
}
});
}
initGame();
}
});
};
return self;
});
var ExtremeButton = Container.expand(function () {
var self = Container.call(this);
// Create button background
var btnBackground = self.attachAsset('safeZone', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.3,
tint: 0xFF6600
});
// Create button text
var btnText = new Text2('EXTREME MODE', {
size: 60,
fill: 0xFFFFFF
});
btnText.anchor.set(0.5, 0.5);
self.addChild(btnText);
// Handle button press
self.down = function (x, y, obj) {
// Visual feedback
tween(btnBackground, {
scaleX: 0.75,
scaleY: 0.28
}, {
duration: 100
});
};
// Handle button release
self.up = function (x, y, obj) {
// Visual feedback
tween(btnBackground, {
scaleX: 0.8,
scaleY: 0.3
}, {
duration: 100,
onFinish: function onFinish() {
// Toggle extreme mode flag
window.extremeMode = !window.extremeMode;
// If turning off extreme mode, also turn off death mode
if (!window.extremeMode) {
window.deathMode = false;
}
// Update button text and color
btnText.setText(window.extremeMode ? 'HARDCORE MODE' : 'EXTREME MODE');
btnBackground.tint = window.extremeMode ? 0xFF0000 : 0xFF6600;
// Show/hide death button based on extreme mode
if (deathButton) {
tween(deathButton, {
alpha: window.extremeMode ? 1 : 0
}, {
duration: 300
});
}
// Play evil laugh when entering extreme mode
if (window.extremeMode) {
LK.getSound('evilLaugh').play();
// Stop all music first, then play extreme death music for extreme mode
LK.stopMusic();
stopAllMusicAndPlay('extremedeath', {
fade: {
start: 0,
end: 1.0,
duration: 800
}
});
} else {
// Back to hardcore mode music
stopAllMusicAndPlay('hardcorebg', {
fade: {
start: 0,
end: 1.0,
duration: 800
}
});
}
initGame();
}
});
};
return self;
});
var HardcoreButton = Container.expand(function () {
var self = Container.call(this);
// Create button background
var btnBackground = self.attachAsset('safeZone', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.3,
tint: 0xFF0000
});
// Create button text
var btnText = new Text2('HARDCORE MODE', {
size: 60,
fill: 0xFFFFFF
});
btnText.anchor.set(0.5, 0.5);
self.addChild(btnText);
// Handle button press
self.down = function (x, y, obj) {
// Visual feedback
tween(btnBackground, {
scaleX: 0.75,
scaleY: 0.28
}, {
duration: 100
});
};
// Handle button release
self.up = function (x, y, obj) {
// Visual feedback
tween(btnBackground, {
scaleX: 0.8,
scaleY: 0.3
}, {
duration: 100,
onFinish: function onFinish() {
// Toggle hardcore mode flag
window.hardcoreMode = !window.hardcoreMode;
// If turning off hardcore mode, also turn off extreme and death modes
if (!window.hardcoreMode) {
window.extremeMode = false;
window.deathMode = false;
}
// Update button text and color
btnText.setText(window.hardcoreMode ? 'NORMAL MODE' : 'HARDCORE MODE');
btnBackground.tint = window.hardcoreMode ? 0x00FF00 : 0xFF0000;
// Show/hide extreme button based on hardcore mode
if (extremeButton) {
tween(extremeButton, {
alpha: window.hardcoreMode ? 1 : 0
}, {
duration: 300
});
}
// Hide death button when hardcore is turned off
if (deathButton) {
tween(deathButton, {
alpha: 0
}, {
duration: 300
});
}
// Play evil laugh when entering hardcore mode
if (window.hardcoreMode) {
LK.getSound('evilLaugh').play();
// Play hardcore music
stopAllMusicAndPlay('hardcorebg', {
fade: {
start: 0,
end: 1.0,
duration: 800
}
});
} else {
// Play normal mode music
stopAllMusicAndPlay('bgMusic', {
fade: {
start: 0,
end: 1.0,
duration: 800
}
});
}
initGame();
}
});
};
return self;
});
var PlayerCircle = Container.expand(function () {
var self = Container.call(this);
var circleGraphics = self.attachAsset('playerCircle', {
anchorX: 0.5,
anchorY: 0.5
});
// Pulse animation for player
self.startPulse = function () {
tween(circleGraphics, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 400,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(circleGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 400,
easing: tween.easeInOut,
onFinish: self.startPulse
});
}
});
};
self.stopPulse = function () {
tween.stop(circleGraphics, {
scaleX: true,
scaleY: true
});
tween(circleGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 300
});
};
self.applyForce = function (angle, magnitude) {
var vx = Math.cos(angle) * magnitude;
var vy = Math.sin(angle) * magnitude;
self.vx = vx;
self.vy = vy;
};
self.vx = 0;
self.vy = 0;
self.friction = 0.95;
self.update = function () {
// Apply velocity
if (!self.isDragging) {
self.x += self.vx;
self.y += self.vy;
// Apply friction
self.vx *= self.friction;
self.vy *= self.friction;
// Stop if velocity is very small
if (Math.abs(self.vx) < 0.1) self.vx = 0;
if (Math.abs(self.vy) < 0.1) self.vy = 0;
// Add slow drift away from center - in both modes, drift away from safe zone
var dx = self.x - safeZone.x;
var dy = self.y - safeZone.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 10) {
// Only apply drift if not exactly at center
var angle = Math.atan2(dy, dx);
// Keep consistent drift force regardless of mode
var driftForce = 0.15;
self.vx += Math.cos(angle) * driftForce;
self.vy += Math.sin(angle) * driftForce;
}
}
// Constrain to screen bounds
if (self.x < 50) {
self.x = 50;
self.vx *= -0.5;
}
if (self.x > 2048 - 50) {
self.x = 2048 - 50;
self.vx *= -0.5;
}
if (self.y < 50) {
self.y = 50;
self.vy *= -0.5;
}
if (self.y > 2732 - 50) {
self.y = 2732 - 50;
self.vy *= -0.5;
}
};
self.isDragging = false;
// Set initial state
self.startPulse();
return self;
});
var SafeZone = Container.expand(function () {
var self = Container.call(this);
var zoneGraphics = self.attachAsset('safeZone', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
// Pulse animation for safe zone
self.startPulse = function () {
tween(zoneGraphics, {
alpha: 0.7
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(zoneGraphics, {
alpha: 0.4
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: self.startPulse
});
}
});
};
self.stopPulse = function () {
tween.stop(zoneGraphics, {
alpha: true
});
};
self.shrink = function () {
tween(zoneGraphics, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 1000,
easing: tween.easeOut
});
};
self.grow = function () {
tween(zoneGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.bounceOut
});
};
// Set initial state
self.startPulse();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x111111
});
/****
* Game Code
****/
// Hardcore mode flag
window.hardcoreMode = false;
// Extreme mode flag
window.extremeMode = false;
// Death mode flag
window.deathMode = false;
// Game constants
var GAME_DURATION = 120000; // 2 minutes
var DANGER_TIMEOUT = 7000; // 7 seconds
var MIN_BUMP_INTERVAL = 5000; // 5 seconds
var MAX_BUMP_INTERVAL = 11000; // 11 seconds
var MAX_BUMP_FORCE = 40; // Increased from 25 for stronger bumps
// Extreme mode constants - much more chaotic
var EXTREME_MIN_BUMP_INTERVAL = 800; // Much faster bumps
var EXTREME_MAX_BUMP_INTERVAL = 2000; // Much faster bumps
var EXTREME_DANGER_TIMEOUT = 3000; // Less time outside safe zone
// Death mode constants - 5 minutes of extreme chaos
var DEATH_GAME_DURATION = 300000; // 5 minutes
var DEATH_MIN_BUMP_INTERVAL = 400; // Even faster than extreme
var DEATH_MAX_BUMP_INTERVAL = 1000; // Even faster than extreme
var DEATH_DANGER_TIMEOUT = 2000; // Even less time outside safe zone
// Define safe teleportation zones that avoid buttons
var SAFE_TELEPORT_ZONES = [
// Left side zones
{
x: 200,
y: 400,
width: 300,
height: 300
}, {
x: 200,
y: 800,
width: 300,
height: 300
}, {
x: 200,
y: 1200,
width: 300,
height: 300
}, {
x: 200,
y: 1600,
width: 300,
height: 300
}, {
x: 200,
y: 2000,
width: 300,
height: 300
},
// Center zones
{
x: 600,
y: 400,
width: 300,
height: 300
}, {
x: 600,
y: 800,
width: 300,
height: 300
}, {
x: 600,
y: 1600,
width: 300,
height: 300
}, {
x: 600,
y: 2000,
width: 300,
height: 300
}, {
x: 1024,
y: 400,
width: 300,
height: 300
}, {
x: 1024,
y: 800,
width: 300,
height: 300
}, {
x: 1024,
y: 1600,
width: 300,
height: 300
}, {
x: 1024,
y: 2000,
width: 300,
height: 300
},
// Right side zones (avoiding button area at top right)
{
x: 1400,
y: 600,
width: 300,
height: 300
}, {
x: 1400,
y: 1000,
width: 300,
height: 300
}, {
x: 1400,
y: 1400,
width: 300,
height: 300
}, {
x: 1400,
y: 1800,
width: 300,
height: 300
}];
// Add hardcore button
var hardcoreButton = new HardcoreButton();
hardcoreButton.x = 2048 - 150;
hardcoreButton.y = 120;
// Update button text based on current mode
hardcoreButton.children[1].setText(window.hardcoreMode ? 'NORMAL MODE' : 'HARDCORE MODE');
hardcoreButton.children[0].tint = window.hardcoreMode ? 0x00FF00 : 0xFF0000;
game.addChild(hardcoreButton);
// Add extreme mode button (only visible when hardcore is enabled)
var extremeButton = new ExtremeButton();
extremeButton.x = 2048 - 150;
extremeButton.y = 250;
extremeButton.alpha = window.hardcoreMode ? 1 : 0;
game.addChild(extremeButton);
// Add death mode button (only visible when extreme is enabled)
var deathButton = new DeathButton();
deathButton.x = 2048 - 150;
deathButton.y = 380;
deathButton.alpha = window.extremeMode ? 1 : 0;
game.addChild(deathButton);
// Universal music management function
function stopAllMusicAndPlay(musicId, options) {
// Stop any currently playing music first
LK.stopMusic();
// Play the new music
LK.playMusic(musicId, options);
}
// Game state variables
var gameTimer = 0;
var outOfSafeZoneTimer = 0;
var isPlayerInSafeZone = true;
var lastBumpTime = 0;
var nextBumpTime = 0;
var dragNode = null;
// Create the safe zone
var safeZone = new SafeZone();
safeZone.x = 2048 / 2;
safeZone.y = 2732 / 2;
game.addChild(safeZone);
// Create the player circle
var player = new PlayerCircle();
player.x = 2048 / 2;
player.y = 2732 / 2;
game.addChild(player);
// UI Elements
var timerText = new Text2('2:00', {
size: 100,
fill: 0xFFFFFF
});
timerText.anchor.set(0.5, 0);
LK.gui.top.addChild(timerText);
var instructionText = new Text2('KEEP THE CIRCLE IN THE MIDDLE', {
size: 70,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
instructionText.y = 120;
LK.gui.top.addChild(instructionText);
// Add pulsing animation to instruction text synchronized with beat
function pulseInstructionText() {
tween(instructionText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(instructionText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 300,
easing: tween.easeIn,
onFinish: pulseInstructionText
});
}
});
}
pulseInstructionText();
var warningText = new Text2('WARNING: RETURN TO SAFE ZONE!', {
size: 70,
fill: 0xFF3333
});
warningText.anchor.set(0.5, 0);
warningText.y = timerText.height + instructionText.height + 150;
warningText.alpha = 0;
LK.gui.top.addChild(warningText);
// Format time as MM:SS
function formatTime(ms) {
var seconds = Math.floor(ms / 1000);
var minutes = Math.floor(seconds / 60);
seconds = seconds % 60;
return minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
}
// Get random teleport position from safe zones
function getRandomTeleportPosition() {
var zone = SAFE_TELEPORT_ZONES[Math.floor(Math.random() * SAFE_TELEPORT_ZONES.length)];
var randomX = zone.x + Math.random() * zone.width;
var randomY = zone.y + Math.random() * zone.height;
return {
x: randomX,
y: randomY
};
}
// Schedule the next random bump
function scheduleNextBump() {
var minInterval, maxInterval;
if (window.deathMode) {
minInterval = DEATH_MIN_BUMP_INTERVAL;
maxInterval = DEATH_MAX_BUMP_INTERVAL;
} else if (window.extremeMode) {
minInterval = EXTREME_MIN_BUMP_INTERVAL;
maxInterval = EXTREME_MAX_BUMP_INTERVAL;
} else {
minInterval = MIN_BUMP_INTERVAL;
maxInterval = MAX_BUMP_INTERVAL;
}
var interval = minInterval + Math.random() * (maxInterval - minInterval);
nextBumpTime = lastBumpTime + interval;
}
// Apply a random force to push player away from center
function applyRandomBump() {
// Calculate angle away from center
var centerX = 2048 / 2;
var centerY = 2732 / 2;
var dx = player.x - centerX;
var dy = player.y - centerY;
var angle = Math.atan2(dy, dx);
// If player is at center, use a random angle
if (Math.abs(dx) < 10 && Math.abs(dy) < 10) {
angle = Math.random() * Math.PI * 2;
}
// Get current game progress (0 to 1)
var currentGameDuration = window.deathMode ? DEATH_GAME_DURATION : GAME_DURATION;
var gameProgress = Math.min(gameTimer / currentGameDuration, 1);
if (window.deathMode) {
// DEATH MODE: Ultimate chaos - 5 minutes of hell
var teleportPos = getRandomTeleportPosition();
// Teleport safe zone
safeZone.x = teleportPos.x;
safeZone.y = teleportPos.y;
// Apply massive force to player for ultimate chaos
var forceMagnitude = 80 + gameProgress * 60; // Even stronger than extreme
player.applyForce(angle, forceMagnitude);
// Add death visual effect
LK.effects.flashScreen(0x000000, 600);
// Display death message
instructionText.setText("DEATH MODE: 5 MINUTES OF HELL!");
} else if (window.extremeMode) {
// EXTREME MODE: Maximum chaos
var teleportPos = getRandomTeleportPosition();
// Teleport safe zone
safeZone.x = teleportPos.x;
safeZone.y = teleportPos.y;
// Also apply force to player in extreme mode for double chaos
var forceMagnitude = 60 + gameProgress * 40; // Much stronger force
player.applyForce(angle, forceMagnitude);
// Add extreme visual effect
LK.effects.flashScreen(0xFF0066, 500);
// Display extreme message
instructionText.setText("EXTREME MODE: 2 MINUTES OF CHAOS!");
} else if (window.hardcoreMode) {
// In hardcore mode, teleport the SAFE ZONE to a safe position
var teleportPos = getRandomTeleportPosition();
// Teleport safe zone
safeZone.x = teleportPos.x;
safeZone.y = teleportPos.y;
// Add stronger visual effect for hardcore mode
LK.effects.flashScreen(0xFF4400, 300);
// Display "Good Luck" message
instructionText.setText("HARDCORE MODE: GOOD LUCK.");
} else {
// Normal mode - apply force
// Increase force based on progress (more force as game goes on)
var forceMagnitude = 20 + (MAX_BUMP_FORCE - 20) * gameProgress; // Starting force increased from 10 to 20
// Apply the force
player.applyForce(angle, forceMagnitude);
}
// Play bump sound
LK.getSound('bump').play();
// Visual effect - flash screen slightly
LK.effects.flashScreen(0xFFFFFF, 200);
// Record time of bump and schedule next one
lastBumpTime = LK.ticks * (1000 / 60); // Convert ticks to ms
scheduleNextBump();
}
// Check if player is in safe zone
function checkPlayerInSafeZone() {
// In both modes, we need to check the distance to the safe zone
// In normal mode, safe zone is centered, but in hardcore, it could be anywhere
var dx = player.x - safeZone.x;
var dy = player.y - safeZone.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Safe zone radius is half the width of the safeZone asset
var safeZoneRadius = safeZone.children[0].width / 2;
return distance < safeZoneRadius;
}
// Handle warning display
function updateWarning() {
if (!isPlayerInSafeZone) {
// Danger progress (0 to 1)
var dangerProgress = outOfSafeZoneTimer / DANGER_TIMEOUT;
// Scale warning text based on danger progress
var scale = 1 + dangerProgress * 0.3;
warningText.scale.set(scale, scale);
// Fade in warning if it's not already visible
if (warningText.alpha < 1) {
tween(warningText, {
alpha: 1
}, {
duration: 300
});
}
// Change text color between red and white for urgency
if (dangerProgress > 0.7) {
if (LK.ticks % 15 === 0) {
// Flash every quarter second
warningText.setText(warningText.text); // Ensure text is refreshed
if (warningText.style && warningText.style.fill) {
warningText.style.fill = warningText.style.fill === "#FF3333" ? "#FFFFFF" : "#FF3333";
} else {
// Fallback if style is not properly initialized
warningText.setText(warningText.text, {
fill: warningText.style && warningText.style.fill === "#FF3333" ? "#FFFFFF" : "#FF3333"
});
}
}
}
} else {
// Fade out warning
if (warningText.alpha > 0) {
tween(warningText, {
alpha: 0
}, {
duration: 300
});
}
}
}
// Start the game
function initGame() {
// Initialize game state
gameTimer = 0;
outOfSafeZoneTimer = 0;
isPlayerInSafeZone = true;
lastBumpTime = 0;
scheduleNextBump();
// Reset positions
player.x = 2048 / 2;
player.y = 2732 / 2;
player.vx = 0;
player.vy = 0;
// Reset safe zone position to center
safeZone.x = 2048 / 2;
safeZone.y = 2732 / 2;
// Update UI based on current mode
if (window.deathMode) {
// Change title text to indicate death mode
instructionText.setText("DEATH MODE: 5 MINUTES OF HELL!");
if (!instructionText.style) instructionText.style = {};
instructionText.style.fill = "#000000";
// Make the safe zone extremely small in death mode
safeZone.children[0].scale.set(0.4, 0.4);
// Update death button text and color
if (deathButton) {
deathButton.children[1].setText('NORMAL MODE');
deathButton.children[0].tint = 0xFF0000;
}
} else if (window.extremeMode) {
// Change title text to indicate extreme mode
instructionText.setText("EXTREME MODE: 2 MINUTES OF CHAOS!");
if (!instructionText.style) instructionText.style = {};
instructionText.style.fill = "#FF0066";
// Make the safe zone even smaller in extreme mode
safeZone.children[0].scale.set(0.6, 0.6);
// Update extreme button text and color
if (extremeButton) {
extremeButton.children[1].setText('HARDCORE MODE');
extremeButton.children[0].tint = 0xFF0000;
}
} else if (window.hardcoreMode) {
// Change title text to indicate hardcore mode with "Good luck"
instructionText.setText("HARDCORE MODE: GOOD LUCK.");
if (!instructionText.style) instructionText.style = {};
instructionText.style.fill = "#FF3333";
// Make the safe zone smaller in hardcore mode
safeZone.children[0].scale.set(0.8, 0.8);
// Update hardcore button text and color
if (hardcoreButton) {
hardcoreButton.children[1].setText('NORMAL MODE');
hardcoreButton.children[0].tint = 0x00FF00;
}
// Update extreme button text and color
if (extremeButton) {
extremeButton.children[1].setText('EXTREME MODE');
extremeButton.children[0].tint = 0xFF6600;
}
} else {
// Reset to normal mode text
instructionText.setText("KEEP THE CIRCLE IN THE MIDDLE");
if (!instructionText.style) instructionText.style = {};
instructionText.style.fill = "#FFFFFF";
// Reset safe zone size
safeZone.children[0].scale.set(1, 1);
// Update hardcore button text and color
if (hardcoreButton) {
hardcoreButton.children[1].setText('HARDCORE MODE');
hardcoreButton.children[0].tint = 0xFF0000;
}
}
// Music is now handled by the hardcore button
// We don't need to start music here as it would cause duplicates
// when toggling modes via the button
// This section is kept for when the game is initially loaded
if (gameTimer === 0 && outOfSafeZoneTimer === 0) {
if (window.deathMode) {
// Death mode has no music - silence is part of the horror
LK.stopMusic();
} else if (window.extremeMode) {
// Extreme mode music
stopAllMusicAndPlay('extremedeath', {
fade: {
start: 0,
end: 1.0,
duration: 800
}
});
} else if (window.hardcoreMode) {
// Hardcore mode music - music is already playing from button press
// but ensure it's playing in case initGame is called directly
stopAllMusicAndPlay('hardcorebg', {
fade: {
start: 0,
end: 1.0,
duration: 800
}
});
} else {
// Normal mode music
stopAllMusicAndPlay('bgMusic', {
fade: {
start: 0,
end: 1.0,
// Set to full volume for intense beat
duration: 800
}
});
}
}
}
// Handle dragging
function handleMove(x, y, obj) {
if (dragNode) {
dragNode.x = x;
dragNode.y = y;
dragNode.isDragging = true;
// Reset velocity when dragging
dragNode.vx = 0;
dragNode.vy = 0;
}
}
// Mouse/touch handlers
game.down = function (x, y, obj) {
// Start dragging the player
dragNode = player;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
if (dragNode) {
dragNode.isDragging = false;
dragNode = null;
}
};
game.move = handleMove;
// Initialize the game
initGame();
// Game update loop
game.update = function () {
// Update game timer
gameTimer += 1000 / 60; // Increment by ms per frame
// Update timer display with correct duration based on mode
var currentGameDuration = window.deathMode ? DEATH_GAME_DURATION : GAME_DURATION;
var timeLeft = Math.max(0, currentGameDuration - gameTimer);
timerText.setText(formatTime(timeLeft));
// Check if player is in safe zone
var wasInSafeZone = isPlayerInSafeZone;
isPlayerInSafeZone = checkPlayerInSafeZone();
// Handle transitions between in/out of safe zone
if (wasInSafeZone && !isPlayerInSafeZone) {
// Just left safe zone
safeZone.shrink();
outOfSafeZoneTimer = 0;
} else if (!wasInSafeZone && isPlayerInSafeZone) {
// Just returned to safe zone
safeZone.grow();
}
// Update danger timer if outside safe zone
if (!isPlayerInSafeZone) {
outOfSafeZoneTimer += 1000 / 60;
// Use appropriate timeout based on mode
var currentDangerTimeout;
if (window.deathMode) {
currentDangerTimeout = DEATH_DANGER_TIMEOUT;
} else if (window.extremeMode) {
currentDangerTimeout = EXTREME_DANGER_TIMEOUT;
} else {
currentDangerTimeout = DANGER_TIMEOUT;
}
// Play warning sound at specific thresholds
if (outOfSafeZoneTimer >= currentDangerTimeout * 0.5 && LK.ticks % 30 === 0) {
LK.getSound('warning').play();
}
// Game over condition
if (outOfSafeZoneTimer >= currentDangerTimeout) {
LK.getSound('lose').play();
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
return;
}
} else {
outOfSafeZoneTimer = 0;
}
// Update warning display
updateWarning();
// Check for random bump time
var currentTime = LK.ticks * (1000 / 60);
if (nextBumpTime > 0 && currentTime >= nextBumpTime) {
applyRandomBump();
}
// Add visual beat pulse every second
if (LK.ticks % 60 === 0) {
// Flash safe zone with beat
LK.effects.flashObject(safeZone, 0x00FFFF, 200);
// Apply small "bump" to instruction text with beat
tween(instructionText, {
y: instructionText.y - 5
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(instructionText, {
y: 120
}, {
duration: 100,
easing: tween.easeIn
});
}
});
}
// Win condition
var currentGameDuration = window.deathMode ? DEATH_GAME_DURATION : GAME_DURATION;
if (gameTimer >= currentGameDuration) {
LK.getSound('win').play();
LK.effects.flashScreen(0x00FF00, 1000);
LK.showYouWin();
return;
}
};