/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { savedLoops: [] }); /**** * Classes ****/ var BeatButton = Container.expand(function (id, label) { var self = Container.call(this); self.id = id; self.isActive = false; var buttonBg = self.attachAsset('beatButton', { anchorX: 0.5, anchorY: 0.5 }); var buttonLabel = new Text2(label, { size: 40, fill: 0xFFFFFF }); buttonLabel.anchor.set(0.5, 0.5); self.addChild(buttonLabel); self.activate = function () { self.isActive = true; self.removeChild(buttonBg); buttonBg = self.attachAsset('beatButtonActive', { anchorX: 0.5, anchorY: 0.5 }); self.addChildAt(buttonBg, 0); }; self.deactivate = function () { self.isActive = false; self.removeChild(buttonBg); buttonBg = self.attachAsset('beatButton', { anchorX: 0.5, anchorY: 0.5 }); self.addChildAt(buttonBg, 0); }; self.down = function (x, y, obj) { if (!self.isActive) { // Deactivate all other beat buttons for (var i = 0; i < beatButtons.length; i++) { beatButtons[i].deactivate(); } self.activate(); selectedBeat = self.id; updateLoop(); } }; return self; }); var EffectButton = Container.expand(function (id, label) { var self = Container.call(this); self.id = id; self.isActive = false; var buttonBg = self.attachAsset('effectButton', { anchorX: 0.5, anchorY: 0.5 }); var buttonLabel = new Text2(label, { size: 35, fill: 0xFFFFFF }); buttonLabel.anchor.set(0.5, 0.5); self.addChild(buttonLabel); self.activate = function () { self.isActive = true; self.removeChild(buttonBg); buttonBg = self.attachAsset('effectButtonActive', { anchorX: 0.5, anchorY: 0.5 }); self.addChildAt(buttonBg, 0); }; self.deactivate = function () { self.isActive = false; self.removeChild(buttonBg); buttonBg = self.attachAsset('effectButton', { anchorX: 0.5, anchorY: 0.5 }); self.addChildAt(buttonBg, 0); }; self.down = function (x, y, obj) { if (self.isActive) { self.deactivate(); selectedEffect = null; } else { // Deactivate all other effect buttons for (var i = 0; i < effectButtons.length; i++) { effectButtons[i].deactivate(); } self.activate(); selectedEffect = self.id; } updateLoop(); }; return self; }); var MelodyButton = Container.expand(function (id, label) { var self = Container.call(this); self.id = id; self.isActive = false; var buttonBg = self.attachAsset('melodyButton', { anchorX: 0.5, anchorY: 0.5 }); var buttonLabel = new Text2(label, { size: 30, fill: 0xFFFFFF }); buttonLabel.anchor.set(0.5, 0.5); self.addChild(buttonLabel); self.activate = function () { self.isActive = true; self.removeChild(buttonBg); buttonBg = self.attachAsset('melodyButtonActive', { anchorX: 0.5, anchorY: 0.5 }); self.addChildAt(buttonBg, 0); }; self.deactivate = function () { self.isActive = false; self.removeChild(buttonBg); buttonBg = self.attachAsset('melodyButton', { anchorX: 0.5, anchorY: 0.5 }); self.addChildAt(buttonBg, 0); }; self.down = function (x, y, obj) { if (self.isActive) { self.deactivate(); selectedMelodies = null; } else { // Deactivate all other melody buttons for (var i = 0; i < melodyButtons.length; i++) { melodyButtons[i].deactivate(); } self.activate(); selectedMelodies = self.id; } updateLoop(); }; return self; }); var PlayStopButton = Container.expand(function () { var self = Container.call(this); self.isPlaying = false; var buttonBg = self.attachAsset('playButton', { anchorX: 0.5, anchorY: 0.5 }); var playIcon = new Text2('▶', { size: 80, fill: 0xFFFFFF }); playIcon.anchor.set(0.5, 0.5); self.addChild(playIcon); self.setPlaying = function (playing) { self.isPlaying = playing; self.removeChild(buttonBg); if (playing) { buttonBg = self.attachAsset('stopButton', { anchorX: 0.5, anchorY: 0.5 }); playIcon.setText('⏹'); } else { buttonBg = self.attachAsset('playButton', { anchorX: 0.5, anchorY: 0.5 }); playIcon.setText('▶'); } self.addChildAt(buttonBg, 0); }; self.down = function (x, y, obj) { if (self.isPlaying) { stopLoop(); } else { startLoop(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2c3e50 }); /**** * Game Code ****/ var selectedBeat = null; var selectedEffect = null; var selectedMelodies = null; var isLoopPlaying = false; var loopTimer = null; var savedLoops = []; if (storage.savedLoops && Array.isArray(storage.savedLoops)) { savedLoops = storage.savedLoops; } var beatButtons = []; var effectButtons = []; var melodyButtons = []; var playStopButton; var saveButton; // Create title var titleText = new Text2('Loop Maker', { size: 80, fill: 0xECF0F1 }); titleText.anchor.set(0.5, 0); titleText.x = 1024; titleText.y = 150; game.addChild(titleText); // Create beat section var beatSectionTitle = new Text2('Beats', { size: 50, fill: 0xECF0F1 }); beatSectionTitle.anchor.set(0, 0.5); beatSectionTitle.x = 1400; beatSectionTitle.y = 500; game.addChild(beatSectionTitle); var beatLabels = ['Kick Drum', 'Snare Beat', 'Hi-Hat', 'Bass Drop', 'Electronic']; for (var i = 0; i < 5; i++) { var beatBtn = new BeatButton(i + 1, beatLabels[i]); beatBtn.x = 200 + i % 3 * 400 + (i >= 3 ? 200 : 0); beatBtn.y = 430 + Math.floor(i / 3) * 140; beatButtons.push(beatBtn); game.addChild(beatBtn); } // Create effect section var effectSectionTitle = new Text2('Effects', { size: 50, fill: 0xECF0F1 }); effectSectionTitle.anchor.set(0, 0.5); effectSectionTitle.x = 1400; effectSectionTitle.y = 830; game.addChild(effectSectionTitle); var effectLabels = ['Reverb', 'Distortion', 'Filter']; for (var i = 0; i < 3; i++) { var effectBtn = new EffectButton(i + 1, effectLabels[i]); effectBtn.x = 400 + i * 350; effectBtn.y = 830; effectButtons.push(effectBtn); game.addChild(effectBtn); } // Create melody section var melodySectionTitle = new Text2('Melodies', { size: 50, fill: 0xECF0F1 }); melodySectionTitle.anchor.set(0, 0.5); melodySectionTitle.x = 1700; melodySectionTitle.y = 1050; game.addChild(melodySectionTitle); var melodyLabels = ['Piano', 'Synth', 'Guitar', 'Electric Guitar']; for (var i = 0; i < 4; i++) { var melodyBtn = new MelodyButton(i + 1, melodyLabels[i]); melodyBtn.x = 300 + i * 350; melodyBtn.y = 1050; melodyButtons.push(melodyBtn); game.addChild(melodyBtn); } // Create play/stop button playStopButton = new PlayStopButton(); playStopButton.x = 1024; playStopButton.y = 1300; game.addChild(playStopButton); // Create save button saveButton = game.addChild(LK.getAsset('saveButton', { anchorX: 0.5, anchorY: 0.5 })); saveButton.x = 1024; saveButton.y = 1550; var saveButtonText = new Text2('Save Loop', { size: 35, fill: 0xFFFFFF }); saveButtonText.anchor.set(0.5, 0.5); saveButton.addChild(saveButtonText); saveButton.down = function (x, y, obj) { if (selectedBeat !== null) { var loopData = { beat: selectedBeat, effect: selectedEffect, melodies: selectedMelodies }; savedLoops.push(loopData); storage.savedLoops = savedLoops; // Visual feedback tween(saveButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(saveButton, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); LK.effects.flashObject(saveButton, 0x2ecc71, 500); } }; // Create saved loops display var savedLoopsText = new Text2('Saved: ' + savedLoops.length, { size: 40, fill: 0xBDC3C7 }); savedLoopsText.anchor.set(0.5, 0); savedLoopsText.x = 1024; savedLoopsText.y = 1650; game.addChild(savedLoopsText); function updateLoop() { if (isLoopPlaying) { stopLoop(); startLoop(); } savedLoopsText.setText('Saved: ' + savedLoops.length); } function startLoop() { if (selectedBeat === null) return; isLoopPlaying = true; playStopButton.setPlaying(true); playLoop(); loopTimer = LK.setInterval(playLoop, 2000); // 2 second loop } function stopLoop() { isLoopPlaying = false; playStopButton.setPlaying(false); if (loopTimer) { LK.clearInterval(loopTimer); loopTimer = null; } } function playLoop() { if (selectedBeat !== null) { var beatSound = LK.getSound('beat' + selectedBeat); if (beatSound) { beatSound.play(); } else { console.log('Beat sound not found: beat' + selectedBeat); } } LK.setTimeout(function () { if (selectedEffect !== null) { var effectSound = LK.getSound('effect' + selectedEffect); if (effectSound) { effectSound.play(); } else { console.log('Effect sound not found: effect' + selectedEffect); } } }, 200); LK.setTimeout(function () { if (selectedMelodies !== null) { var melodySound = LK.getSound('melody' + selectedMelodies); if (melodySound) { melodySound.play(); } else { console.log('Melody sound not found: melody' + selectedMelodies); } } }, 400); } // Auto-select first beat for better UX beatButtons[0].down(0, 0, {}); game.update = function () { // Game loop runs here };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
savedLoops: []
});
/****
* Classes
****/
var BeatButton = Container.expand(function (id, label) {
var self = Container.call(this);
self.id = id;
self.isActive = false;
var buttonBg = self.attachAsset('beatButton', {
anchorX: 0.5,
anchorY: 0.5
});
var buttonLabel = new Text2(label, {
size: 40,
fill: 0xFFFFFF
});
buttonLabel.anchor.set(0.5, 0.5);
self.addChild(buttonLabel);
self.activate = function () {
self.isActive = true;
self.removeChild(buttonBg);
buttonBg = self.attachAsset('beatButtonActive', {
anchorX: 0.5,
anchorY: 0.5
});
self.addChildAt(buttonBg, 0);
};
self.deactivate = function () {
self.isActive = false;
self.removeChild(buttonBg);
buttonBg = self.attachAsset('beatButton', {
anchorX: 0.5,
anchorY: 0.5
});
self.addChildAt(buttonBg, 0);
};
self.down = function (x, y, obj) {
if (!self.isActive) {
// Deactivate all other beat buttons
for (var i = 0; i < beatButtons.length; i++) {
beatButtons[i].deactivate();
}
self.activate();
selectedBeat = self.id;
updateLoop();
}
};
return self;
});
var EffectButton = Container.expand(function (id, label) {
var self = Container.call(this);
self.id = id;
self.isActive = false;
var buttonBg = self.attachAsset('effectButton', {
anchorX: 0.5,
anchorY: 0.5
});
var buttonLabel = new Text2(label, {
size: 35,
fill: 0xFFFFFF
});
buttonLabel.anchor.set(0.5, 0.5);
self.addChild(buttonLabel);
self.activate = function () {
self.isActive = true;
self.removeChild(buttonBg);
buttonBg = self.attachAsset('effectButtonActive', {
anchorX: 0.5,
anchorY: 0.5
});
self.addChildAt(buttonBg, 0);
};
self.deactivate = function () {
self.isActive = false;
self.removeChild(buttonBg);
buttonBg = self.attachAsset('effectButton', {
anchorX: 0.5,
anchorY: 0.5
});
self.addChildAt(buttonBg, 0);
};
self.down = function (x, y, obj) {
if (self.isActive) {
self.deactivate();
selectedEffect = null;
} else {
// Deactivate all other effect buttons
for (var i = 0; i < effectButtons.length; i++) {
effectButtons[i].deactivate();
}
self.activate();
selectedEffect = self.id;
}
updateLoop();
};
return self;
});
var MelodyButton = Container.expand(function (id, label) {
var self = Container.call(this);
self.id = id;
self.isActive = false;
var buttonBg = self.attachAsset('melodyButton', {
anchorX: 0.5,
anchorY: 0.5
});
var buttonLabel = new Text2(label, {
size: 30,
fill: 0xFFFFFF
});
buttonLabel.anchor.set(0.5, 0.5);
self.addChild(buttonLabel);
self.activate = function () {
self.isActive = true;
self.removeChild(buttonBg);
buttonBg = self.attachAsset('melodyButtonActive', {
anchorX: 0.5,
anchorY: 0.5
});
self.addChildAt(buttonBg, 0);
};
self.deactivate = function () {
self.isActive = false;
self.removeChild(buttonBg);
buttonBg = self.attachAsset('melodyButton', {
anchorX: 0.5,
anchorY: 0.5
});
self.addChildAt(buttonBg, 0);
};
self.down = function (x, y, obj) {
if (self.isActive) {
self.deactivate();
selectedMelodies = null;
} else {
// Deactivate all other melody buttons
for (var i = 0; i < melodyButtons.length; i++) {
melodyButtons[i].deactivate();
}
self.activate();
selectedMelodies = self.id;
}
updateLoop();
};
return self;
});
var PlayStopButton = Container.expand(function () {
var self = Container.call(this);
self.isPlaying = false;
var buttonBg = self.attachAsset('playButton', {
anchorX: 0.5,
anchorY: 0.5
});
var playIcon = new Text2('▶', {
size: 80,
fill: 0xFFFFFF
});
playIcon.anchor.set(0.5, 0.5);
self.addChild(playIcon);
self.setPlaying = function (playing) {
self.isPlaying = playing;
self.removeChild(buttonBg);
if (playing) {
buttonBg = self.attachAsset('stopButton', {
anchorX: 0.5,
anchorY: 0.5
});
playIcon.setText('⏹');
} else {
buttonBg = self.attachAsset('playButton', {
anchorX: 0.5,
anchorY: 0.5
});
playIcon.setText('▶');
}
self.addChildAt(buttonBg, 0);
};
self.down = function (x, y, obj) {
if (self.isPlaying) {
stopLoop();
} else {
startLoop();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c3e50
});
/****
* Game Code
****/
var selectedBeat = null;
var selectedEffect = null;
var selectedMelodies = null;
var isLoopPlaying = false;
var loopTimer = null;
var savedLoops = [];
if (storage.savedLoops && Array.isArray(storage.savedLoops)) {
savedLoops = storage.savedLoops;
}
var beatButtons = [];
var effectButtons = [];
var melodyButtons = [];
var playStopButton;
var saveButton;
// Create title
var titleText = new Text2('Loop Maker', {
size: 80,
fill: 0xECF0F1
});
titleText.anchor.set(0.5, 0);
titleText.x = 1024;
titleText.y = 150;
game.addChild(titleText);
// Create beat section
var beatSectionTitle = new Text2('Beats', {
size: 50,
fill: 0xECF0F1
});
beatSectionTitle.anchor.set(0, 0.5);
beatSectionTitle.x = 1400;
beatSectionTitle.y = 500;
game.addChild(beatSectionTitle);
var beatLabels = ['Kick Drum', 'Snare Beat', 'Hi-Hat', 'Bass Drop', 'Electronic'];
for (var i = 0; i < 5; i++) {
var beatBtn = new BeatButton(i + 1, beatLabels[i]);
beatBtn.x = 200 + i % 3 * 400 + (i >= 3 ? 200 : 0);
beatBtn.y = 430 + Math.floor(i / 3) * 140;
beatButtons.push(beatBtn);
game.addChild(beatBtn);
}
// Create effect section
var effectSectionTitle = new Text2('Effects', {
size: 50,
fill: 0xECF0F1
});
effectSectionTitle.anchor.set(0, 0.5);
effectSectionTitle.x = 1400;
effectSectionTitle.y = 830;
game.addChild(effectSectionTitle);
var effectLabels = ['Reverb', 'Distortion', 'Filter'];
for (var i = 0; i < 3; i++) {
var effectBtn = new EffectButton(i + 1, effectLabels[i]);
effectBtn.x = 400 + i * 350;
effectBtn.y = 830;
effectButtons.push(effectBtn);
game.addChild(effectBtn);
}
// Create melody section
var melodySectionTitle = new Text2('Melodies', {
size: 50,
fill: 0xECF0F1
});
melodySectionTitle.anchor.set(0, 0.5);
melodySectionTitle.x = 1700;
melodySectionTitle.y = 1050;
game.addChild(melodySectionTitle);
var melodyLabels = ['Piano', 'Synth', 'Guitar', 'Electric Guitar'];
for (var i = 0; i < 4; i++) {
var melodyBtn = new MelodyButton(i + 1, melodyLabels[i]);
melodyBtn.x = 300 + i * 350;
melodyBtn.y = 1050;
melodyButtons.push(melodyBtn);
game.addChild(melodyBtn);
}
// Create play/stop button
playStopButton = new PlayStopButton();
playStopButton.x = 1024;
playStopButton.y = 1300;
game.addChild(playStopButton);
// Create save button
saveButton = game.addChild(LK.getAsset('saveButton', {
anchorX: 0.5,
anchorY: 0.5
}));
saveButton.x = 1024;
saveButton.y = 1550;
var saveButtonText = new Text2('Save Loop', {
size: 35,
fill: 0xFFFFFF
});
saveButtonText.anchor.set(0.5, 0.5);
saveButton.addChild(saveButtonText);
saveButton.down = function (x, y, obj) {
if (selectedBeat !== null) {
var loopData = {
beat: selectedBeat,
effect: selectedEffect,
melodies: selectedMelodies
};
savedLoops.push(loopData);
storage.savedLoops = savedLoops;
// Visual feedback
tween(saveButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(saveButton, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
LK.effects.flashObject(saveButton, 0x2ecc71, 500);
}
};
// Create saved loops display
var savedLoopsText = new Text2('Saved: ' + savedLoops.length, {
size: 40,
fill: 0xBDC3C7
});
savedLoopsText.anchor.set(0.5, 0);
savedLoopsText.x = 1024;
savedLoopsText.y = 1650;
game.addChild(savedLoopsText);
function updateLoop() {
if (isLoopPlaying) {
stopLoop();
startLoop();
}
savedLoopsText.setText('Saved: ' + savedLoops.length);
}
function startLoop() {
if (selectedBeat === null) return;
isLoopPlaying = true;
playStopButton.setPlaying(true);
playLoop();
loopTimer = LK.setInterval(playLoop, 2000); // 2 second loop
}
function stopLoop() {
isLoopPlaying = false;
playStopButton.setPlaying(false);
if (loopTimer) {
LK.clearInterval(loopTimer);
loopTimer = null;
}
}
function playLoop() {
if (selectedBeat !== null) {
var beatSound = LK.getSound('beat' + selectedBeat);
if (beatSound) {
beatSound.play();
} else {
console.log('Beat sound not found: beat' + selectedBeat);
}
}
LK.setTimeout(function () {
if (selectedEffect !== null) {
var effectSound = LK.getSound('effect' + selectedEffect);
if (effectSound) {
effectSound.play();
} else {
console.log('Effect sound not found: effect' + selectedEffect);
}
}
}, 200);
LK.setTimeout(function () {
if (selectedMelodies !== null) {
var melodySound = LK.getSound('melody' + selectedMelodies);
if (melodySound) {
melodySound.play();
} else {
console.log('Melody sound not found: melody' + selectedMelodies);
}
}
}, 400);
}
// Auto-select first beat for better UX
beatButtons[0].down(0, 0, {});
game.update = function () {
// Game loop runs here
};