User prompt
implement these changes Reduced timer acceleration: Changed max speed increase from 40ms to 20ms per tick, and made it trigger every 10 points instead of 5. Keep timer visible during number pad: Removed the line that clears the timer display during NumberPadOverride, and pause the main timer while the mini-game is active. Reasonable malfunction chance: Capped at 35% instead of 60% and reduced the increase rate. Consistent timer display: Removed unnecessary timer resets that were causing display issues.
User prompt
Sometimes, when doing the screwing puzzle, the wire pops up, making the players to click the wire unfortunately fix it
User prompt
after completing any puzzles, like the screwing or the num pad one, add 3 more seconds to the timer
User prompt
add Run music on the background
User prompt
When the screwing puzzle comes instead of ending the game if I click somewhere else, flash red on the screen and reduce the timer instead
User prompt
Decrease the text size now
User prompt
little more
User prompt
bring the "Cut the correct wire to defuse the bomb" little down
User prompt
On the starter put "Ready to Defuse the bomb", On top of the screen before the game starts put "Cut the correct wire to defuse the bomb" Make these words disappear when the Starter is clicked
User prompt
I want to make like this, the Starter asset is like a closing plate for panel_border, meaning that Starter is just like a closed panel, clicking it opens the bomb, and let's us defuse it
User prompt
If the starter asset is the there, don't hide other assets on the screen
User prompt
put the Starter in the middle of the screen at the background everything should exist
User prompt
Have everything with the Starter as well, take out the timer, screen display
User prompt
Put the Starter asset in the middle of the screen, pause the timer until that when clicked on the Starter asset, the game should start letting the timer to resume.
User prompt
Only trigger the num pad event or puzzle after the wires are reset
User prompt
Sometimes, the num pad appears without resetting the countdown even after cutting the wire ( fix that)
Code edit (1 edits merged)
Please save this source code
User prompt
Do not shuffle the numbers in the num pad, let it stay static, and also don't make the code disappear
User prompt
looks like the wires can be clicked after the num pad override appears, fix that. And also trigger randomly this event as soon as the wires are reset
User prompt
center the numpadoverlay, it is in the top left away from the screen
User prompt
Puzzle Name: Number Pad Override 🎮 Event Type: Random timed event during gameplay 🧠 Description / Prompt: A Number Pad Override puzzle appears as a surprise challenge. The screen displays a number pad (0–9), and a side note flashes a 4-digit code (e.g., 4827). The player must click the numbers in the exact order shown on the side note within a short time limit (e.g., 5–7 seconds). If the player clicks incorrectly or runs out of time, the bomb explodes and the game ends. If done correctly, the player is allowed to continue defusing the bomb. 🎯 Goal: Add tension and force quick recognition + reaction skills. ⚠️ Fail Condition: Wrong input = instant loss Timeout = instant loss ✨ Optional Variations: Numbers on the pad shuffle positions after each click. The displayed code fades out after 2 seconds. A distracting sound or screen flicker effect plays during the puzzle.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // NumberPadOverride class (Number Pad Override puzzle) var NumberPadOverride = Container.expand(function () { var self = Container.call(this); // Puzzle state self.active = false; self.code = []; self.input = []; self.timeLimit = 6000; // ms, can be randomized 5000-7000 self.timer = null; self.codeText = null; self.padButtons = []; self.onResult = null; // function(success) self.shufflePad = true; // shuffle after each click self.fadeCode = true; // code fades after 2s self.flicker = true; // screen flicker effect self._codeFadeTimeout = null; self._flickerTimeout = null; // Background overlay var overlay = self.attachAsset('CommBack', { anchorX: 0.5, anchorY: 0.5, width: 2048, height: 2732, alpha: 0.92, x: 0, y: 0 }); // Puzzle panel var panel = new Container(); panel.x = 0; panel.y = 0; self.addChild(panel); // Panel background var panelBg = panel.attachAsset('panel_bg', { anchorX: 0.5, anchorY: 0.5, width: 900, height: 1100, x: 0, y: 0 }); // Code display self.codeText = new Text2('', { size: 120, fill: '#fc1100' }); self.codeText.anchor.set(0.5, 0.5); self.codeText.x = 0; self.codeText.y = -400; panel.addChild(self.codeText); // Timer number self.timerText = new Text2('', { size: 90, fill: '#fc1100' }); self.timerText.anchor.set(0.5, 0.5); self.timerText.x = 0; self.timerText.y = -250; panel.addChild(self.timerText); // Pad buttons (0-9) self._createPad = function (numbers) { // Remove old buttons for (var i = 0; i < self.padButtons.length; i++) { self.padButtons[i].destroy(); } self.padButtons = []; // Layout: 3x4 grid (0 at bottom center) var padOrder = numbers || [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; var positions = [[-180, -60], [0, -60], [180, -60], [-180, 120], [0, 120], [180, 120], [-180, 300], [0, 300], [180, 300], [0, 480]]; for (var i = 0; i < 10; i++) { var n = padOrder[i]; var btn = new Container(); var btnBg = btn.attachAsset('panel_border', { anchorX: 0.5, anchorY: 0.5, width: 160, height: 160, x: 0, y: 0 }); var btnText = new Text2('' + n, { size: 90, fill: '#222' }); btnText.anchor.set(0.5, 0.5); btnText.x = 0; btnText.y = 0; btn.addChild(btnText); btn.x = positions[i][0]; btn.y = positions[i][1]; // Touch/click event (function (num) { btn.down = function (x, y, obj) { self._handleInput(num); }; })(n); panel.addChild(btn); self.padButtons.push(btn); } }; // Shuffle pad numbers self._shufflePadNumbers = function () { var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; for (var i = arr.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var t = arr[i]; arr[i] = arr[j]; arr[j] = t; } return arr; }; // Start the puzzle self.start = function (code, timeLimit, onResult) { self.active = true; self.code = code.slice(); self.input = []; self.timeLimit = timeLimit || 5000 + Math.floor(Math.random() * 2000); self.onResult = onResult; self.visible = true; // Show code self.codeText.setText(code.join('')); self.codeText.visible = true; // Timer self._startTime = Date.now(); self._endTime = self._startTime + self.timeLimit; self._updateTimer(); if (self.timer) LK.clearInterval(self.timer); self.timer = LK.setInterval(self._updateTimer, 60); // Pad var padNums = self.shufflePad ? self._shufflePadNumbers() : [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; self._createPad(padNums); // Fade code after 2s if (self.fadeCode) { if (self._codeFadeTimeout) LK.clearTimeout(self._codeFadeTimeout); self._codeFadeTimeout = LK.setTimeout(function () { self.codeText.visible = false; }, 2000); } // Flicker effect if (self.flicker) { if (self._flickerTimeout) LK.clearTimeout(self._flickerTimeout); self._flickerTimeout = LK.setTimeout(function () { LK.effects.flashScreen(0xffffff, 120); }, 800 + Math.floor(Math.random() * 800)); } }; // Handle input self._handleInput = function (num) { if (!self.active) return; self.input.push(num); // Animate button press for (var i = 0; i < self.padButtons.length; i++) { var btn = self.padButtons[i]; var btnText = btn.children[1]; if (btnText && btnText.text == num) { tween(btn, { scaleX: 0.85, scaleY: 0.85 }, { duration: 60, yoyo: true, repeat: 1 }); } } // Shuffle pad after each click if (self.shufflePad) { var padNums = self._shufflePadNumbers(); self._createPad(padNums); } // Check input for (var i = 0; i < self.input.length; i++) { if (self.input[i] !== self.code[i]) { // Wrong input: fail instantly self._fail(); return; } } if (self.input.length === self.code.length) { // Success! self._success(); } }; // Timer update self._updateTimer = function () { if (!self.active) return; var now = Date.now(); var msLeft = Math.max(0, self._endTime - now); var secLeft = Math.ceil(msLeft / 1000); self.timerText.setText(secLeft); self.timerText.setStyle({ fill: '#fc1100' }); if (msLeft <= 0) { self._fail(); } }; // Success self._success = function () { self.active = false; if (self.timer) LK.clearInterval(self.timer); if (self._codeFadeTimeout) LK.clearTimeout(self._codeFadeTimeout); if (self._flickerTimeout) LK.clearTimeout(self._flickerTimeout); self.visible = false; if (typeof self.onResult === 'function') self.onResult(true); }; // Fail self._fail = function () { self.active = false; if (self.timer) LK.clearInterval(self.timer); if (self._codeFadeTimeout) LK.clearTimeout(self._codeFadeTimeout); if (self._flickerTimeout) LK.clearTimeout(self._flickerTimeout); self.visible = false; // Play fail sound and flash LK.getSound('fail').play(); LK.effects.flashScreen(0xff0000, 600); if (typeof self.onResult === 'function') self.onResult(false); }; // Clean up self.destroy = function () { if (self.timer) LK.clearInterval(self.timer); if (self._codeFadeTimeout) LK.clearTimeout(self._codeFadeTimeout); if (self._flickerTimeout) LK.clearTimeout(self._flickerTimeout); for (var i = 0; i < self.padButtons.length; i++) { self.padButtons[i].destroy(); } self.padButtons = []; self.visible = false; }; self.visible = false; return self; }); // Screw class (for malfunction minigame) var Screw = Container.expand(function () { var self = Container.call(this); self.fixed = false; self.screwAsset = self.attachAsset('screw', { anchorX: 0.5, anchorY: 0.5 }); // Touch/click event self.down = function (x, y, obj) { if (self.fixed) { return; } self.fixed = true; // Animate: fade out and shrink tween(self, { scaleX: 0.1, scaleY: 0.1, alpha: 0 }, { duration: 200, easing: tween.cubicIn, onFinish: function onFinish() { self.visible = false; } }); if (typeof self.onFix === 'function') { self.onFix(self); } }; return self; }); // Wire class var Wire = Container.expand(function () { var self = Container.call(this); // Properties self.color = 'red'; // default, will be set on init self.cut = false; // Attach asset self.wireAsset = null; self.init = function (color) { self.color = color; self.cut = false; var assetId = 'wire_' + color; self.wireAsset = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); }; // Cut animation self.cutWire = function () { if (self.cut) { return; } self.cut = true; // Animate: fade out and shrink tween(self, { scaleX: 0.1, scaleY: 0.1, alpha: 0 }, { duration: 300, easing: tween.cubicIn, onFinish: function onFinish() { self.visible = false; } }); }; // Touch/click event self.down = function (x, y, obj) { if (self.cut) { return; } if (typeof self.onCut === 'function') { self.onCut(self); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181818 }); /**** * Game Code ****/ // --- Game constants --- // Wires: red, blue, green, yellow, black, white // Panel // Communication screen // Screw (for malfunction minigame) // Malfunction overlay // Sounds var WIRE_COLORS = ['red', 'blue', 'green', 'yellow', 'black', 'white']; var WIRES_PER_PANEL = 4; var PANEL_X = 2048 / 2; var PANEL_Y = 2732 / 2; var PANEL_W = 700; var PANEL_H = 500; var SCREEN_H = 180; var ROUND_TIME = 8000; // ms per round var MALFUNCTION_CHANCE = 0.18; // 18% chance per round // --- Game state --- var wires = []; var panel = null; var screen = null; var screenText = null; var malOverlay = null; var screws = []; var screwBox = null; // Box for screws during malfunction minigame var malfunctionActive = false; var roundTimer = null; var timeLeft = 0; var timerBar = null; var correctWireColor = ''; var canCut = true; var scoreText = null; var roundNum = 0; var tickingSoundTimer = null; // --- GUI --- scoreText = new Text2('0', { size: 120, fill: "#fff" }); scoreText.anchor.set(0.5, 1); LK.gui.bottom.addChild(scoreText); // Timer bar timerBar = LK.getAsset('panel_bg', { width: 600, height: 24, color: 0x44ff44, anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 180 }); game.addChild(timerBar); // --- Panel setup --- panel = new Container(); var panelBorder = panel.attachAsset('panel_border', { anchorX: 0.5, anchorY: 0.5 }); var panelBg = panel.attachAsset('panel_bg', { anchorX: 0.5, anchorY: 0.5 }); // Add a box inside the panel_bg (steel panel) var innerBox = panel.attachAsset('panel_border', { anchorX: 0.5, anchorY: 0.5, width: 900, // slightly smaller than panel_bg (1500x2000), visually inside height: 1200, x: 0, y: 50 // move it down a bit to be inside the panel visually }); panel.x = PANEL_X; panel.y = PANEL_Y; game.addChild(panel); // --- Communication screen --- screen = new Container(); var screenBg = screen.attachAsset('screen', { anchorX: 0.5, anchorY: 0.5 }); screen.x = 0; // Place the screen at the top of the panel, matching the panel_bg aspect ratio (panel_bg is 1500x2000, so screen should be near the top edge) screen.y = -1000 + SCREEN_H / 2 + 60 + 40; // -1000 is half of 2000 (panel_bg height), add some margin panel.addChild(screen); screenText = new Text2('', { size: 60, fill: "#fff" }); screenText.anchor.set(0.5, 0.5); screen.addChild(screenText); // Malfunction overlay (hidden by default) malOverlay = LK.getAsset('mal_overlay', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, alpha: 0.8 }); // Center malOverlay in the middle of the screen container malOverlay.x = 0; malOverlay.y = 0; malOverlay.visible = false; screen.addChild(malOverlay); // --- Functions --- function shuffle(arr) { // Fisher-Yates shuffle for (var i = arr.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var t = arr[i]; arr[i] = arr[j]; arr[j] = t; } return arr; } function startRound() { roundNum += 1; canCut = true; malfunctionActive = false; // Remove old wires for (var i = 0; i < wires.length; i++) { wires[i].destroy(); } wires = []; // Remove screws if any for (var i = 0; i < screws.length; i++) { screws[i].destroy(); } screws = []; // Randomize wires var colorPool = shuffle(WIRE_COLORS.slice()); var roundWires = colorPool.slice(0, WIRES_PER_PANEL); // Pick correct wire correctWireColor = roundWires[Math.floor(Math.random() * roundWires.length)]; // Place wires vertically in panel var spacing = PANEL_H / (WIRES_PER_PANEL + 1); for (var i = 0; i < roundWires.length; i++) { var w = new Wire(); w.init(roundWires[i]); w.x = 0; w.y = -PANEL_H / 2 + spacing * (i + 1) + 40; w.onCut = handleWireCut; panel.addChild(w); wires.push(w); } // Set screen text screenText.setText(correctWireColor.toUpperCase() + ' WIRE!'); screenText.visible = true; screenText.setStyle({ fill: '#309191' }); // Always set text color to black for correctWireColor malOverlay.visible = false; // Malfunction? var malfunctionChance = MALFUNCTION_CHANCE; if (LK.getScore() > 30) { // Gradually increase malfunction chance after score 30, up to 60% malfunctionChance = Math.min(0.6, MALFUNCTION_CHANCE + 0.02 * (LK.getScore() - 30)); } if (Math.random() < malfunctionChance) { LK.setTimeout(triggerMalfunction, 600 + Math.floor(Math.random() * 800)); } // Start timer timeLeft = ROUND_TIME; updateTimerBar(); if (roundTimer) { LK.clearInterval(roundTimer); } roundTimer = LK.setInterval(tickTimer, 30); // Ticking sound if (tickingSoundTimer) { LK.clearInterval(tickingSoundTimer); } tickingSoundTimer = LK.setInterval(function () { LK.getSound('tick').play(); }, 1000); } function handleWireCut(wire) { if (!canCut || malfunctionActive && !screws.length) { return; } canCut = false; wire.cutWire(); if (wire.color === correctWireColor) { // Success! LK.getSound('cut').play(); LK.setScore(LK.getScore() + 1); scoreText.setText(LK.getScore()); // Animate panel flash green LK.effects.flashObject(panel, 0x44ff44, 300); // Next round after short delay LK.setTimeout(startRound, 700); } else { // Wrong wire! LK.getSound('fail').play(); LK.effects.flashScreen(0xff0000, 600); LK.setScore(Math.max(0, LK.getScore() - 1)); scoreText.setText(LK.getScore()); // Game over LK.setTimeout(function () { LK.showGameOver(); }, 600); } } function tickTimer() { if (!canCut) { return; } // Gradually speed up timer after score > 20 var timerDecrement = 30; var score = LK.getScore(); if (score > 20) { // Increase speed: for every 5 points above 20, timerDecrement increases by 2ms, up to a max of 60ms per tick var extra = Math.min(40, Math.floor((score - 20) / 5) * 2); timerDecrement += extra; } timeLeft -= timerDecrement; // --- Add: Score increases with time (every 1000ms, +1 score) --- if (typeof tickTimer._accum === "undefined") { tickTimer._accum = 0; tickTimer._lastScoreTime = 0; } tickTimer._accum += timerDecrement; if (tickTimer._accum - tickTimer._lastScoreTime >= 1000) { LK.setScore(LK.getScore() + 1); scoreText.setText(LK.getScore()); tickTimer._lastScoreTime += 1000; } updateTimerBar(); if (timeLeft <= 0) { canCut = false; LK.getSound('fail').play(); LK.effects.flashScreen(0xff0000, 600); LK.setTimeout(function () { LK.showGameOver(); }, 600); } } function updateTimerBar() { // Remove bar visual, show countdown number instead timerBar.visible = false; // Add or update a countdown number Text2 object if (typeof updateTimerBar.timerNumber === "undefined") { updateTimerBar.timerNumber = new Text2('', { size: 100, fill: '#fc1100' }); updateTimerBar.timerNumber.anchor.set(0.5, 0.5); updateTimerBar.timerNumber.x = 2048 / 2; updateTimerBar.timerNumber.y = 180; game.addChild(updateTimerBar.timerNumber); } var secondsLeft = Math.ceil(Math.max(0, timeLeft) / 1000); updateTimerBar.timerNumber.setText(secondsLeft); // Always set timer number text color to red updateTimerBar.timerNumber.setStyle({ fill: '#fc1100' }); } function triggerMalfunction() { if (!canCut) { return; } malfunctionActive = true; screenText.visible = false; malOverlay.visible = true; // Hide screws for now, only show after click for (var i = 0; i < screws.length; i++) { screws[i].destroy(); } screws = []; // Randomly choose malfunction type: 50% screw, 50% number pad override var useNumberPad = Math.random() < 0.5; if (useNumberPad) { // --- Number Pad Override puzzle --- if (typeof game._numberPadOverride === "undefined" || !game._numberPadOverride) { game._numberPadOverride = new NumberPadOverride(); game.addChild(game._numberPadOverride); } var code = []; for (var i = 0; i < 4; i++) code.push(Math.floor(Math.random() * 10)); var timeLimit = 5000 + Math.floor(Math.random() * 2000); // 5-7s game._numberPadOverride.start(code, timeLimit, function (success) { malfunctionActive = false; malOverlay.visible = false; screenText.visible = true; if (!success) { // Game over LK.setTimeout(function () { LK.showGameOver(); }, 600); } }); LK.getSound('beep').play(); return; } // --- Screw minigame fallback --- // Add a one-time click handler to the screen to show the screw minigame screen.down = function (x, y, obj) { // Remove this handler after first click screen.down = undefined; // Create a new box (screwBox) that will contain the screws, centered on the bomb/panel if (typeof screwBox !== "undefined" && screwBox && screwBox.parent) { screwBox.parent.removeChild(screwBox); } screwBox = new Container(); // Add a background for the screwBox (use panel_border for visual consistency) var screwBoxBg = screwBox.attachAsset('CommBack', { anchorX: 0.5, anchorY: 0.5, width: 1500, // Match panel_bg width height: 1000, // Half of panel_bg height (2000px) x: 0, y: 0 }); // Center the screwBox on the panel screwBox.x = 0; screwBox.y = 0; panel.addChild(screwBox); // Show screws at random positions inside the screwBox var screwCount = 3 + Math.floor(Math.random() * 2); // 3 or 4 screws = []; for (var i = 0; i < screwCount; i++) { var s = new Screw(); // Place randomly within the screwBox area s.x = -220 + Math.random() * 440; s.y = -120 + Math.random() * 240; s.onFix = function (screw) { handleScrewFix(screw); // If all screws are fixed, remove the screwBox and return to bomb screen var allFixed = true; for (var j = 0; j < screws.length; j++) { if (!screws[j].fixed) { allFixed = false; break; } } if (allFixed) { if (screwBox && screwBox.parent) { screwBox.parent.removeChild(screwBox); } screwBox = null; } }; screwBox.addChild(s); screws.push(s); } LK.getSound('beep').play(); }; } function handleScrewFix(screw) { // Don't allow fixing screws if the minigame hasn't started (blank screen) if (!screws.length) { return; } LK.getSound('fix').play(); // Check if all screws fixed var allFixed = true; for (var i = 0; i < screws.length; i++) { if (!screws[i].fixed) { allFixed = false; break; } } if (allFixed) { malfunctionActive = false; malOverlay.visible = false; screenText.visible = true; // Remove screws from screen for (var i = 0; i < screws.length; i++) { screws[i].destroy(); } screws = []; // Remove any leftover click handler screen.down = undefined; } } // --- Game event handlers --- // Drag prevention: no drag in this game game.move = function (x, y, obj) {}; // --- Game update loop --- game.update = function () { // Win condition: e.g. 20 points if (LK.getScore() >= 99999999999) { LK.showYouWin(); } }; // --- Start game --- LK.setScore(0); scoreText.setText('0'); startRound();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// NumberPadOverride class (Number Pad Override puzzle)
var NumberPadOverride = Container.expand(function () {
var self = Container.call(this);
// Puzzle state
self.active = false;
self.code = [];
self.input = [];
self.timeLimit = 6000; // ms, can be randomized 5000-7000
self.timer = null;
self.codeText = null;
self.padButtons = [];
self.onResult = null; // function(success)
self.shufflePad = true; // shuffle after each click
self.fadeCode = true; // code fades after 2s
self.flicker = true; // screen flicker effect
self._codeFadeTimeout = null;
self._flickerTimeout = null;
// Background overlay
var overlay = self.attachAsset('CommBack', {
anchorX: 0.5,
anchorY: 0.5,
width: 2048,
height: 2732,
alpha: 0.92,
x: 0,
y: 0
});
// Puzzle panel
var panel = new Container();
panel.x = 0;
panel.y = 0;
self.addChild(panel);
// Panel background
var panelBg = panel.attachAsset('panel_bg', {
anchorX: 0.5,
anchorY: 0.5,
width: 900,
height: 1100,
x: 0,
y: 0
});
// Code display
self.codeText = new Text2('', {
size: 120,
fill: '#fc1100'
});
self.codeText.anchor.set(0.5, 0.5);
self.codeText.x = 0;
self.codeText.y = -400;
panel.addChild(self.codeText);
// Timer number
self.timerText = new Text2('', {
size: 90,
fill: '#fc1100'
});
self.timerText.anchor.set(0.5, 0.5);
self.timerText.x = 0;
self.timerText.y = -250;
panel.addChild(self.timerText);
// Pad buttons (0-9)
self._createPad = function (numbers) {
// Remove old buttons
for (var i = 0; i < self.padButtons.length; i++) {
self.padButtons[i].destroy();
}
self.padButtons = [];
// Layout: 3x4 grid (0 at bottom center)
var padOrder = numbers || [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
var positions = [[-180, -60], [0, -60], [180, -60], [-180, 120], [0, 120], [180, 120], [-180, 300], [0, 300], [180, 300], [0, 480]];
for (var i = 0; i < 10; i++) {
var n = padOrder[i];
var btn = new Container();
var btnBg = btn.attachAsset('panel_border', {
anchorX: 0.5,
anchorY: 0.5,
width: 160,
height: 160,
x: 0,
y: 0
});
var btnText = new Text2('' + n, {
size: 90,
fill: '#222'
});
btnText.anchor.set(0.5, 0.5);
btnText.x = 0;
btnText.y = 0;
btn.addChild(btnText);
btn.x = positions[i][0];
btn.y = positions[i][1];
// Touch/click event
(function (num) {
btn.down = function (x, y, obj) {
self._handleInput(num);
};
})(n);
panel.addChild(btn);
self.padButtons.push(btn);
}
};
// Shuffle pad numbers
self._shufflePadNumbers = function () {
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
for (var i = arr.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
return arr;
};
// Start the puzzle
self.start = function (code, timeLimit, onResult) {
self.active = true;
self.code = code.slice();
self.input = [];
self.timeLimit = timeLimit || 5000 + Math.floor(Math.random() * 2000);
self.onResult = onResult;
self.visible = true;
// Show code
self.codeText.setText(code.join(''));
self.codeText.visible = true;
// Timer
self._startTime = Date.now();
self._endTime = self._startTime + self.timeLimit;
self._updateTimer();
if (self.timer) LK.clearInterval(self.timer);
self.timer = LK.setInterval(self._updateTimer, 60);
// Pad
var padNums = self.shufflePad ? self._shufflePadNumbers() : [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
self._createPad(padNums);
// Fade code after 2s
if (self.fadeCode) {
if (self._codeFadeTimeout) LK.clearTimeout(self._codeFadeTimeout);
self._codeFadeTimeout = LK.setTimeout(function () {
self.codeText.visible = false;
}, 2000);
}
// Flicker effect
if (self.flicker) {
if (self._flickerTimeout) LK.clearTimeout(self._flickerTimeout);
self._flickerTimeout = LK.setTimeout(function () {
LK.effects.flashScreen(0xffffff, 120);
}, 800 + Math.floor(Math.random() * 800));
}
};
// Handle input
self._handleInput = function (num) {
if (!self.active) return;
self.input.push(num);
// Animate button press
for (var i = 0; i < self.padButtons.length; i++) {
var btn = self.padButtons[i];
var btnText = btn.children[1];
if (btnText && btnText.text == num) {
tween(btn, {
scaleX: 0.85,
scaleY: 0.85
}, {
duration: 60,
yoyo: true,
repeat: 1
});
}
}
// Shuffle pad after each click
if (self.shufflePad) {
var padNums = self._shufflePadNumbers();
self._createPad(padNums);
}
// Check input
for (var i = 0; i < self.input.length; i++) {
if (self.input[i] !== self.code[i]) {
// Wrong input: fail instantly
self._fail();
return;
}
}
if (self.input.length === self.code.length) {
// Success!
self._success();
}
};
// Timer update
self._updateTimer = function () {
if (!self.active) return;
var now = Date.now();
var msLeft = Math.max(0, self._endTime - now);
var secLeft = Math.ceil(msLeft / 1000);
self.timerText.setText(secLeft);
self.timerText.setStyle({
fill: '#fc1100'
});
if (msLeft <= 0) {
self._fail();
}
};
// Success
self._success = function () {
self.active = false;
if (self.timer) LK.clearInterval(self.timer);
if (self._codeFadeTimeout) LK.clearTimeout(self._codeFadeTimeout);
if (self._flickerTimeout) LK.clearTimeout(self._flickerTimeout);
self.visible = false;
if (typeof self.onResult === 'function') self.onResult(true);
};
// Fail
self._fail = function () {
self.active = false;
if (self.timer) LK.clearInterval(self.timer);
if (self._codeFadeTimeout) LK.clearTimeout(self._codeFadeTimeout);
if (self._flickerTimeout) LK.clearTimeout(self._flickerTimeout);
self.visible = false;
// Play fail sound and flash
LK.getSound('fail').play();
LK.effects.flashScreen(0xff0000, 600);
if (typeof self.onResult === 'function') self.onResult(false);
};
// Clean up
self.destroy = function () {
if (self.timer) LK.clearInterval(self.timer);
if (self._codeFadeTimeout) LK.clearTimeout(self._codeFadeTimeout);
if (self._flickerTimeout) LK.clearTimeout(self._flickerTimeout);
for (var i = 0; i < self.padButtons.length; i++) {
self.padButtons[i].destroy();
}
self.padButtons = [];
self.visible = false;
};
self.visible = false;
return self;
});
// Screw class (for malfunction minigame)
var Screw = Container.expand(function () {
var self = Container.call(this);
self.fixed = false;
self.screwAsset = self.attachAsset('screw', {
anchorX: 0.5,
anchorY: 0.5
});
// Touch/click event
self.down = function (x, y, obj) {
if (self.fixed) {
return;
}
self.fixed = true;
// Animate: fade out and shrink
tween(self, {
scaleX: 0.1,
scaleY: 0.1,
alpha: 0
}, {
duration: 200,
easing: tween.cubicIn,
onFinish: function onFinish() {
self.visible = false;
}
});
if (typeof self.onFix === 'function') {
self.onFix(self);
}
};
return self;
});
// Wire class
var Wire = Container.expand(function () {
var self = Container.call(this);
// Properties
self.color = 'red'; // default, will be set on init
self.cut = false;
// Attach asset
self.wireAsset = null;
self.init = function (color) {
self.color = color;
self.cut = false;
var assetId = 'wire_' + color;
self.wireAsset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
};
// Cut animation
self.cutWire = function () {
if (self.cut) {
return;
}
self.cut = true;
// Animate: fade out and shrink
tween(self, {
scaleX: 0.1,
scaleY: 0.1,
alpha: 0
}, {
duration: 300,
easing: tween.cubicIn,
onFinish: function onFinish() {
self.visible = false;
}
});
};
// Touch/click event
self.down = function (x, y, obj) {
if (self.cut) {
return;
}
if (typeof self.onCut === 'function') {
self.onCut(self);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181818
});
/****
* Game Code
****/
// --- Game constants ---
// Wires: red, blue, green, yellow, black, white
// Panel
// Communication screen
// Screw (for malfunction minigame)
// Malfunction overlay
// Sounds
var WIRE_COLORS = ['red', 'blue', 'green', 'yellow', 'black', 'white'];
var WIRES_PER_PANEL = 4;
var PANEL_X = 2048 / 2;
var PANEL_Y = 2732 / 2;
var PANEL_W = 700;
var PANEL_H = 500;
var SCREEN_H = 180;
var ROUND_TIME = 8000; // ms per round
var MALFUNCTION_CHANCE = 0.18; // 18% chance per round
// --- Game state ---
var wires = [];
var panel = null;
var screen = null;
var screenText = null;
var malOverlay = null;
var screws = [];
var screwBox = null; // Box for screws during malfunction minigame
var malfunctionActive = false;
var roundTimer = null;
var timeLeft = 0;
var timerBar = null;
var correctWireColor = '';
var canCut = true;
var scoreText = null;
var roundNum = 0;
var tickingSoundTimer = null;
// --- GUI ---
scoreText = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreText.anchor.set(0.5, 1);
LK.gui.bottom.addChild(scoreText);
// Timer bar
timerBar = LK.getAsset('panel_bg', {
width: 600,
height: 24,
color: 0x44ff44,
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 180
});
game.addChild(timerBar);
// --- Panel setup ---
panel = new Container();
var panelBorder = panel.attachAsset('panel_border', {
anchorX: 0.5,
anchorY: 0.5
});
var panelBg = panel.attachAsset('panel_bg', {
anchorX: 0.5,
anchorY: 0.5
});
// Add a box inside the panel_bg (steel panel)
var innerBox = panel.attachAsset('panel_border', {
anchorX: 0.5,
anchorY: 0.5,
width: 900,
// slightly smaller than panel_bg (1500x2000), visually inside
height: 1200,
x: 0,
y: 50 // move it down a bit to be inside the panel visually
});
panel.x = PANEL_X;
panel.y = PANEL_Y;
game.addChild(panel);
// --- Communication screen ---
screen = new Container();
var screenBg = screen.attachAsset('screen', {
anchorX: 0.5,
anchorY: 0.5
});
screen.x = 0;
// Place the screen at the top of the panel, matching the panel_bg aspect ratio (panel_bg is 1500x2000, so screen should be near the top edge)
screen.y = -1000 + SCREEN_H / 2 + 60 + 40; // -1000 is half of 2000 (panel_bg height), add some margin
panel.addChild(screen);
screenText = new Text2('', {
size: 60,
fill: "#fff"
});
screenText.anchor.set(0.5, 0.5);
screen.addChild(screenText);
// Malfunction overlay (hidden by default)
malOverlay = LK.getAsset('mal_overlay', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
alpha: 0.8
});
// Center malOverlay in the middle of the screen container
malOverlay.x = 0;
malOverlay.y = 0;
malOverlay.visible = false;
screen.addChild(malOverlay);
// --- Functions ---
function shuffle(arr) {
// Fisher-Yates shuffle
for (var i = arr.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
return arr;
}
function startRound() {
roundNum += 1;
canCut = true;
malfunctionActive = false;
// Remove old wires
for (var i = 0; i < wires.length; i++) {
wires[i].destroy();
}
wires = [];
// Remove screws if any
for (var i = 0; i < screws.length; i++) {
screws[i].destroy();
}
screws = [];
// Randomize wires
var colorPool = shuffle(WIRE_COLORS.slice());
var roundWires = colorPool.slice(0, WIRES_PER_PANEL);
// Pick correct wire
correctWireColor = roundWires[Math.floor(Math.random() * roundWires.length)];
// Place wires vertically in panel
var spacing = PANEL_H / (WIRES_PER_PANEL + 1);
for (var i = 0; i < roundWires.length; i++) {
var w = new Wire();
w.init(roundWires[i]);
w.x = 0;
w.y = -PANEL_H / 2 + spacing * (i + 1) + 40;
w.onCut = handleWireCut;
panel.addChild(w);
wires.push(w);
}
// Set screen text
screenText.setText(correctWireColor.toUpperCase() + ' WIRE!');
screenText.visible = true;
screenText.setStyle({
fill: '#309191'
}); // Always set text color to black for correctWireColor
malOverlay.visible = false;
// Malfunction?
var malfunctionChance = MALFUNCTION_CHANCE;
if (LK.getScore() > 30) {
// Gradually increase malfunction chance after score 30, up to 60%
malfunctionChance = Math.min(0.6, MALFUNCTION_CHANCE + 0.02 * (LK.getScore() - 30));
}
if (Math.random() < malfunctionChance) {
LK.setTimeout(triggerMalfunction, 600 + Math.floor(Math.random() * 800));
}
// Start timer
timeLeft = ROUND_TIME;
updateTimerBar();
if (roundTimer) {
LK.clearInterval(roundTimer);
}
roundTimer = LK.setInterval(tickTimer, 30);
// Ticking sound
if (tickingSoundTimer) {
LK.clearInterval(tickingSoundTimer);
}
tickingSoundTimer = LK.setInterval(function () {
LK.getSound('tick').play();
}, 1000);
}
function handleWireCut(wire) {
if (!canCut || malfunctionActive && !screws.length) {
return;
}
canCut = false;
wire.cutWire();
if (wire.color === correctWireColor) {
// Success!
LK.getSound('cut').play();
LK.setScore(LK.getScore() + 1);
scoreText.setText(LK.getScore());
// Animate panel flash green
LK.effects.flashObject(panel, 0x44ff44, 300);
// Next round after short delay
LK.setTimeout(startRound, 700);
} else {
// Wrong wire!
LK.getSound('fail').play();
LK.effects.flashScreen(0xff0000, 600);
LK.setScore(Math.max(0, LK.getScore() - 1));
scoreText.setText(LK.getScore());
// Game over
LK.setTimeout(function () {
LK.showGameOver();
}, 600);
}
}
function tickTimer() {
if (!canCut) {
return;
}
// Gradually speed up timer after score > 20
var timerDecrement = 30;
var score = LK.getScore();
if (score > 20) {
// Increase speed: for every 5 points above 20, timerDecrement increases by 2ms, up to a max of 60ms per tick
var extra = Math.min(40, Math.floor((score - 20) / 5) * 2);
timerDecrement += extra;
}
timeLeft -= timerDecrement;
// --- Add: Score increases with time (every 1000ms, +1 score) ---
if (typeof tickTimer._accum === "undefined") {
tickTimer._accum = 0;
tickTimer._lastScoreTime = 0;
}
tickTimer._accum += timerDecrement;
if (tickTimer._accum - tickTimer._lastScoreTime >= 1000) {
LK.setScore(LK.getScore() + 1);
scoreText.setText(LK.getScore());
tickTimer._lastScoreTime += 1000;
}
updateTimerBar();
if (timeLeft <= 0) {
canCut = false;
LK.getSound('fail').play();
LK.effects.flashScreen(0xff0000, 600);
LK.setTimeout(function () {
LK.showGameOver();
}, 600);
}
}
function updateTimerBar() {
// Remove bar visual, show countdown number instead
timerBar.visible = false;
// Add or update a countdown number Text2 object
if (typeof updateTimerBar.timerNumber === "undefined") {
updateTimerBar.timerNumber = new Text2('', {
size: 100,
fill: '#fc1100'
});
updateTimerBar.timerNumber.anchor.set(0.5, 0.5);
updateTimerBar.timerNumber.x = 2048 / 2;
updateTimerBar.timerNumber.y = 180;
game.addChild(updateTimerBar.timerNumber);
}
var secondsLeft = Math.ceil(Math.max(0, timeLeft) / 1000);
updateTimerBar.timerNumber.setText(secondsLeft);
// Always set timer number text color to red
updateTimerBar.timerNumber.setStyle({
fill: '#fc1100'
});
}
function triggerMalfunction() {
if (!canCut) {
return;
}
malfunctionActive = true;
screenText.visible = false;
malOverlay.visible = true;
// Hide screws for now, only show after click
for (var i = 0; i < screws.length; i++) {
screws[i].destroy();
}
screws = [];
// Randomly choose malfunction type: 50% screw, 50% number pad override
var useNumberPad = Math.random() < 0.5;
if (useNumberPad) {
// --- Number Pad Override puzzle ---
if (typeof game._numberPadOverride === "undefined" || !game._numberPadOverride) {
game._numberPadOverride = new NumberPadOverride();
game.addChild(game._numberPadOverride);
}
var code = [];
for (var i = 0; i < 4; i++) code.push(Math.floor(Math.random() * 10));
var timeLimit = 5000 + Math.floor(Math.random() * 2000); // 5-7s
game._numberPadOverride.start(code, timeLimit, function (success) {
malfunctionActive = false;
malOverlay.visible = false;
screenText.visible = true;
if (!success) {
// Game over
LK.setTimeout(function () {
LK.showGameOver();
}, 600);
}
});
LK.getSound('beep').play();
return;
}
// --- Screw minigame fallback ---
// Add a one-time click handler to the screen to show the screw minigame
screen.down = function (x, y, obj) {
// Remove this handler after first click
screen.down = undefined;
// Create a new box (screwBox) that will contain the screws, centered on the bomb/panel
if (typeof screwBox !== "undefined" && screwBox && screwBox.parent) {
screwBox.parent.removeChild(screwBox);
}
screwBox = new Container();
// Add a background for the screwBox (use panel_border for visual consistency)
var screwBoxBg = screwBox.attachAsset('CommBack', {
anchorX: 0.5,
anchorY: 0.5,
width: 1500,
// Match panel_bg width
height: 1000,
// Half of panel_bg height (2000px)
x: 0,
y: 0
});
// Center the screwBox on the panel
screwBox.x = 0;
screwBox.y = 0;
panel.addChild(screwBox);
// Show screws at random positions inside the screwBox
var screwCount = 3 + Math.floor(Math.random() * 2); // 3 or 4
screws = [];
for (var i = 0; i < screwCount; i++) {
var s = new Screw();
// Place randomly within the screwBox area
s.x = -220 + Math.random() * 440;
s.y = -120 + Math.random() * 240;
s.onFix = function (screw) {
handleScrewFix(screw);
// If all screws are fixed, remove the screwBox and return to bomb screen
var allFixed = true;
for (var j = 0; j < screws.length; j++) {
if (!screws[j].fixed) {
allFixed = false;
break;
}
}
if (allFixed) {
if (screwBox && screwBox.parent) {
screwBox.parent.removeChild(screwBox);
}
screwBox = null;
}
};
screwBox.addChild(s);
screws.push(s);
}
LK.getSound('beep').play();
};
}
function handleScrewFix(screw) {
// Don't allow fixing screws if the minigame hasn't started (blank screen)
if (!screws.length) {
return;
}
LK.getSound('fix').play();
// Check if all screws fixed
var allFixed = true;
for (var i = 0; i < screws.length; i++) {
if (!screws[i].fixed) {
allFixed = false;
break;
}
}
if (allFixed) {
malfunctionActive = false;
malOverlay.visible = false;
screenText.visible = true;
// Remove screws from screen
for (var i = 0; i < screws.length; i++) {
screws[i].destroy();
}
screws = [];
// Remove any leftover click handler
screen.down = undefined;
}
}
// --- Game event handlers ---
// Drag prevention: no drag in this game
game.move = function (x, y, obj) {};
// --- Game update loop ---
game.update = function () {
// Win condition: e.g. 20 points
if (LK.getScore() >= 99999999999) {
LK.showYouWin();
}
};
// --- Start game ---
LK.setScore(0);
scoreText.setText('0');
startRound();
It is like the back of a bomb, wires on the side. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
It's a screen, very chip like, light blue screen. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
“Top-down view of a steel box with a smooth metallic surface, subtle reflections, and sharp clean edges. The box should appear sturdy and industrial, with a slightly brushed texture on the steel. Lighting highlights the metal’s cool gray color and gives depth to the edges. Minimal shadows inside the box, set against a plain light background.”. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
it's a black wire. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
it's a blue wire. Don't cut it open, just blue nothing else. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
it's a green wire. Don't cut it open, just blue nothing else. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
it's a red wire. Don't cut it open, just blue nothing else. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
it's a yellow wire. Don't cut it open, just blue nothing else. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
paint it white
It's like back of a chip display. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Make it light greyish black
It is a black screen, like a glass pane. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Make it steel
That's a button, imagine a keyboard button. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
make it as a perfect rectangle, screws on all the corners. no background, transparent background