/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Pad class for colored buttons
var Pad = Container.expand(function () {
var self = Container.call(this);
// Properties: colorName, soundId, assetId, index
self.colorName = '';
self.soundId = '';
self.assetId = '';
self.index = 0;
// Attach asset
var padAsset = null;
self.initPad = function (colorName, soundId, assetId, index) {
self.colorName = colorName;
self.soundId = soundId;
self.assetId = assetId;
self.index = index;
padAsset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2
});
// For touch feedback, store reference
self.padAsset = padAsset;
};
// Flash the pad (light up effect)
self.flash = function (duration) {
// Animate scale up and alpha up, then back
tween(self.padAsset, {
scaleX: 3,
scaleY: 3,
alpha: 1
}, {
duration: duration / 2,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self.padAsset, {
scaleX: 2,
scaleY: 2,
alpha: 0.85
}, {
duration: duration / 2,
easing: tween.easeIn
});
}
});
};
// Play the pad's sound
self.playSound = function () {
LK.getSound(self.soundId).play();
};
// Enable/disable pad for input
self.setEnabled = function (enabled) {
self.enabled = enabled;
self.padAsset.alpha = enabled ? 0.85 : 0.5;
};
// Touch/click event
self.down = function (x, y, obj) {
if (!self.enabled) {
return;
}
// Visual feedback
self.flash(180);
self.playSound();
// Notify game
if (typeof self.onPadPressed === 'function') {
self.onPadPressed(self.index);
}
};
// Set default alpha
self.padAsset = padAsset;
if (self.padAsset) {
self.padAsset.alpha = 0.85;
}
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181818
});
/****
* Game Code
****/
// Pad definitions
// Four colored pads (Red, Blue, Green, Yellow)
// Sounds for each pad
// Simple background music (optional, can be replaced with actual music asset)
var bg = LK.getAsset('retroArcadeGridBg', {});
game.addChild(bg);
var padDefs = [{
colorName: 'red',
soundId: 'sndRed',
assetId: 'arcadeBtnRed64' // pixel art red arcade button, glowing, 64x64
}, {
colorName: 'blue',
soundId: 'sndBlue',
assetId: 'arcadeBtnBlue64' // pixel art blue arcade button, glowing, 64x64
}, {
colorName: 'green',
soundId: 'sndGreen',
assetId: 'arcadeBtnGreen64' // pixel art green arcade button, glowing, 64x64
}, {
colorName: 'yellow',
soundId: 'sndYellow',
assetId: 'arcadeBtnYellow64' // pixel art yellow arcade button, glowing, 64x64
}];
// Pad positions (2x2 grid, centered)
var padPositions = [{
x: 2048 / 2 - 340,
y: 2732 / 2 - 340
},
// Top-left (Red)
{
x: 2048 / 2 + 340,
y: 2732 / 2 - 340
},
// Top-right (Blue)
{
x: 2048 / 2 - 340,
y: 2732 / 2 + 340
},
// Bottom-left (Green)
{
x: 2048 / 2 + 340,
y: 2732 / 2 + 340
} // Bottom-right (Yellow)
];
// Game state variables
var pads = [];
var sequence = [];
var playerStep = 0;
var isPlayerTurn = false;
var isAnimating = false;
var score = 0;
var highScore = 0;
var sequenceTimer = null;
var showSequenceIndex = 0;
// Pattern and music speed control
var patternStepDuration = 480; // ms, initial step duration
var musicTempo = 1.0; // initial music rate
// Score text
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// "Get Ready" text
var infoTxt = new Text2('', {
size: 90,
fill: 0xFFFBE0
});
infoTxt.anchor.set(0.5, 0.5);
infoTxt.visible = false;
LK.gui.center.addChild(infoTxt);
// Create pads and add to game
for (var i = 0; i < 4; i++) {
var pad = new Pad();
pad.initPad(padDefs[i].colorName, padDefs[i].soundId, padDefs[i].assetId, i);
pad.x = padPositions[i].x;
pad.y = padPositions[i].y;
pad.setEnabled(false);
// Pad press callback
pad.onPadPressed = function (padIndex) {
if (!isPlayerTurn || isAnimating) {
return;
}
handlePlayerInput(padIndex);
};
pads.push(pad);
game.addChild(pad);
}
// Start background music
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 1,
duration: 1200
}
});
// Start the game
startNewGame();
function startNewGame() {
sequence = [];
playerStep = 0;
score = 0;
isPlayerTurn = false;
isAnimating = false;
showSequenceIndex = 0;
scoreTxt.setText('0');
infoTxt.setText('Get Ready!');
infoTxt.visible = true;
setPadsEnabled(false);
patternStepDuration = 480;
musicTempo = 1.0;
LK.playMusic('bgmusic', {
rate: musicTempo
});
// Short delay before first round
LK.setTimeout(function () {
infoTxt.visible = false;
addToSequence();
showSequence();
}, 900);
}
function setPadsEnabled(enabled) {
for (var i = 0; i < pads.length; i++) {
pads[i].setEnabled(enabled);
}
}
// Add a random color to the sequence
function addToSequence() {
var next = Math.floor(Math.random() * 4);
sequence.push(next);
}
// Show the sequence to the player (one by one)
function showSequence() {
isAnimating = true;
isPlayerTurn = false;
setPadsEnabled(false);
showSequenceIndex = 0;
playSequenceStep();
}
function playSequenceStep() {
if (showSequenceIndex >= sequence.length) {
// Sequence done, player's turn
isAnimating = false;
isPlayerTurn = true;
setPadsEnabled(true);
playerStep = 0;
return;
}
var padIndex = sequence[showSequenceIndex];
var pad = pads[padIndex];
pad.flash(320);
pad.playSound();
showSequenceIndex++;
sequenceTimer = LK.setTimeout(playSequenceStep, patternStepDuration);
}
// Handle player input
function handlePlayerInput(padIndex) {
if (!isPlayerTurn || isAnimating) {
return;
}
// Check if correct
if (padIndex === sequence[playerStep]) {
playerStep++;
if (playerStep === sequence.length) {
// Completed sequence, next round
score++;
scoreTxt.setText(score + '');
isPlayerTurn = false;
setPadsEnabled(false);
// Speed up pattern and music every 2 levels
if (score % 2 === 0) {
// Calculate new pattern speed (minimum 180ms)
patternStepDuration = Math.max(180, 480 - Math.floor(score / 2) * 80);
// Calculate new music tempo (1.0 + 0.1 per 2 levels, max 2.0)
musicTempo = Math.min(2.0, 1.0 + score / 2 * 0.1);
LK.playMusic('bgmusic', {
rate: musicTempo
});
}
LK.setTimeout(function () {
addToSequence();
showSequence();
}, 700);
}
} else {
// Wrong input, game over
pads[padIndex].flash(400);
LK.effects.flashScreen(0xff0000, 800);
setPadsEnabled(false);
infoTxt.setText('Game Over');
infoTxt.visible = true;
LK.setTimeout(function () {
infoTxt.visible = false;
LK.showGameOver();
}, 1200);
}
}
// Optional: allow restart on game over by tapping anywhere
game.down = function (x, y, obj) {
// Only allow restart if not animating and not player's turn
if (!isPlayerTurn && !isAnimating && !infoTxt.visible) {
startNewGame();
}
};
// Clean up on destroy (not strictly needed, but good practice)
game.destroy = function () {
if (sequenceTimer) {
LK.clearTimeout(sequenceTimer);
}
LK.stopMusic();
};
// Main update loop (not much needed here)
game.update = function () {
// No per-frame logic needed for this game
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Pad class for colored buttons
var Pad = Container.expand(function () {
var self = Container.call(this);
// Properties: colorName, soundId, assetId, index
self.colorName = '';
self.soundId = '';
self.assetId = '';
self.index = 0;
// Attach asset
var padAsset = null;
self.initPad = function (colorName, soundId, assetId, index) {
self.colorName = colorName;
self.soundId = soundId;
self.assetId = assetId;
self.index = index;
padAsset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2
});
// For touch feedback, store reference
self.padAsset = padAsset;
};
// Flash the pad (light up effect)
self.flash = function (duration) {
// Animate scale up and alpha up, then back
tween(self.padAsset, {
scaleX: 3,
scaleY: 3,
alpha: 1
}, {
duration: duration / 2,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self.padAsset, {
scaleX: 2,
scaleY: 2,
alpha: 0.85
}, {
duration: duration / 2,
easing: tween.easeIn
});
}
});
};
// Play the pad's sound
self.playSound = function () {
LK.getSound(self.soundId).play();
};
// Enable/disable pad for input
self.setEnabled = function (enabled) {
self.enabled = enabled;
self.padAsset.alpha = enabled ? 0.85 : 0.5;
};
// Touch/click event
self.down = function (x, y, obj) {
if (!self.enabled) {
return;
}
// Visual feedback
self.flash(180);
self.playSound();
// Notify game
if (typeof self.onPadPressed === 'function') {
self.onPadPressed(self.index);
}
};
// Set default alpha
self.padAsset = padAsset;
if (self.padAsset) {
self.padAsset.alpha = 0.85;
}
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181818
});
/****
* Game Code
****/
// Pad definitions
// Four colored pads (Red, Blue, Green, Yellow)
// Sounds for each pad
// Simple background music (optional, can be replaced with actual music asset)
var bg = LK.getAsset('retroArcadeGridBg', {});
game.addChild(bg);
var padDefs = [{
colorName: 'red',
soundId: 'sndRed',
assetId: 'arcadeBtnRed64' // pixel art red arcade button, glowing, 64x64
}, {
colorName: 'blue',
soundId: 'sndBlue',
assetId: 'arcadeBtnBlue64' // pixel art blue arcade button, glowing, 64x64
}, {
colorName: 'green',
soundId: 'sndGreen',
assetId: 'arcadeBtnGreen64' // pixel art green arcade button, glowing, 64x64
}, {
colorName: 'yellow',
soundId: 'sndYellow',
assetId: 'arcadeBtnYellow64' // pixel art yellow arcade button, glowing, 64x64
}];
// Pad positions (2x2 grid, centered)
var padPositions = [{
x: 2048 / 2 - 340,
y: 2732 / 2 - 340
},
// Top-left (Red)
{
x: 2048 / 2 + 340,
y: 2732 / 2 - 340
},
// Top-right (Blue)
{
x: 2048 / 2 - 340,
y: 2732 / 2 + 340
},
// Bottom-left (Green)
{
x: 2048 / 2 + 340,
y: 2732 / 2 + 340
} // Bottom-right (Yellow)
];
// Game state variables
var pads = [];
var sequence = [];
var playerStep = 0;
var isPlayerTurn = false;
var isAnimating = false;
var score = 0;
var highScore = 0;
var sequenceTimer = null;
var showSequenceIndex = 0;
// Pattern and music speed control
var patternStepDuration = 480; // ms, initial step duration
var musicTempo = 1.0; // initial music rate
// Score text
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// "Get Ready" text
var infoTxt = new Text2('', {
size: 90,
fill: 0xFFFBE0
});
infoTxt.anchor.set(0.5, 0.5);
infoTxt.visible = false;
LK.gui.center.addChild(infoTxt);
// Create pads and add to game
for (var i = 0; i < 4; i++) {
var pad = new Pad();
pad.initPad(padDefs[i].colorName, padDefs[i].soundId, padDefs[i].assetId, i);
pad.x = padPositions[i].x;
pad.y = padPositions[i].y;
pad.setEnabled(false);
// Pad press callback
pad.onPadPressed = function (padIndex) {
if (!isPlayerTurn || isAnimating) {
return;
}
handlePlayerInput(padIndex);
};
pads.push(pad);
game.addChild(pad);
}
// Start background music
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 1,
duration: 1200
}
});
// Start the game
startNewGame();
function startNewGame() {
sequence = [];
playerStep = 0;
score = 0;
isPlayerTurn = false;
isAnimating = false;
showSequenceIndex = 0;
scoreTxt.setText('0');
infoTxt.setText('Get Ready!');
infoTxt.visible = true;
setPadsEnabled(false);
patternStepDuration = 480;
musicTempo = 1.0;
LK.playMusic('bgmusic', {
rate: musicTempo
});
// Short delay before first round
LK.setTimeout(function () {
infoTxt.visible = false;
addToSequence();
showSequence();
}, 900);
}
function setPadsEnabled(enabled) {
for (var i = 0; i < pads.length; i++) {
pads[i].setEnabled(enabled);
}
}
// Add a random color to the sequence
function addToSequence() {
var next = Math.floor(Math.random() * 4);
sequence.push(next);
}
// Show the sequence to the player (one by one)
function showSequence() {
isAnimating = true;
isPlayerTurn = false;
setPadsEnabled(false);
showSequenceIndex = 0;
playSequenceStep();
}
function playSequenceStep() {
if (showSequenceIndex >= sequence.length) {
// Sequence done, player's turn
isAnimating = false;
isPlayerTurn = true;
setPadsEnabled(true);
playerStep = 0;
return;
}
var padIndex = sequence[showSequenceIndex];
var pad = pads[padIndex];
pad.flash(320);
pad.playSound();
showSequenceIndex++;
sequenceTimer = LK.setTimeout(playSequenceStep, patternStepDuration);
}
// Handle player input
function handlePlayerInput(padIndex) {
if (!isPlayerTurn || isAnimating) {
return;
}
// Check if correct
if (padIndex === sequence[playerStep]) {
playerStep++;
if (playerStep === sequence.length) {
// Completed sequence, next round
score++;
scoreTxt.setText(score + '');
isPlayerTurn = false;
setPadsEnabled(false);
// Speed up pattern and music every 2 levels
if (score % 2 === 0) {
// Calculate new pattern speed (minimum 180ms)
patternStepDuration = Math.max(180, 480 - Math.floor(score / 2) * 80);
// Calculate new music tempo (1.0 + 0.1 per 2 levels, max 2.0)
musicTempo = Math.min(2.0, 1.0 + score / 2 * 0.1);
LK.playMusic('bgmusic', {
rate: musicTempo
});
}
LK.setTimeout(function () {
addToSequence();
showSequence();
}, 700);
}
} else {
// Wrong input, game over
pads[padIndex].flash(400);
LK.effects.flashScreen(0xff0000, 800);
setPadsEnabled(false);
infoTxt.setText('Game Over');
infoTxt.visible = true;
LK.setTimeout(function () {
infoTxt.visible = false;
LK.showGameOver();
}, 1200);
}
}
// Optional: allow restart on game over by tapping anywhere
game.down = function (x, y, obj) {
// Only allow restart if not animating and not player's turn
if (!isPlayerTurn && !isAnimating && !infoTxt.visible) {
startNewGame();
}
};
// Clean up on destroy (not strictly needed, but good practice)
game.destroy = function () {
if (sequenceTimer) {
LK.clearTimeout(sequenceTimer);
}
LK.stopMusic();
};
// Main update loop (not much needed here)
game.update = function () {
// No per-frame logic needed for this game
};