/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var BeatMarker = Container.expand(function () { var self = Container.call(this); var markerGraphics = self.attachAsset('beatMarker', { anchorX: 0.5, anchorY: 0.5 }); self.targetX = 0; self.targetY = 0; self.speed = 3; self.isActive = true; self.hasBeenHit = false; self.update = function () { if (!self.isActive) return; // Move toward target var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } }; self.down = function (x, y, obj) { if (!self.isActive || self.hasBeenHit) return; var distance = Math.sqrt(Math.pow(self.x - self.targetX, 2) + Math.pow(self.y - self.targetY, 2)); if (distance < 200) { self.hit(); } }; self.hit = function () { if (self.hasBeenHit) return; self.hasBeenHit = true; self.isActive = false; // Perfect hit effect var hitEffect = game.addChild(LK.getAsset('perfectHit', { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y, alpha: 1 })); tween(hitEffect, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 300, onFinish: function onFinish() { hitEffect.destroy(); } }); // Score and combo combo++; var points = 100 * combo; LK.setScore(LK.getScore() + points); // Update UI scoreTxt.setText(LK.getScore()); comboTxt.setText('Combo: ' + combo); // Caveman dance animation cavemanDance(); LK.getSound('hit').play(); self.destroy(); }; return self; }); var Caveman = Container.expand(function () { var self = Container.call(this); var cavemanGraphics = self.attachAsset('caveman', { anchorX: 0.5, anchorY: 1.0 }); self.isIdle = true; self.danceTimer = 0; self.update = function () { if (self.isIdle) { self.danceTimer++; if (self.danceTimer % 30 === 0) { self.idleDance(); } } }; self.idleDance = function () { tween(cavemanGraphics, { scaleX: 1.1, rotation: 0.1 }, { duration: 200, easing: tween.easeInOut, onFinish: function onFinish() { tween(cavemanGraphics, { scaleX: 1.0, rotation: -0.1 }, { duration: 200, easing: tween.easeInOut, onFinish: function onFinish() { tween(cavemanGraphics, { rotation: 0 }, { duration: 100 }); } }); } }); }; self.performDance = function () { self.isIdle = false; tween(cavemanGraphics, { scaleY: 0.8, rotation: 0.3 }, { duration: 150, easing: tween.bounceOut, onFinish: function onFinish() { tween(cavemanGraphics, { scaleY: 1.2, rotation: -0.3 }, { duration: 150, easing: tween.bounceOut, onFinish: function onFinish() { tween(cavemanGraphics, { scaleY: 1.0, rotation: 0 }, { duration: 200, onFinish: function onFinish() { self.isIdle = true; } }); } }); } }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2C1810 }); /**** * Game Code ****/ var caveman; var targetArea; var beatMarkers = []; var combo = 0; var lives = 3; var markerSpawnTimer = 0; var gameSpeed = 1; var scoreTxt, comboTxt, livesTxt; // Create target area in center targetArea = game.addChild(LK.getAsset('targetArea', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0.7, scaleX: 3.0, scaleY: 3.0 })); // Create caveman caveman = game.addChild(new Caveman()); caveman.x = 2048 / 2; caveman.y = 2732 / 2 + 100; // UI Elements scoreTxt = new Text2('0', { size: 80, fill: 0xFFD700 }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); comboTxt = new Text2('Combo: 0', { size: 60, fill: 0xFF6B35 }); comboTxt.anchor.set(0, 0); comboTxt.x = 150; comboTxt.y = 100; LK.gui.topLeft.addChild(comboTxt); livesTxt = new Text2('Lives: 3', { size: 60, fill: 0xFF4444 }); livesTxt.anchor.set(1, 0); LK.gui.topRight.addChild(livesTxt); function spawnBeatMarker() { var marker = new BeatMarker(); // Random spawn position from edges var side = Math.floor(Math.random() * 4); switch (side) { case 0: // Top marker.x = Math.random() * 2048; marker.y = -100; break; case 1: // Right marker.x = 2148; marker.y = Math.random() * 2732; break; case 2: // Bottom marker.x = Math.random() * 2048; marker.y = 2832; break; case 3: // Left marker.x = -100; marker.y = Math.random() * 2732; break; } marker.targetX = targetArea.x; marker.targetY = targetArea.y; marker.speed = 2 + gameSpeed; beatMarkers.push(marker); game.addChild(marker); } function cavemanDance() { caveman.performDance(); } function checkMissedMarkers() { for (var i = beatMarkers.length - 1; i >= 0; i--) { var marker = beatMarkers[i]; if (!marker.isActive || marker.hasBeenHit) continue; var distance = Math.sqrt(Math.pow(marker.x - marker.targetX, 2) + Math.pow(marker.y - marker.targetY, 2)); // Check if marker passed the target without being hit if (distance < 10 && !marker.hasBeenHit) { // Miss! combo = 0; lives--; comboTxt.setText('Combo: 0'); livesTxt.setText('Lives: ' + lives); // Flash screen red LK.effects.flashScreen(0xFF0000, 300); LK.getSound('miss').play(); marker.destroy(); beatMarkers.splice(i, 1); if (lives <= 0) { LK.showGameOver(); return; } } // Remove markers that are too far past the target else if (distance > 200 && Math.sqrt(Math.pow(marker.x - marker.targetX, 2) + Math.pow(marker.y - marker.targetY, 2)) > Math.sqrt(Math.pow(marker.x - marker.targetX, 2) + Math.pow(marker.y - marker.targetY, 2))) { marker.destroy(); beatMarkers.splice(i, 1); } } } game.down = function (x, y, obj) { // Check if any marker was hit var hit = false; for (var i = 0; i < beatMarkers.length; i++) { var marker = beatMarkers[i]; if (marker.isActive && !marker.hasBeenHit) { var distance = Math.sqrt(Math.pow(marker.x - marker.targetX, 2) + Math.pow(marker.y - marker.targetY, 2)); if (distance < 200) { marker.hit(); hit = true; break; } } } if (!hit) { // Missed tap combo = Math.max(0, combo - 1); comboTxt.setText('Combo: ' + combo); } }; game.update = function () { markerSpawnTimer++; // Spawn markers based on beat (every 60 ticks = 1 second at 60fps) if (markerSpawnTimer >= Math.max(30, 90 - LK.ticks / 300)) { spawnBeatMarker(); markerSpawnTimer = 0; } // Gradually increase difficulty if (LK.ticks % 600 === 0) { gameSpeed += 0.1; } checkMissedMarkers(); // Clean up destroyed markers for (var i = beatMarkers.length - 1; i >= 0; i--) { if (beatMarkers[i].hasBeenHit) { beatMarkers.splice(i, 1); } } // Update UI scoreTxt.setText(LK.getScore()); }; // Start the music LK.playMusic('danceMusic');
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BeatMarker = Container.expand(function () {
var self = Container.call(this);
var markerGraphics = self.attachAsset('beatMarker', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetX = 0;
self.targetY = 0;
self.speed = 3;
self.isActive = true;
self.hasBeenHit = false;
self.update = function () {
if (!self.isActive) return;
// Move toward target
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
self.down = function (x, y, obj) {
if (!self.isActive || self.hasBeenHit) return;
var distance = Math.sqrt(Math.pow(self.x - self.targetX, 2) + Math.pow(self.y - self.targetY, 2));
if (distance < 200) {
self.hit();
}
};
self.hit = function () {
if (self.hasBeenHit) return;
self.hasBeenHit = true;
self.isActive = false;
// Perfect hit effect
var hitEffect = game.addChild(LK.getAsset('perfectHit', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y,
alpha: 1
}));
tween(hitEffect, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
onFinish: function onFinish() {
hitEffect.destroy();
}
});
// Score and combo
combo++;
var points = 100 * combo;
LK.setScore(LK.getScore() + points);
// Update UI
scoreTxt.setText(LK.getScore());
comboTxt.setText('Combo: ' + combo);
// Caveman dance animation
cavemanDance();
LK.getSound('hit').play();
self.destroy();
};
return self;
});
var Caveman = Container.expand(function () {
var self = Container.call(this);
var cavemanGraphics = self.attachAsset('caveman', {
anchorX: 0.5,
anchorY: 1.0
});
self.isIdle = true;
self.danceTimer = 0;
self.update = function () {
if (self.isIdle) {
self.danceTimer++;
if (self.danceTimer % 30 === 0) {
self.idleDance();
}
}
};
self.idleDance = function () {
tween(cavemanGraphics, {
scaleX: 1.1,
rotation: 0.1
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(cavemanGraphics, {
scaleX: 1.0,
rotation: -0.1
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(cavemanGraphics, {
rotation: 0
}, {
duration: 100
});
}
});
}
});
};
self.performDance = function () {
self.isIdle = false;
tween(cavemanGraphics, {
scaleY: 0.8,
rotation: 0.3
}, {
duration: 150,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(cavemanGraphics, {
scaleY: 1.2,
rotation: -0.3
}, {
duration: 150,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(cavemanGraphics, {
scaleY: 1.0,
rotation: 0
}, {
duration: 200,
onFinish: function onFinish() {
self.isIdle = true;
}
});
}
});
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2C1810
});
/****
* Game Code
****/
var caveman;
var targetArea;
var beatMarkers = [];
var combo = 0;
var lives = 3;
var markerSpawnTimer = 0;
var gameSpeed = 1;
var scoreTxt, comboTxt, livesTxt;
// Create target area in center
targetArea = game.addChild(LK.getAsset('targetArea', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0.7,
scaleX: 3.0,
scaleY: 3.0
}));
// Create caveman
caveman = game.addChild(new Caveman());
caveman.x = 2048 / 2;
caveman.y = 2732 / 2 + 100;
// UI Elements
scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFD700
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
comboTxt = new Text2('Combo: 0', {
size: 60,
fill: 0xFF6B35
});
comboTxt.anchor.set(0, 0);
comboTxt.x = 150;
comboTxt.y = 100;
LK.gui.topLeft.addChild(comboTxt);
livesTxt = new Text2('Lives: 3', {
size: 60,
fill: 0xFF4444
});
livesTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(livesTxt);
function spawnBeatMarker() {
var marker = new BeatMarker();
// Random spawn position from edges
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
marker.x = Math.random() * 2048;
marker.y = -100;
break;
case 1:
// Right
marker.x = 2148;
marker.y = Math.random() * 2732;
break;
case 2:
// Bottom
marker.x = Math.random() * 2048;
marker.y = 2832;
break;
case 3:
// Left
marker.x = -100;
marker.y = Math.random() * 2732;
break;
}
marker.targetX = targetArea.x;
marker.targetY = targetArea.y;
marker.speed = 2 + gameSpeed;
beatMarkers.push(marker);
game.addChild(marker);
}
function cavemanDance() {
caveman.performDance();
}
function checkMissedMarkers() {
for (var i = beatMarkers.length - 1; i >= 0; i--) {
var marker = beatMarkers[i];
if (!marker.isActive || marker.hasBeenHit) continue;
var distance = Math.sqrt(Math.pow(marker.x - marker.targetX, 2) + Math.pow(marker.y - marker.targetY, 2));
// Check if marker passed the target without being hit
if (distance < 10 && !marker.hasBeenHit) {
// Miss!
combo = 0;
lives--;
comboTxt.setText('Combo: 0');
livesTxt.setText('Lives: ' + lives);
// Flash screen red
LK.effects.flashScreen(0xFF0000, 300);
LK.getSound('miss').play();
marker.destroy();
beatMarkers.splice(i, 1);
if (lives <= 0) {
LK.showGameOver();
return;
}
}
// Remove markers that are too far past the target
else if (distance > 200 && Math.sqrt(Math.pow(marker.x - marker.targetX, 2) + Math.pow(marker.y - marker.targetY, 2)) > Math.sqrt(Math.pow(marker.x - marker.targetX, 2) + Math.pow(marker.y - marker.targetY, 2))) {
marker.destroy();
beatMarkers.splice(i, 1);
}
}
}
game.down = function (x, y, obj) {
// Check if any marker was hit
var hit = false;
for (var i = 0; i < beatMarkers.length; i++) {
var marker = beatMarkers[i];
if (marker.isActive && !marker.hasBeenHit) {
var distance = Math.sqrt(Math.pow(marker.x - marker.targetX, 2) + Math.pow(marker.y - marker.targetY, 2));
if (distance < 200) {
marker.hit();
hit = true;
break;
}
}
}
if (!hit) {
// Missed tap
combo = Math.max(0, combo - 1);
comboTxt.setText('Combo: ' + combo);
}
};
game.update = function () {
markerSpawnTimer++;
// Spawn markers based on beat (every 60 ticks = 1 second at 60fps)
if (markerSpawnTimer >= Math.max(30, 90 - LK.ticks / 300)) {
spawnBeatMarker();
markerSpawnTimer = 0;
}
// Gradually increase difficulty
if (LK.ticks % 600 === 0) {
gameSpeed += 0.1;
}
checkMissedMarkers();
// Clean up destroyed markers
for (var i = beatMarkers.length - 1; i >= 0; i--) {
if (beatMarkers[i].hasBeenHit) {
beatMarkers.splice(i, 1);
}
}
// Update UI
scoreTxt.setText(LK.getScore());
};
// Start the music
LK.playMusic('danceMusic');