/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, currentLevel: 1 }); /**** * Classes ****/ var Agent = Container.expand(function () { var self = Container.call(this); // Agent properties self.speed = 10; self.state = 'ready'; // ready, charging, breaching, recovering self.chargeSpeed = 0; // Create agent asset var agentAsset = self.attachAsset('agent', { anchorX: 0.5, anchorY: 0.5 }); // Create battering ram var ramAsset = self.attachAsset('ram', { anchorX: 0.5, anchorY: 0.5, x: 300, y: 0 }); // Method to charge at the door self.charge = function () { if (self.state !== 'ready') { return; } self.state = 'charging'; self.chargeSpeed = 0; }; // Method to update agent's position and state self.update = function () { if (self.state === 'charging') { // Increase charge speed self.chargeSpeed += 1; self.x += self.chargeSpeed; } else if (self.state === 'recovering') { // Move back to starting position self.x -= self.speed; if (self.x <= self.startX) { self.x = self.startX; self.state = 'ready'; } } }; // Method to reset agent self.reset = function (startX, startY) { self.startX = startX; self.startY = startY; self.x = startX; self.y = startY; self.state = 'ready'; self.chargeSpeed = 0; }; return self; }); var Door = Container.expand(function () { var self = Container.call(this); // Door properties self.health = 100; self.breachable = false; self.breached = false; // Create door asset var doorAsset = self.attachAsset('door', { anchorX: 0.5, anchorY: 0.5 }); // Doorknob removed // Breach effect (hidden initially) var breachEffect = self.attachAsset('breach_effect', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); // Method to animate the breach self.breach = function () { if (self.breached) { return; } self.breached = true; // Flash the breach effect breachEffect.alpha = 0.8; tween(breachEffect, { alpha: 0 }, { duration: 500 }); // Play door breaking sound LK.getSound('breach').play(); // Animate door opening tween(doorAsset, { rotation: Math.PI / 2 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { // Play the FBI OPEN UP sound after door opens LK.getSound('fbi_open_up').play(); } }); }; // Method to reset door self.reset = function () { doorAsset.rotation = 0; self.breached = false; self.health = 100; breachEffect.alpha = 0; }; // Method to set the door's difficulty level self.setLevel = function (level) { // Adjust door properties based on level self.health = 100 + level * 20; }; return self; }); var InstructionText = Container.expand(function () { var self = Container.call(this); // Create instruction text var instructionText = new Text2('TAP AND HOLD TO CHARGE\nRELEASE AT THE RIGHT MOMENT', { size: 60, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 0); self.addChild(instructionText); // Method to update instruction text self.updateText = function (text) { instructionText.setText(text); }; return self; }); var LevelInfo = Container.expand(function () { var self = Container.call(this); // Create level text var levelText = new Text2('LEVEL 1', { size: 80, fill: 0xFFFFFF }); levelText.anchor.set(0.5, 0); self.addChild(levelText); // Create score text var scoreText = new Text2('SCORE: 0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); scoreText.y = 100; self.addChild(scoreText); // Method to update level display self.updateLevel = function (level) { levelText.setText('LEVEL ' + level); }; // Method to update score display self.updateScore = function (score) { scoreText.setText('SCORE: ' + score); }; return self; }); var ProgressBar = Container.expand(function () { var self = Container.call(this); // Properties self.currentValue = 0; self.maxValue = 100; // Background bar var bgBar = self.attachAsset('progressBarBg', { anchorX: 0, anchorY: 0.5 }); // Progress bar var progressBar = self.attachAsset('progressBar', { anchorX: 0, anchorY: 0.5 }); // Target zone for perfect timing var targetZone = self.attachAsset('targetZone', { anchorX: 0.5, anchorY: 0.5, alpha: 0.7 }); // Update the progress bar display self.updateProgress = function (value) { self.currentValue = value; if (value > self.maxValue) { self.currentValue = self.maxValue; } if (value < 0) { self.currentValue = 0; } var percentage = self.currentValue / self.maxValue; progressBar.scale.x = percentage; }; // Set the target zone position self.setTargetZone = function (min, max) { var center = (min + max) / 2; var width = max - min; targetZone.x = bgBar.width * center; targetZone.scale.x = width; }; // Check if the current value is in the target zone self.isInTargetZone = function () { var minTarget = (targetZone.x - targetZone.width * targetZone.scale.x / 2) / bgBar.width * self.maxValue; var maxTarget = (targetZone.x + targetZone.width * targetZone.scale.x / 2) / bgBar.width * self.maxValue; return self.currentValue >= minTarget && self.currentValue <= maxTarget; }; // Reset the progress bar self.reset = function () { self.updateProgress(0); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x333333 }); /**** * Game Code ****/ // Game variables var currentLevel = storage.currentLevel || 1; var score = 0; var highScore = storage.highScore || 0; var isCharging = false; var gameState = 'ready'; // ready, charging, breaching, success, fail // Create game elements var door = new Door(); var agent = new Agent(); var progressBar = new ProgressBar(); var levelInfo = new LevelInfo(); var instructionText = new InstructionText(); // Initialize level parameters based on difficulty var levelParams = { chargeSpeed: 1, targetMin: 0.7, targetMax: 0.8, timeLimit: 5000 }; // Set up game timer var gameTimer = null; // Initialize game layout function initGame() { // Play background music LK.playMusic('game_theme'); // Set up door door.x = 2048 / 2 + 500; door.y = 2732 / 2; door.setLevel(currentLevel); game.addChild(door); // Set up agent agent.reset(400, 2732 / 2); game.addChild(agent); // Set up progress bar progressBar.x = 2048 / 2 - 750; progressBar.y = 2732 - 300; progressBar.setTargetZone(levelParams.targetMin, levelParams.targetMax); game.addChild(progressBar); // Set up level info levelInfo.x = 2048 / 2; levelInfo.y = 150; levelInfo.updateLevel(currentLevel); levelInfo.updateScore(score); game.addChild(levelInfo); // Set up instruction text instructionText.x = 2048 / 2; instructionText.y = 2732 - 450; game.addChild(instructionText); // Update level parameters based on current level updateLevelParams(); } // Update level parameters based on difficulty function updateLevelParams() { levelParams.chargeSpeed = 1 + currentLevel * 0.2; levelParams.targetMin = Math.max(0.4, 0.8 - currentLevel * 0.05); levelParams.targetMax = Math.min(0.9, levelParams.targetMin + 0.1); levelParams.timeLimit = Math.max(2000, 5000 - currentLevel * 200); // Update progress bar target zone progressBar.setTargetZone(levelParams.targetMin, levelParams.targetMax); } // Reset level for next attempt function resetLevel() { door.reset(); agent.reset(400, 2732 / 2); progressBar.reset(); gameState = 'ready'; isCharging = false; if (gameTimer) { LK.clearTimeout(gameTimer); gameTimer = null; } instructionText.updateText('TAP AND HOLD TO CHARGE\nRELEASE AT THE RIGHT MOMENT'); } // Start next level function nextLevel() { currentLevel++; storage.currentLevel = currentLevel; // Update level display levelInfo.updateLevel(currentLevel); // Update level parameters updateLevelParams(); // Reset level resetLevel(); } // Handle successful breach function handleSuccess() { gameState = 'success'; // Calculate score based on timing accuracy var accuracyBonus = progressBar.isInTargetZone() ? 100 : 50; var levelBonus = currentLevel * 50; var levelScore = 100 + accuracyBonus + levelBonus; // Update total score score += levelScore; levelInfo.updateScore(score); // Update high score if needed if (score > highScore) { highScore = score; storage.highScore = highScore; } // Show success message instructionText.updateText('PERFECT BREACH! +' + levelScore + ' POINTS'); // Play success sound LK.getSound('success').play(); // Go to next level after delay LK.setTimeout(function () { nextLevel(); }, 2000); } // Handle failed breach function handleFail(reason) { gameState = 'fail'; // Show fail message instructionText.updateText('BREACH FAILED: ' + reason); // Play fail sound LK.getSound('fail').play(); // Reset level after delay LK.setTimeout(function () { resetLevel(); }, 2000); } // Game input handlers game.down = function (x, y, obj) { if (gameState !== 'ready') { return; } // Start charging isCharging = true; gameState = 'charging'; // Set time limit for charge gameTimer = LK.setTimeout(function () { if (gameState === 'charging') { handleFail('TIME EXPIRED'); } }, levelParams.timeLimit); }; game.up = function (x, y, obj) { if (gameState !== 'charging' || !isCharging) { return; } // Stop charging and check breach success isCharging = false; gameState = 'breaching'; // Clear timeout if (gameTimer) { LK.clearTimeout(gameTimer); gameTimer = null; } // Check if breach was successful based on progress bar if (progressBar.currentValue > 0) { if (progressBar.isInTargetZone()) { // Perfect breach door.breach(); handleSuccess(); } else if (progressBar.currentValue > levelParams.targetMax * 100) { // Too much force handleFail('TOO MUCH FORCE'); } else { // Not enough force handleFail('NOT ENOUGH FORCE'); } } else { // No charge handleFail('NO CHARGE APPLIED'); } }; // Game update function game.update = function () { // Update agent agent.update(); // Update charging progress if (gameState === 'charging' && isCharging) { var newValue = progressBar.currentValue + levelParams.chargeSpeed; progressBar.updateProgress(newValue); // If progress exceeds max, auto-release if (progressBar.currentValue >= 100) { // Simulate releasing the charge game.up(0, 0, null); } } }; // Initialize the game initGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
currentLevel: 1
});
/****
* Classes
****/
var Agent = Container.expand(function () {
var self = Container.call(this);
// Agent properties
self.speed = 10;
self.state = 'ready'; // ready, charging, breaching, recovering
self.chargeSpeed = 0;
// Create agent asset
var agentAsset = self.attachAsset('agent', {
anchorX: 0.5,
anchorY: 0.5
});
// Create battering ram
var ramAsset = self.attachAsset('ram', {
anchorX: 0.5,
anchorY: 0.5,
x: 300,
y: 0
});
// Method to charge at the door
self.charge = function () {
if (self.state !== 'ready') {
return;
}
self.state = 'charging';
self.chargeSpeed = 0;
};
// Method to update agent's position and state
self.update = function () {
if (self.state === 'charging') {
// Increase charge speed
self.chargeSpeed += 1;
self.x += self.chargeSpeed;
} else if (self.state === 'recovering') {
// Move back to starting position
self.x -= self.speed;
if (self.x <= self.startX) {
self.x = self.startX;
self.state = 'ready';
}
}
};
// Method to reset agent
self.reset = function (startX, startY) {
self.startX = startX;
self.startY = startY;
self.x = startX;
self.y = startY;
self.state = 'ready';
self.chargeSpeed = 0;
};
return self;
});
var Door = Container.expand(function () {
var self = Container.call(this);
// Door properties
self.health = 100;
self.breachable = false;
self.breached = false;
// Create door asset
var doorAsset = self.attachAsset('door', {
anchorX: 0.5,
anchorY: 0.5
});
// Doorknob removed
// Breach effect (hidden initially)
var breachEffect = self.attachAsset('breach_effect', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
// Method to animate the breach
self.breach = function () {
if (self.breached) {
return;
}
self.breached = true;
// Flash the breach effect
breachEffect.alpha = 0.8;
tween(breachEffect, {
alpha: 0
}, {
duration: 500
});
// Play door breaking sound
LK.getSound('breach').play();
// Animate door opening
tween(doorAsset, {
rotation: Math.PI / 2
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Play the FBI OPEN UP sound after door opens
LK.getSound('fbi_open_up').play();
}
});
};
// Method to reset door
self.reset = function () {
doorAsset.rotation = 0;
self.breached = false;
self.health = 100;
breachEffect.alpha = 0;
};
// Method to set the door's difficulty level
self.setLevel = function (level) {
// Adjust door properties based on level
self.health = 100 + level * 20;
};
return self;
});
var InstructionText = Container.expand(function () {
var self = Container.call(this);
// Create instruction text
var instructionText = new Text2('TAP AND HOLD TO CHARGE\nRELEASE AT THE RIGHT MOMENT', {
size: 60,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
self.addChild(instructionText);
// Method to update instruction text
self.updateText = function (text) {
instructionText.setText(text);
};
return self;
});
var LevelInfo = Container.expand(function () {
var self = Container.call(this);
// Create level text
var levelText = new Text2('LEVEL 1', {
size: 80,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0);
self.addChild(levelText);
// Create score text
var scoreText = new Text2('SCORE: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
scoreText.y = 100;
self.addChild(scoreText);
// Method to update level display
self.updateLevel = function (level) {
levelText.setText('LEVEL ' + level);
};
// Method to update score display
self.updateScore = function (score) {
scoreText.setText('SCORE: ' + score);
};
return self;
});
var ProgressBar = Container.expand(function () {
var self = Container.call(this);
// Properties
self.currentValue = 0;
self.maxValue = 100;
// Background bar
var bgBar = self.attachAsset('progressBarBg', {
anchorX: 0,
anchorY: 0.5
});
// Progress bar
var progressBar = self.attachAsset('progressBar', {
anchorX: 0,
anchorY: 0.5
});
// Target zone for perfect timing
var targetZone = self.attachAsset('targetZone', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
// Update the progress bar display
self.updateProgress = function (value) {
self.currentValue = value;
if (value > self.maxValue) {
self.currentValue = self.maxValue;
}
if (value < 0) {
self.currentValue = 0;
}
var percentage = self.currentValue / self.maxValue;
progressBar.scale.x = percentage;
};
// Set the target zone position
self.setTargetZone = function (min, max) {
var center = (min + max) / 2;
var width = max - min;
targetZone.x = bgBar.width * center;
targetZone.scale.x = width;
};
// Check if the current value is in the target zone
self.isInTargetZone = function () {
var minTarget = (targetZone.x - targetZone.width * targetZone.scale.x / 2) / bgBar.width * self.maxValue;
var maxTarget = (targetZone.x + targetZone.width * targetZone.scale.x / 2) / bgBar.width * self.maxValue;
return self.currentValue >= minTarget && self.currentValue <= maxTarget;
};
// Reset the progress bar
self.reset = function () {
self.updateProgress(0);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x333333
});
/****
* Game Code
****/
// Game variables
var currentLevel = storage.currentLevel || 1;
var score = 0;
var highScore = storage.highScore || 0;
var isCharging = false;
var gameState = 'ready'; // ready, charging, breaching, success, fail
// Create game elements
var door = new Door();
var agent = new Agent();
var progressBar = new ProgressBar();
var levelInfo = new LevelInfo();
var instructionText = new InstructionText();
// Initialize level parameters based on difficulty
var levelParams = {
chargeSpeed: 1,
targetMin: 0.7,
targetMax: 0.8,
timeLimit: 5000
};
// Set up game timer
var gameTimer = null;
// Initialize game layout
function initGame() {
// Play background music
LK.playMusic('game_theme');
// Set up door
door.x = 2048 / 2 + 500;
door.y = 2732 / 2;
door.setLevel(currentLevel);
game.addChild(door);
// Set up agent
agent.reset(400, 2732 / 2);
game.addChild(agent);
// Set up progress bar
progressBar.x = 2048 / 2 - 750;
progressBar.y = 2732 - 300;
progressBar.setTargetZone(levelParams.targetMin, levelParams.targetMax);
game.addChild(progressBar);
// Set up level info
levelInfo.x = 2048 / 2;
levelInfo.y = 150;
levelInfo.updateLevel(currentLevel);
levelInfo.updateScore(score);
game.addChild(levelInfo);
// Set up instruction text
instructionText.x = 2048 / 2;
instructionText.y = 2732 - 450;
game.addChild(instructionText);
// Update level parameters based on current level
updateLevelParams();
}
// Update level parameters based on difficulty
function updateLevelParams() {
levelParams.chargeSpeed = 1 + currentLevel * 0.2;
levelParams.targetMin = Math.max(0.4, 0.8 - currentLevel * 0.05);
levelParams.targetMax = Math.min(0.9, levelParams.targetMin + 0.1);
levelParams.timeLimit = Math.max(2000, 5000 - currentLevel * 200);
// Update progress bar target zone
progressBar.setTargetZone(levelParams.targetMin, levelParams.targetMax);
}
// Reset level for next attempt
function resetLevel() {
door.reset();
agent.reset(400, 2732 / 2);
progressBar.reset();
gameState = 'ready';
isCharging = false;
if (gameTimer) {
LK.clearTimeout(gameTimer);
gameTimer = null;
}
instructionText.updateText('TAP AND HOLD TO CHARGE\nRELEASE AT THE RIGHT MOMENT');
}
// Start next level
function nextLevel() {
currentLevel++;
storage.currentLevel = currentLevel;
// Update level display
levelInfo.updateLevel(currentLevel);
// Update level parameters
updateLevelParams();
// Reset level
resetLevel();
}
// Handle successful breach
function handleSuccess() {
gameState = 'success';
// Calculate score based on timing accuracy
var accuracyBonus = progressBar.isInTargetZone() ? 100 : 50;
var levelBonus = currentLevel * 50;
var levelScore = 100 + accuracyBonus + levelBonus;
// Update total score
score += levelScore;
levelInfo.updateScore(score);
// Update high score if needed
if (score > highScore) {
highScore = score;
storage.highScore = highScore;
}
// Show success message
instructionText.updateText('PERFECT BREACH! +' + levelScore + ' POINTS');
// Play success sound
LK.getSound('success').play();
// Go to next level after delay
LK.setTimeout(function () {
nextLevel();
}, 2000);
}
// Handle failed breach
function handleFail(reason) {
gameState = 'fail';
// Show fail message
instructionText.updateText('BREACH FAILED: ' + reason);
// Play fail sound
LK.getSound('fail').play();
// Reset level after delay
LK.setTimeout(function () {
resetLevel();
}, 2000);
}
// Game input handlers
game.down = function (x, y, obj) {
if (gameState !== 'ready') {
return;
}
// Start charging
isCharging = true;
gameState = 'charging';
// Set time limit for charge
gameTimer = LK.setTimeout(function () {
if (gameState === 'charging') {
handleFail('TIME EXPIRED');
}
}, levelParams.timeLimit);
};
game.up = function (x, y, obj) {
if (gameState !== 'charging' || !isCharging) {
return;
}
// Stop charging and check breach success
isCharging = false;
gameState = 'breaching';
// Clear timeout
if (gameTimer) {
LK.clearTimeout(gameTimer);
gameTimer = null;
}
// Check if breach was successful based on progress bar
if (progressBar.currentValue > 0) {
if (progressBar.isInTargetZone()) {
// Perfect breach
door.breach();
handleSuccess();
} else if (progressBar.currentValue > levelParams.targetMax * 100) {
// Too much force
handleFail('TOO MUCH FORCE');
} else {
// Not enough force
handleFail('NOT ENOUGH FORCE');
}
} else {
// No charge
handleFail('NO CHARGE APPLIED');
}
};
// Game update function
game.update = function () {
// Update agent
agent.update();
// Update charging progress
if (gameState === 'charging' && isCharging) {
var newValue = progressBar.currentValue + levelParams.chargeSpeed;
progressBar.updateProgress(newValue);
// If progress exceeds max, auto-release
if (progressBar.currentValue >= 100) {
// Simulate releasing the charge
game.up(0, 0, null);
}
}
};
// Initialize the game
initGame();