/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ // Import music beat plugin // Note class: represents a falling note var Note = Container.expand(function () { var self = Container.call(this); // Properties: keyIndex (0-3), speed, hit, missed self.keyIndex = 0; self.speed = 12; // px per frame self.hit = false; self.missed = false; self.noteAsset = null; // Set up note asset self.setType = function (keyIndex) { self.keyIndex = keyIndex; var assetId = 'note' + (keyIndex + 1); self.noteAsset = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); }; // Called every tick self.update = function () { self.y += self.speed; }; // Flash feedback (hit/miss) self.flash = function (type) { var flashId = type === 'hit' ? 'hitFlash' : 'missFlash'; var flash = LK.getAsset(flashId, { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0 }); flash.alpha = 0.7; self.addChild(flash); tween(flash, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { flash.destroy(); } }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xcccccc }); /**** * Game Code ****/ var NUM_KEYS = 4; var KEY_WIDTH = 400; var KEY_HEIGHT = 300; var KEY_GAP = 12; var NOTE_WIDTH = 320; var NOTE_HEIGHT = 120; var GAME_W = 2048; var GAME_H = 2732; var KEY_Y = 120; // distance from bottom // Add background image (fills the screen, behind all elements) var background = LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: GAME_W, height: GAME_H }); game.addChild(background); // Music // Sound for hit/miss // Feedback flash // Notes: colored ellipses // Piano keys: white rectangles // 4 piano keys (white), 4 note shapes (colored), 1 background music // Piano key layout: 4 keys, bottom of screen, evenly spaced // Key positions (centered) var keyPositions = []; var totalWidth = NUM_KEYS * KEY_WIDTH + (NUM_KEYS - 1) * KEY_GAP; var startX = (GAME_W - totalWidth) / 2 + KEY_WIDTH / 2; for (var i = 0; i < NUM_KEYS; i++) { keyPositions[i] = { x: startX + i * (KEY_WIDTH + KEY_GAP), y: GAME_H - KEY_HEIGHT / 2 - KEY_Y }; } // Create piano keys var pianoKeys = []; for (var i = 0; i < NUM_KEYS; i++) { var keyAssetId = 'pianoKey' + (i + 1); var key = new Container(); var keyShape = key.attachAsset(keyAssetId, { anchorX: 0.5, anchorY: 0.5 }); key.x = keyPositions[i].x; key.y = keyPositions[i].y; key.keyIndex = i; game.addChild(key); pianoKeys.push(key); } // Score display var score = 0; var bestScore = storage.bestScore || 0; var scoreTxt = new Text2('0', { size: 120, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Best score display (smaller, top right) var bestScoreTxt = new Text2('Rekor: ' + bestScore, { size: 60, fill: "#fff" }); bestScoreTxt.anchor.set(1, 0); LK.gui.topRight.addChild(bestScoreTxt); // Notes array var notes = []; // Note spawn timing var noteInterval = 38; // frames between notes (approx 1.5 notes/sec) var noteTimer = 0; // Feedback for key press (flash) function flashKey(keyIndex, type) { var key = pianoKeys[keyIndex]; var flashId = type === 'hit' ? 'hitFlash' : 'missFlash'; var flash = LK.getAsset(flashId, { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0 }); flash.alpha = 0.7; key.addChild(flash); tween(flash, { alpha: 0 }, { duration: 250, onFinish: function onFinish() { flash.destroy(); } }); } // Touch handling game.down = function (x, y, obj) { // Check if touch is on a key for (var i = 0; i < pianoKeys.length; i++) { var key = pianoKeys[i]; // Rectangle hit test var left = key.x - KEY_WIDTH / 2; var right = key.x + KEY_WIDTH / 2; var top = key.y - KEY_HEIGHT / 2; var bottom = key.y + KEY_HEIGHT / 2; if (x >= left && x <= right && y >= top && y <= bottom) { // Find the lowest note in this column that is hittable var hitNote = null; var hitWindow = 120; // px, how close to key to count as hit for (var j = 0; j < notes.length; j++) { var note = notes[j]; if (note.keyIndex === i && !note.hit && !note.missed) { // Note is in this column var noteBottom = note.y + NOTE_HEIGHT / 2; var keyTop = key.y - KEY_HEIGHT / 2; var keyBottom = key.y + KEY_HEIGHT / 2; // If note is within hit window above the key (falling down) if (noteBottom >= keyTop - hitWindow && noteBottom <= keyBottom + hitWindow) { // For falling notes, prefer the lowest note (closest to the key) if (!hitNote || note.y > hitNote.y) { hitNote = note; } } } } if (hitNote) { // Hit! hitNote.hit = true; hitNote.flash('hit'); flashKey(i, 'hit'); LK.getSound('hit').play(); score += 1; if (score > bestScore) { bestScore = score; storage.bestScore = bestScore; bestScoreTxt.setText('Rekor: ' + bestScore); } scoreTxt.setText(score); } else { // Miss (touched key but no note in window) flashKey(i, 'miss'); LK.getSound('miss').play(); // Optionally, penalize or just give feedback } break; } } }; // No drag or move needed for this game game.move = function (x, y, obj) {}; game.up = function (x, y, obj) {}; // Game update loop game.update = function () { // Adjust note speed based on score var baseSpeed = 6; // much slower than before var speedStep = 2.5; // how much to increase per step var stepScore = 10; // every 10 points after 20, increase speed var minScore = 20; var maxSpeed = 22; // cap speed so it doesn't get too fast var currentSpeed = baseSpeed; if (score >= minScore) { // For every stepScore after minScore, increase speed by speedStep var steps = Math.floor((score - minScore) / stepScore) + 1; currentSpeed = baseSpeed + steps * speedStep; if (currentSpeed > maxSpeed) currentSpeed = maxSpeed; } // Spawn notes at regular interval noteTimer++; if (noteTimer >= noteInterval) { noteTimer = 0; var keyIndex = Math.floor(Math.random() * NUM_KEYS); var note = new Note(); note.setType(keyIndex); note.x = keyPositions[keyIndex].x; note.y = 0 - NOTE_HEIGHT / 2; // Spawn at the very top note.lastY = note.y; note.lastHit = false; note.speed = currentSpeed; // set speed based on score notes.push(note); game.addChild(note); } // Update notes for (var i = notes.length - 1; i >= 0; i--) { var note = notes[i]; note.update(); // If note is hit, remove after short delay if (note.hit) { note.destroy(); notes.splice(i, 1); continue; } // If note passes below the key and not hit, mark as missed var key = pianoKeys[note.keyIndex]; var keyBottom = key.y + KEY_HEIGHT / 2; if (!note.missed && note.y - NOTE_HEIGHT / 2 > keyBottom + 40) { note.missed = true; note.flash('miss'); flashKey(note.keyIndex, 'miss'); LK.getSound('miss').play(); // End game on miss LK.effects.flashScreen(0xe57373, 600); if (score > bestScore) { bestScore = score; storage.bestScore = bestScore; } LK.stopMusic(); LK.showGameOver(); return; } // Remove notes that are far off screen if (note.y - NOTE_HEIGHT / 2 > GAME_H + 200) { note.destroy(); notes.splice(i, 1); } } }; // Start music game.onStart = function () { LK.stopMusic(); LK.playMusic('piano', { loop: true, fade: { start: 1, end: 1, duration: 0 }, start: 0 // always start from the beginning }); // Reset note timer noteTimer = 0; }; // Stop music when game ends game.onGameOver = function () { LK.stopMusic(); noteTimer = 0; };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// Import music beat plugin
// Note class: represents a falling note
var Note = Container.expand(function () {
var self = Container.call(this);
// Properties: keyIndex (0-3), speed, hit, missed
self.keyIndex = 0;
self.speed = 12; // px per frame
self.hit = false;
self.missed = false;
self.noteAsset = null;
// Set up note asset
self.setType = function (keyIndex) {
self.keyIndex = keyIndex;
var assetId = 'note' + (keyIndex + 1);
self.noteAsset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
};
// Called every tick
self.update = function () {
self.y += self.speed;
};
// Flash feedback (hit/miss)
self.flash = function (type) {
var flashId = type === 'hit' ? 'hitFlash' : 'missFlash';
var flash = LK.getAsset(flashId, {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0
});
flash.alpha = 0.7;
self.addChild(flash);
tween(flash, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
flash.destroy();
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xcccccc
});
/****
* Game Code
****/
var NUM_KEYS = 4;
var KEY_WIDTH = 400;
var KEY_HEIGHT = 300;
var KEY_GAP = 12;
var NOTE_WIDTH = 320;
var NOTE_HEIGHT = 120;
var GAME_W = 2048;
var GAME_H = 2732;
var KEY_Y = 120; // distance from bottom
// Add background image (fills the screen, behind all elements)
var background = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: GAME_W,
height: GAME_H
});
game.addChild(background);
// Music
// Sound for hit/miss
// Feedback flash
// Notes: colored ellipses
// Piano keys: white rectangles
// 4 piano keys (white), 4 note shapes (colored), 1 background music
// Piano key layout: 4 keys, bottom of screen, evenly spaced
// Key positions (centered)
var keyPositions = [];
var totalWidth = NUM_KEYS * KEY_WIDTH + (NUM_KEYS - 1) * KEY_GAP;
var startX = (GAME_W - totalWidth) / 2 + KEY_WIDTH / 2;
for (var i = 0; i < NUM_KEYS; i++) {
keyPositions[i] = {
x: startX + i * (KEY_WIDTH + KEY_GAP),
y: GAME_H - KEY_HEIGHT / 2 - KEY_Y
};
}
// Create piano keys
var pianoKeys = [];
for (var i = 0; i < NUM_KEYS; i++) {
var keyAssetId = 'pianoKey' + (i + 1);
var key = new Container();
var keyShape = key.attachAsset(keyAssetId, {
anchorX: 0.5,
anchorY: 0.5
});
key.x = keyPositions[i].x;
key.y = keyPositions[i].y;
key.keyIndex = i;
game.addChild(key);
pianoKeys.push(key);
}
// Score display
var score = 0;
var bestScore = storage.bestScore || 0;
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Best score display (smaller, top right)
var bestScoreTxt = new Text2('Rekor: ' + bestScore, {
size: 60,
fill: "#fff"
});
bestScoreTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(bestScoreTxt);
// Notes array
var notes = [];
// Note spawn timing
var noteInterval = 38; // frames between notes (approx 1.5 notes/sec)
var noteTimer = 0;
// Feedback for key press (flash)
function flashKey(keyIndex, type) {
var key = pianoKeys[keyIndex];
var flashId = type === 'hit' ? 'hitFlash' : 'missFlash';
var flash = LK.getAsset(flashId, {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0
});
flash.alpha = 0.7;
key.addChild(flash);
tween(flash, {
alpha: 0
}, {
duration: 250,
onFinish: function onFinish() {
flash.destroy();
}
});
}
// Touch handling
game.down = function (x, y, obj) {
// Check if touch is on a key
for (var i = 0; i < pianoKeys.length; i++) {
var key = pianoKeys[i];
// Rectangle hit test
var left = key.x - KEY_WIDTH / 2;
var right = key.x + KEY_WIDTH / 2;
var top = key.y - KEY_HEIGHT / 2;
var bottom = key.y + KEY_HEIGHT / 2;
if (x >= left && x <= right && y >= top && y <= bottom) {
// Find the lowest note in this column that is hittable
var hitNote = null;
var hitWindow = 120; // px, how close to key to count as hit
for (var j = 0; j < notes.length; j++) {
var note = notes[j];
if (note.keyIndex === i && !note.hit && !note.missed) {
// Note is in this column
var noteBottom = note.y + NOTE_HEIGHT / 2;
var keyTop = key.y - KEY_HEIGHT / 2;
var keyBottom = key.y + KEY_HEIGHT / 2;
// If note is within hit window above the key (falling down)
if (noteBottom >= keyTop - hitWindow && noteBottom <= keyBottom + hitWindow) {
// For falling notes, prefer the lowest note (closest to the key)
if (!hitNote || note.y > hitNote.y) {
hitNote = note;
}
}
}
}
if (hitNote) {
// Hit!
hitNote.hit = true;
hitNote.flash('hit');
flashKey(i, 'hit');
LK.getSound('hit').play();
score += 1;
if (score > bestScore) {
bestScore = score;
storage.bestScore = bestScore;
bestScoreTxt.setText('Rekor: ' + bestScore);
}
scoreTxt.setText(score);
} else {
// Miss (touched key but no note in window)
flashKey(i, 'miss');
LK.getSound('miss').play();
// Optionally, penalize or just give feedback
}
break;
}
}
};
// No drag or move needed for this game
game.move = function (x, y, obj) {};
game.up = function (x, y, obj) {};
// Game update loop
game.update = function () {
// Adjust note speed based on score
var baseSpeed = 6; // much slower than before
var speedStep = 2.5; // how much to increase per step
var stepScore = 10; // every 10 points after 20, increase speed
var minScore = 20;
var maxSpeed = 22; // cap speed so it doesn't get too fast
var currentSpeed = baseSpeed;
if (score >= minScore) {
// For every stepScore after minScore, increase speed by speedStep
var steps = Math.floor((score - minScore) / stepScore) + 1;
currentSpeed = baseSpeed + steps * speedStep;
if (currentSpeed > maxSpeed) currentSpeed = maxSpeed;
}
// Spawn notes at regular interval
noteTimer++;
if (noteTimer >= noteInterval) {
noteTimer = 0;
var keyIndex = Math.floor(Math.random() * NUM_KEYS);
var note = new Note();
note.setType(keyIndex);
note.x = keyPositions[keyIndex].x;
note.y = 0 - NOTE_HEIGHT / 2; // Spawn at the very top
note.lastY = note.y;
note.lastHit = false;
note.speed = currentSpeed; // set speed based on score
notes.push(note);
game.addChild(note);
}
// Update notes
for (var i = notes.length - 1; i >= 0; i--) {
var note = notes[i];
note.update();
// If note is hit, remove after short delay
if (note.hit) {
note.destroy();
notes.splice(i, 1);
continue;
}
// If note passes below the key and not hit, mark as missed
var key = pianoKeys[note.keyIndex];
var keyBottom = key.y + KEY_HEIGHT / 2;
if (!note.missed && note.y - NOTE_HEIGHT / 2 > keyBottom + 40) {
note.missed = true;
note.flash('miss');
flashKey(note.keyIndex, 'miss');
LK.getSound('miss').play();
// End game on miss
LK.effects.flashScreen(0xe57373, 600);
if (score > bestScore) {
bestScore = score;
storage.bestScore = bestScore;
}
LK.stopMusic();
LK.showGameOver();
return;
}
// Remove notes that are far off screen
if (note.y - NOTE_HEIGHT / 2 > GAME_H + 200) {
note.destroy();
notes.splice(i, 1);
}
}
};
// Start music
game.onStart = function () {
LK.stopMusic();
LK.playMusic('piano', {
loop: true,
fade: {
start: 1,
end: 1,
duration: 0
},
start: 0 // always start from the beginning
});
// Reset note timer
noteTimer = 0;
};
// Stop music when game ends
game.onGameOver = function () {
LK.stopMusic();
noteTimer = 0;
};
piyano tuşu. In-Game asset. 2d. High contrast. No shadows
dark mode müzik çalınan mekan. In-Game asset. 2d. High contrast. No shadows
kızgın surat. In-Game asset. 2d. High contrast. No shadows
müzik dinleyen neşeli surat. In-Game asset. 2d. High contrast. No shadows
müzik aleti beyaz. In-Game asset. 2d. High contrast. No shadows