/****
* 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');