/****
* 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
};