/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Tile = Container.expand(function () { var self = Container.call(this); var tileGraphics = self.attachAsset('tile', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; // Will be updated dynamically when tile is created self.lane = 0; self.lastY = 0; self.pianoNotes = ['pianoC']; self.selectedNote = self.pianoNotes[Math.floor(Math.random() * self.pianoNotes.length)]; self.update = function () { self.lastY = self.y; self.y += self.speed; }; self.down = function (x, y, obj) { var targetY = 2732 - 100; if (Math.abs(self.y - targetY) < 100) { LK.setScore(LK.getScore() + 5); LK.getSound('pianoC').play(); LK.getSound('bass').play(); scoreTxt.setText(LK.getScore()); // Update high score if current score exceeds it if (LK.getScore() > highScore) { highScore = LK.getScore(); storage.highScore = highScore; highScoreTxt.setText('High: ' + highScore); } // Update game speed when score increases updateGameSpeed(); // Update speed for all existing tiles - increased progression for (var j = 0; j < tiles.length; j++) { tiles[j].speed = baseSpeed + Math.floor(LK.getScore() / 50) * 0.8; } self.destroy(); for (var i = tiles.length - 1; i >= 0; i--) { if (tiles[i] === self) { tiles.splice(i, 1); break; } } // Event handled successfully - no propagation control needed } else { LK.setScore(0); LK.getSound('buzz').play(); scoreTxt.setText(LK.getScore()); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2a2a2a }); /**** * Game Code ****/ var laneWidth = 2048 / 4; var lanes = []; var tiles = []; var laneConsecutiveCount = [0, 0, 0, 0]; // Track consecutive tiles per lane // Create lane separators for (var i = 1; i < 4; i++) { var separator = game.addChild(LK.getAsset('lane', { anchorX: 0.5, anchorY: 0 })); separator.x = i * laneWidth; separator.y = 0; } ; // Start main beat music immediately LK.playMusic('bgbeat', { volume: 2 }); // Create score text var scoreTxt = new Text2('0', { size: 120, fill: 0xffffff }); scoreTxt.anchor.set(0.5, 0); scoreTxt.y = 80; LK.gui.top.addChild(scoreTxt); // Create high score text - reset to 0 at start of each game var highScore = 0; storage.highScore = 0; var highScoreTxt = new Text2('High: ' + highScore, { size: 80, fill: 0xcccccc }); highScoreTxt.anchor.set(0.5, 0); highScoreTxt.y = 200; LK.gui.top.addChild(highScoreTxt); // Create bottom line marker var bottomLine = game.addChild(LK.getAsset('bottomLine', { anchorX: 0.5, anchorY: 0.5 })); bottomLine.x = 2048 / 2; bottomLine.y = 2732 - 100; bottomLine.width = 2048; // Base spawn interval and speed - made more challenging var baseSpawnInterval = 400; var baseSpeed = 8; // Spawn tiles with dynamic interval based on score var tileSpawnTimer = LK.setInterval(function () { // Start spawning multiple tiles at higher scores for increased difficulty var tilesToSpawn = 1; if (LK.getScore() >= 100) tilesToSpawn = Math.random() < 0.2 ? 2 : 1; if (LK.getScore() >= 300) tilesToSpawn = Math.random() < 0.3 ? 2 : 1; for (var tileCount = 0; tileCount < tilesToSpawn; tileCount++) { var newTile = new Tile(); var randomLane = Math.floor(Math.random() * 4); // Check if this lane already has 3 consecutive tiles, if so pick a different lane var attempts = 0; while (laneConsecutiveCount[randomLane] >= 3 && attempts < 10) { randomLane = Math.floor(Math.random() * 4); attempts++; } // If all lanes are at max, reset all counters and use original lane if (attempts >= 10) { for (var k = 0; k < 4; k++) { laneConsecutiveCount[k] = 0; } randomLane = Math.floor(Math.random() * 4); } newTile.x = randomLane * laneWidth + laneWidth / 2; newTile.y = -75 - tileCount * 200; // Offset multiple tiles vertically newTile.lane = randomLane; newTile.lastY = newTile.y; // Set speed based on current score - increase by 0.8 every 50 points newTile.speed = baseSpeed + Math.floor(LK.getScore() / 50) * 0.8; // Update consecutive count for this lane laneConsecutiveCount[randomLane]++; // Reset other lanes' consecutive count for (var j = 0; j < 4; j++) { if (j !== randomLane) { laneConsecutiveCount[j] = 0; } } tiles.push(newTile); game.addChild(newTile); } }, baseSpawnInterval); // Function to update spawn rate based on score function updateGameSpeed() { // Calculate new spawn interval - decrease by 30ms every 50 points (minimum 150ms) var newInterval = Math.max(150, baseSpawnInterval - Math.floor(LK.getScore() / 50) * 30); LK.clearInterval(tileSpawnTimer); tileSpawnTimer = LK.setInterval(function () { // Advanced difficulty: spawn multiple tiles simultaneously at higher scores var tilesToSpawn = 1; if (LK.getScore() >= 200) tilesToSpawn = Math.random() < 0.3 ? 2 : 1; if (LK.getScore() >= 500) tilesToSpawn = Math.random() < 0.4 ? 2 : 1; if (LK.getScore() >= 1000) tilesToSpawn = Math.random() < 0.2 ? 3 : Math.random() < 0.5 ? 2 : 1; for (var tileCount = 0; tileCount < tilesToSpawn; tileCount++) { var newTile = new Tile(); var randomLane = Math.floor(Math.random() * 4); // Check if this lane already has 3 consecutive tiles, if so pick a different lane var attempts = 0; while (laneConsecutiveCount[randomLane] >= 3 && attempts < 10) { randomLane = Math.floor(Math.random() * 4); attempts++; } // If all lanes are at max, reset all counters and use original lane if (attempts >= 10) { for (var k = 0; k < 4; k++) { laneConsecutiveCount[k] = 0; } randomLane = Math.floor(Math.random() * 4); } newTile.x = randomLane * laneWidth + laneWidth / 2; newTile.y = -75 - tileCount * 200; // Offset multiple tiles vertically newTile.lane = randomLane; newTile.lastY = newTile.y; // Set speed based on current score - increase by 0.8 every 50 points newTile.speed = baseSpeed + Math.floor(LK.getScore() / 50) * 0.8; // Update consecutive count for this lane laneConsecutiveCount[randomLane]++; // Reset other lanes' consecutive count for (var j = 0; j < 4; j++) { if (j !== randomLane) { laneConsecutiveCount[j] = 0; } } tiles.push(newTile); game.addChild(newTile); } }, newInterval); } game.down = function (x, y, obj) { // Only reset score if clicking on empty area (not on tiles) // The tile's own down handler will handle scoring when clicked correctly var clickedOnTile = false; for (var i = 0; i < tiles.length; i++) { var tile = tiles[i]; var tileBounds = { x: tile.x - 200, // tile width/2 y: tile.y - 75, // tile height/2 width: 400, height: 150 }; if (x >= tileBounds.x && x <= tileBounds.x + tileBounds.width && y >= tileBounds.y && y <= tileBounds.y + tileBounds.height) { clickedOnTile = true; break; } } if (!clickedOnTile) { LK.setScore(0); LK.getSound('buzz').play(); scoreTxt.setText(LK.getScore()); } }; game.update = function () { // Update tiles and check for missed tiles for (var i = tiles.length - 1; i >= 0; i--) { var tile = tiles[i]; // Check if tile went off screen (missed) if (tile.lastY < 2732 && tile.y >= 2732) { LK.setScore(0); LK.getSound('buzz').play(); scoreTxt.setText(LK.getScore()); tile.destroy(); tiles.splice(i, 1); } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Tile = Container.expand(function () {
var self = Container.call(this);
var tileGraphics = self.attachAsset('tile', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8; // Will be updated dynamically when tile is created
self.lane = 0;
self.lastY = 0;
self.pianoNotes = ['pianoC'];
self.selectedNote = self.pianoNotes[Math.floor(Math.random() * self.pianoNotes.length)];
self.update = function () {
self.lastY = self.y;
self.y += self.speed;
};
self.down = function (x, y, obj) {
var targetY = 2732 - 100;
if (Math.abs(self.y - targetY) < 100) {
LK.setScore(LK.getScore() + 5);
LK.getSound('pianoC').play();
LK.getSound('bass').play();
scoreTxt.setText(LK.getScore());
// Update high score if current score exceeds it
if (LK.getScore() > highScore) {
highScore = LK.getScore();
storage.highScore = highScore;
highScoreTxt.setText('High: ' + highScore);
}
// Update game speed when score increases
updateGameSpeed();
// Update speed for all existing tiles - increased progression
for (var j = 0; j < tiles.length; j++) {
tiles[j].speed = baseSpeed + Math.floor(LK.getScore() / 50) * 0.8;
}
self.destroy();
for (var i = tiles.length - 1; i >= 0; i--) {
if (tiles[i] === self) {
tiles.splice(i, 1);
break;
}
}
// Event handled successfully - no propagation control needed
} else {
LK.setScore(0);
LK.getSound('buzz').play();
scoreTxt.setText(LK.getScore());
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2a2a2a
});
/****
* Game Code
****/
var laneWidth = 2048 / 4;
var lanes = [];
var tiles = [];
var laneConsecutiveCount = [0, 0, 0, 0]; // Track consecutive tiles per lane
// Create lane separators
for (var i = 1; i < 4; i++) {
var separator = game.addChild(LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0
}));
separator.x = i * laneWidth;
separator.y = 0;
}
;
// Start main beat music immediately
LK.playMusic('bgbeat', {
volume: 2
});
// Create score text
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xffffff
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.y = 80;
LK.gui.top.addChild(scoreTxt);
// Create high score text - reset to 0 at start of each game
var highScore = 0;
storage.highScore = 0;
var highScoreTxt = new Text2('High: ' + highScore, {
size: 80,
fill: 0xcccccc
});
highScoreTxt.anchor.set(0.5, 0);
highScoreTxt.y = 200;
LK.gui.top.addChild(highScoreTxt);
// Create bottom line marker
var bottomLine = game.addChild(LK.getAsset('bottomLine', {
anchorX: 0.5,
anchorY: 0.5
}));
bottomLine.x = 2048 / 2;
bottomLine.y = 2732 - 100;
bottomLine.width = 2048;
// Base spawn interval and speed - made more challenging
var baseSpawnInterval = 400;
var baseSpeed = 8;
// Spawn tiles with dynamic interval based on score
var tileSpawnTimer = LK.setInterval(function () {
// Start spawning multiple tiles at higher scores for increased difficulty
var tilesToSpawn = 1;
if (LK.getScore() >= 100) tilesToSpawn = Math.random() < 0.2 ? 2 : 1;
if (LK.getScore() >= 300) tilesToSpawn = Math.random() < 0.3 ? 2 : 1;
for (var tileCount = 0; tileCount < tilesToSpawn; tileCount++) {
var newTile = new Tile();
var randomLane = Math.floor(Math.random() * 4);
// Check if this lane already has 3 consecutive tiles, if so pick a different lane
var attempts = 0;
while (laneConsecutiveCount[randomLane] >= 3 && attempts < 10) {
randomLane = Math.floor(Math.random() * 4);
attempts++;
}
// If all lanes are at max, reset all counters and use original lane
if (attempts >= 10) {
for (var k = 0; k < 4; k++) {
laneConsecutiveCount[k] = 0;
}
randomLane = Math.floor(Math.random() * 4);
}
newTile.x = randomLane * laneWidth + laneWidth / 2;
newTile.y = -75 - tileCount * 200; // Offset multiple tiles vertically
newTile.lane = randomLane;
newTile.lastY = newTile.y;
// Set speed based on current score - increase by 0.8 every 50 points
newTile.speed = baseSpeed + Math.floor(LK.getScore() / 50) * 0.8;
// Update consecutive count for this lane
laneConsecutiveCount[randomLane]++;
// Reset other lanes' consecutive count
for (var j = 0; j < 4; j++) {
if (j !== randomLane) {
laneConsecutiveCount[j] = 0;
}
}
tiles.push(newTile);
game.addChild(newTile);
}
}, baseSpawnInterval);
// Function to update spawn rate based on score
function updateGameSpeed() {
// Calculate new spawn interval - decrease by 30ms every 50 points (minimum 150ms)
var newInterval = Math.max(150, baseSpawnInterval - Math.floor(LK.getScore() / 50) * 30);
LK.clearInterval(tileSpawnTimer);
tileSpawnTimer = LK.setInterval(function () {
// Advanced difficulty: spawn multiple tiles simultaneously at higher scores
var tilesToSpawn = 1;
if (LK.getScore() >= 200) tilesToSpawn = Math.random() < 0.3 ? 2 : 1;
if (LK.getScore() >= 500) tilesToSpawn = Math.random() < 0.4 ? 2 : 1;
if (LK.getScore() >= 1000) tilesToSpawn = Math.random() < 0.2 ? 3 : Math.random() < 0.5 ? 2 : 1;
for (var tileCount = 0; tileCount < tilesToSpawn; tileCount++) {
var newTile = new Tile();
var randomLane = Math.floor(Math.random() * 4);
// Check if this lane already has 3 consecutive tiles, if so pick a different lane
var attempts = 0;
while (laneConsecutiveCount[randomLane] >= 3 && attempts < 10) {
randomLane = Math.floor(Math.random() * 4);
attempts++;
}
// If all lanes are at max, reset all counters and use original lane
if (attempts >= 10) {
for (var k = 0; k < 4; k++) {
laneConsecutiveCount[k] = 0;
}
randomLane = Math.floor(Math.random() * 4);
}
newTile.x = randomLane * laneWidth + laneWidth / 2;
newTile.y = -75 - tileCount * 200; // Offset multiple tiles vertically
newTile.lane = randomLane;
newTile.lastY = newTile.y;
// Set speed based on current score - increase by 0.8 every 50 points
newTile.speed = baseSpeed + Math.floor(LK.getScore() / 50) * 0.8;
// Update consecutive count for this lane
laneConsecutiveCount[randomLane]++;
// Reset other lanes' consecutive count
for (var j = 0; j < 4; j++) {
if (j !== randomLane) {
laneConsecutiveCount[j] = 0;
}
}
tiles.push(newTile);
game.addChild(newTile);
}
}, newInterval);
}
game.down = function (x, y, obj) {
// Only reset score if clicking on empty area (not on tiles)
// The tile's own down handler will handle scoring when clicked correctly
var clickedOnTile = false;
for (var i = 0; i < tiles.length; i++) {
var tile = tiles[i];
var tileBounds = {
x: tile.x - 200,
// tile width/2
y: tile.y - 75,
// tile height/2
width: 400,
height: 150
};
if (x >= tileBounds.x && x <= tileBounds.x + tileBounds.width && y >= tileBounds.y && y <= tileBounds.y + tileBounds.height) {
clickedOnTile = true;
break;
}
}
if (!clickedOnTile) {
LK.setScore(0);
LK.getSound('buzz').play();
scoreTxt.setText(LK.getScore());
}
};
game.update = function () {
// Update tiles and check for missed tiles
for (var i = tiles.length - 1; i >= 0; i--) {
var tile = tiles[i];
// Check if tile went off screen (missed)
if (tile.lastY < 2732 && tile.y >= 2732) {
LK.setScore(0);
LK.getSound('buzz').play();
scoreTxt.setText(LK.getScore());
tile.destroy();
tiles.splice(i, 1);
}
}
};