User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'setText')' in or related to this line: 'scoreText.setText('Score: ' + LK.getScore());' Line Number: 453
User prompt
Oyunu tekrar gelistir. Ama ekledigin herşeyin bı manası olsun. Level atlamanın da bı manası olsun. Ne yaparsan bı karsilik da üret. ↪💡 Consider importing and using the following plugins: @upit/tween.v1, @upit/storage.v1
User prompt
Başka seyler daha ekle. Bağımlı yapacak uzun soluklu eğlenceli bı oyun olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1, @upit/storage.v1
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'multiplierText.style.fill = 0xFFFFFF; // White for 1x' Line Number: 195
User prompt
Oyuna kendin birşeyler kat iyilestir
User prompt
Hataları düzelt
User prompt
Pluginler de yükleme hatası var düzelt
User prompt
Kendin oyunu geliştirecek fikirler ekle
User prompt
Her 5 tuş da bı %2 kadar oyun hızi artsın
User prompt
Nice yapmak sifirlamasin artık. Eğer 2/3 ise onu 1/3 E indirsin. Her "nice" -1 Early yapsın.
User prompt
Recoveryyi kaldır. Adını early diye yaz. Oyuncu eğer üst üste early yaparsa kaybedecek. Ve o early skorunda 0/3 yazacak. Her hata yaptığında 1 artcak. Ta ki 3/3 olana kadar. Ama 2/3 iken "Nice" yaparsa sifirlancak
User prompt
Delete that game over scene. Also if the gamer makes 3 earlies at the same time the game will end we lose. But if he manages to take control. It resets (make a score for that) also doing it early should not be -5 instead it should be -30
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'toGlobal')' in or related to this line: 'var localPos = self.toLocal(obj.parent.toGlobal(obj.position));' Line Number: 80
User prompt
Bı Game over sahnesi yaz. Tekrar başlatma düğmesi de olsun
User prompt
Oyuncu yanlışlıkla early yaptigi zaman combo başa sarmalı
User prompt
Çift tiklamali tuşu kaldır. Yerine sadece bı tane koy
User prompt
Iki kez tıklamanız gereken yeni bı tile üret assetsle beraber
User prompt
Bazen iki tuş aynı anda gelebilsin (2 den fazla olmasın)
User prompt
Score displayini ayır ikiye. +10 a ait başka bı asset -5 ait başka bı assets olsun. Böylece ikisine ayrı Ui koyabilirim.
User prompt
Ortadaki feedback kısmına kazandığımız ve kaybettiğimiz skoru yazan bı assets koy.
User prompt
Bütün Piano1 Piano2 Piano3 Piano4 ve Piano5 seslerini tuşlara rastgele bir şekilde gelecek şekilde ekle.
User prompt
Add the music to game
User prompt
Tap0 Piano,Piano2 ve Bass soundlarını 4 Tuşa eşit dağıt
User prompt
4 ayrı "Tap" ses kimliği oluştur. 4 notaya da ayrı ses vericem çünkü.
User prompt
"Early" "Missed" ve "Nice" yazısını assetse çevir. Bende boylelikle image değiştirebilirim
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
currentLevel: 1,
totalGamesPlayed: 0,
achievements: {},
unlockedLevels: 1
});
/****
* Classes
****/
var Particle = Container.expand(function (x, y, color) {
var self = Container.call(this);
var graphics = self.attachAsset('feedbackPerfect', {
anchorX: 0.5,
anchorY: 0.5
});
graphics.tint = color || 0xFFD700;
graphics.width = 20;
graphics.height = 20;
self.x = x;
self.y = y;
self.vx = (Math.random() - 0.5) * 10;
self.vy = (Math.random() - 0.5) * 10 - 5;
self.life = 60;
self.maxLife = 60;
self.update = function () {
self.x += self.vx;
self.y += self.vy;
self.vy += 0.2; // gravity
self.life--;
self.alpha = self.life / self.maxLife;
if (self.life <= 0) {
self.destroy();
}
};
return self;
});
var PowerTile = Container.expand(function (laneIndex, powerType) {
var self = Container.call(this);
var graphics = self.attachAsset('quickTile' + laneIndex, {
anchorX: 0.5,
anchorY: 0.5
});
// Tint based on power type
if (powerType === 'double') {
graphics.tint = 0xFFD700; // Gold for double score
} else if (powerType === 'slow') {
graphics.tint = 0x00FFFF; // Cyan for slow time
} else if (powerType === 'shield') {
graphics.tint = 0x00FF00; // Green for shield
}
self.speed = 12;
self.lane = laneIndex || 0;
self.powerType = powerType;
self.hit = false;
self.missed = false;
self.earlyPressed = false;
self.destroyed = false;
// Add pulsing effect
self.pulseTimer = 0;
self.update = function () {
if (self.destroyed) return;
self.y += self.speed;
// Pulsing effect
self.pulseTimer++;
graphics.scaleX = 1 + Math.sin(self.pulseTimer * 0.2) * 0.1;
graphics.scaleY = 1 + Math.sin(self.pulseTimer * 0.2) * 0.1;
// Check if tile is past hit line and not hit
if (self.y > hitLineY + 80 && !self.hit && !self.missed) {
self.missed = true;
comboCount = 0;
comboMultiplier = 1;
perfectStreak = 0;
showFeedback('MISSED', self.lane);
LK.getSound('miss').play();
LK.showGameOver();
}
};
return self;
});
var QuickTile = Container.expand(function (laneIndex) {
var self = Container.call(this);
var assetName = 'quickTile' + laneIndex;
var graphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 12;
self.lane = laneIndex || 0;
self.hit = false;
self.missed = false;
self.earlyPressed = false;
self.destroyed = false;
self.update = function () {
if (self.destroyed) return;
self.y += self.speed;
// Check if tile is past hit line and not hit
if (self.y > hitLineY + 80 && !self.hit && !self.missed) {
self.missed = true;
comboCount = 0; // Reset combo on miss
comboMultiplier = 1; // Reset multiplier
perfectStreak = 0; // Reset perfect streak
showFeedback('MISSED', self.lane);
LK.getSound('miss').play();
LK.showGameOver();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a1a
});
/****
* Game Code
****/
var lanes = [];
var hitLineY = 2200;
var tiles = [];
var activeLanes = [false, false, false, false];
var comboCount = 0;
var tileSpawnTimer = 0;
var feedbackTexts = [];
var tileSpawnInterval = 45;
var gameSpeed = 1;
var earlyCount = 0;
var keyPressCount = 0;
var particles = [];
var comboMultiplier = 1;
var perfectStreak = 0;
var lastHitTime = 0;
var currentLevel = storage.currentLevel || 1;
var powerTiles = [];
var activePowerUps = {
doubleScore: 0,
slowTime: 0,
shield: 0
};
// Achievement definitions
var achievements = {
firstWin: {
name: "First Steps",
desc: "Complete your first game",
unlocked: false
},
perfectionist: {
name: "Perfectionist",
desc: "Get 50 perfect hits in a row",
unlocked: false
},
speedDemon: {
name: "Speed Demon",
desc: "Reach level 5",
unlocked: false
},
comboMaster: {
name: "Combo Master",
desc: "Achieve a 100+ combo",
unlocked: false
},
highScorer: {
name: "High Scorer",
desc: "Score 10,000 points",
unlocked: false
}
};
// Load saved achievements
for (var key in achievements) {
if (storage.achievements && storage.achievements[key]) {
achievements[key].unlocked = true;
}
}
// Create lanes
for (var i = 0; i < 4; i++) {
var lane = game.addChild(LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0.5
}));
lane.x = 256 + i * 512;
lane.y = 1366;
lanes.push(lane);
}
// Create hit line
var hitLine = game.addChild(LK.getAsset('hitLine', {
anchorX: 0.5,
anchorY: 0.5
}));
hitLine.x = 1024;
hitLine.y = hitLineY;
// Create lane dividers
for (var i = 1; i < 4; i++) {
var divider = game.addChild(LK.getAsset('laneDivider', {
anchorX: 0.5,
anchorY: 0.5
}));
divider.x = i * 512;
divider.y = 1366;
}
// Create UI
var scoreText = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var comboText = new Text2('Combo: 0', {
size: 60,
fill: 0xFFFF00
});
comboText.anchor.set(0.5, 0);
comboText.y = 100;
LK.gui.top.addChild(comboText);
var earlyText = new Text2('Early: 0/3', {
size: 60,
fill: 0xFF4444
});
earlyText.anchor.set(0.5, 0);
earlyText.y = 160;
LK.gui.top.addChild(earlyText);
var streakText = new Text2('Streak: 0', {
size: 50,
fill: 0x00FFFF
});
streakText.anchor.set(0.5, 0);
streakText.y = 220;
LK.gui.top.addChild(streakText);
var multiplierText = new Text2('x1', {
size: 80,
fill: 0xFFD700
});
multiplierText.anchor.set(1, 0);
multiplierText.x = -20;
multiplierText.y = 20;
LK.gui.topRight.addChild(multiplierText);
var levelText = new Text2('Level: ' + currentLevel, {
size: 50,
fill: 0xFFFFFF
});
levelText.anchor.set(0, 0);
levelText.x = 20;
levelText.y = 20;
LK.gui.topLeft.addChild(levelText);
var highScoreText = new Text2('Best: ' + storage.highScore, {
size: 40,
fill: 0xFFD700
});
highScoreText.anchor.set(0, 0);
highScoreText.x = 20;
highScoreText.y = 80;
LK.gui.topLeft.addChild(highScoreText);
function updateScoreDisplay() {
scoreText.setText('Score: ' + LK.getScore());
comboText.setText('Combo: ' + comboCount);
earlyText.setText('Early: ' + earlyCount + '/3');
streakText.setText('Streak: ' + perfectStreak);
multiplierText.setText('x' + comboMultiplier);
levelText.setText('Level: ' + currentLevel);
highScoreText.setText('Best: ' + storage.highScore);
// Update multiplier color based on value
if (comboMultiplier >= 4) {
multiplierText.fill = 0xFF0000; // Red for 4x+
} else if (comboMultiplier >= 3) {
multiplierText.fill = 0xFF8800; // Orange for 3x
} else if (comboMultiplier >= 2) {
multiplierText.fill = 0xFFD700; // Gold for 2x
} else {
multiplierText.fill = 0xFFFFFF; // White for 1x
}
// Check achievements
checkAchievements();
}
function showFeedback(text, laneIndex) {
var assetName = 'feedback' + text.charAt(0).toUpperCase() + text.slice(1).toLowerCase();
var feedbackImage = game.addChild(LK.getAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
}));
feedbackImage.x = 1024; // Center of screen
feedbackImage.y = 1366; // Center of screen vertically
feedbackImage.alpha = 1;
feedbackTexts.push(feedbackImage);
// Add score display based on feedback type
var scoreDisplay;
if (text === 'NICE') {
scoreDisplay = game.addChild(LK.getAsset('positiveScoreDisplay', {
anchorX: 0.5,
anchorY: 0.5
}));
} else {
scoreDisplay = game.addChild(LK.getAsset('negativeScoreDisplay', {
anchorX: 0.5,
anchorY: 0.5
}));
}
scoreDisplay.x = 1024; // Center of screen
scoreDisplay.y = 1450; // Below feedback
scoreDisplay.alpha = 1;
feedbackTexts.push(scoreDisplay);
// Create score text overlay
var scoreChangeText = new Text2('', {
size: 60,
fill: text === 'NICE' ? 0x00FF00 : 0xFF0000
});
scoreChangeText.anchor.set(0.5, 0.5);
scoreChangeText.x = scoreDisplay.x;
scoreChangeText.y = scoreDisplay.y;
if (text === 'NICE') {
scoreChangeText.setText('+10');
} else if (text === 'EARLY') {
scoreChangeText.setText('-30');
} else if (text === 'MISSED') {
scoreChangeText.setText('0');
}
game.addChild(scoreChangeText);
feedbackTexts.push(scoreChangeText);
tween(feedbackImage, {
alpha: 0,
y: feedbackImage.y - 100
}, {
duration: 1000,
onFinish: function onFinish() {
feedbackImage.destroy();
var index = feedbackTexts.indexOf(feedbackImage);
if (index > -1) feedbackTexts.splice(index, 1);
}
});
tween(scoreDisplay, {
alpha: 0,
y: scoreDisplay.y - 100
}, {
duration: 1000,
onFinish: function onFinish() {
scoreDisplay.destroy();
var index = feedbackTexts.indexOf(scoreDisplay);
if (index > -1) feedbackTexts.splice(index, 1);
}
});
tween(scoreChangeText, {
alpha: 0,
y: scoreChangeText.y - 100
}, {
duration: 1000,
onFinish: function onFinish() {
scoreChangeText.destroy();
var index = feedbackTexts.indexOf(scoreChangeText);
if (index > -1) feedbackTexts.splice(index, 1);
}
});
}
function spawnTile() {
// 5% chance to spawn power tile (increases with level)
var powerChance = 0.05 + currentLevel * 0.01;
if (Math.random() < powerChance) {
spawnPowerTile();
return;
}
// Adjusted spawn chances based on level
var multiTileChance = 0.3 + currentLevel * 0.05; // More multi-tiles at higher levels
var spawnTwo = Math.random() < multiTileChance;
if (spawnTwo) {
// Spawn two tiles in different lanes
var laneIndex1 = Math.floor(Math.random() * 4);
var laneIndex2;
// Make sure second lane is different from first
do {
laneIndex2 = Math.floor(Math.random() * 4);
} while (laneIndex2 === laneIndex1);
// Create first tile
var tile1 = new QuickTile(laneIndex1);
tile1.x = 256 + laneIndex1 * 512;
tile1.y = -100;
tiles.push(tile1);
game.addChild(tile1);
// Create second tile
var tile2 = new QuickTile(laneIndex2);
tile2.x = 256 + laneIndex2 * 512;
tile2.y = -100;
tiles.push(tile2);
game.addChild(tile2);
} else {
// Spawn single tile
var laneIndex = Math.floor(Math.random() * 4);
var tile = new QuickTile(laneIndex);
tile.x = 256 + laneIndex * 512;
tile.y = -100;
tiles.push(tile);
game.addChild(tile);
}
}
function createParticles(x, y, count, color) {
for (var i = 0; i < count; i++) {
var particle = new Particle(x, y, color);
particles.push(particle);
game.addChild(particle);
}
}
function checkAchievements() {
var currentScore = LK.getScore();
// High Scorer achievement
if (currentScore >= 10000 && !achievements.highScorer.unlocked) {
unlockAchievement('highScorer');
}
// Perfectionist achievement
if (perfectStreak >= 50 && !achievements.perfectionist.unlocked) {
unlockAchievement('perfectionist');
}
// Combo Master achievement
if (comboCount >= 100 && !achievements.comboMaster.unlocked) {
unlockAchievement('comboMaster');
}
// Speed Demon achievement
if (currentLevel >= 5 && !achievements.speedDemon.unlocked) {
unlockAchievement('speedDemon');
}
// Update high score
if (currentScore > storage.highScore) {
storage.highScore = currentScore;
}
}
function unlockAchievement(achievementKey) {
achievements[achievementKey].unlocked = true;
if (!storage.achievements) storage.achievements = {};
storage.achievements[achievementKey] = true;
// Show achievement notification
showAchievementNotification(achievements[achievementKey]);
LK.effects.flashScreen(0xFFD700, 500);
}
function showAchievementNotification(achievement) {
var achievementText = new Text2('Achievement Unlocked!\n' + achievement.name, {
size: 60,
fill: 0xFFD700
});
achievementText.anchor.set(0.5, 0.5);
achievementText.x = 1024;
achievementText.y = 800;
game.addChild(achievementText);
tween(achievementText, {
alpha: 0,
y: achievementText.y - 100
}, {
duration: 3000,
onFinish: function onFinish() {
achievementText.destroy();
}
});
}
function spawnPowerTile() {
var powerTypes = ['double', 'slow', 'shield'];
var powerType = powerTypes[Math.floor(Math.random() * powerTypes.length)];
var laneIndex = Math.floor(Math.random() * 4);
var powerTile = new PowerTile(laneIndex, powerType);
powerTile.x = 256 + laneIndex * 512;
powerTile.y = -100;
powerTiles.push(powerTile);
game.addChild(powerTile);
}
function activatePowerUp(powerType) {
if (powerType === 'double') {
activePowerUps.doubleScore = 600; // 10 seconds at 60fps
showPowerUpNotification('Double Score!', 0xFFD700);
} else if (powerType === 'slow') {
activePowerUps.slowTime = 600;
showPowerUpNotification('Slow Time!', 0x00FFFF);
} else if (powerType === 'shield') {
activePowerUps.shield = 600;
showPowerUpNotification('Shield Active!', 0x00FF00);
}
}
function showPowerUpNotification(text, color) {
var powerText = new Text2(text, {
size: 80,
fill: color
});
powerText.anchor.set(0.5, 0.5);
powerText.x = 1024;
powerText.y = 1000;
game.addChild(powerText);
tween(powerText, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5,
y: powerText.y - 100
}, {
duration: 2000,
onFinish: function onFinish() {
powerText.destroy();
}
});
}
function getLaneFromX(x) {
if (x < 512) return 0;
if (x < 1024) return 1;
if (x < 1536) return 2;
return 3;
}
function activateLane(laneIndex) {
if (laneIndex >= 0 && laneIndex < 4) {
activeLanes[laneIndex] = true;
lanes[laneIndex].removeChild(lanes[laneIndex].children[0]);
var activeLane = LK.getAsset('laneActive', {
anchorX: 0.5,
anchorY: 0.5
});
lanes[laneIndex].addChild(activeLane);
}
}
function deactivateLane(laneIndex) {
if (laneIndex >= 0 && laneIndex < 4) {
activeLanes[laneIndex] = false;
lanes[laneIndex].removeChild(lanes[laneIndex].children[0]);
var normalLane = LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0.5
});
lanes[laneIndex].addChild(normalLane);
}
}
game.down = function (x, y, obj) {
var laneIndex = getLaneFromX(x);
activateLane(laneIndex);
// Increment key press counter
keyPressCount++;
// Increase game speed by 2% every 5 key presses
if (keyPressCount % 5 === 0) {
gameSpeed *= 1.02;
}
// Add lane press animation
tween(lanes[laneIndex], {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 100,
easing: tween.easeOut
});
// Check for tile hits
var hitTile = false;
// Check power tiles first
for (var i = 0; i < powerTiles.length; i++) {
var powerTile = powerTiles[i];
if (powerTile.lane === laneIndex && !powerTile.missed && !powerTile.earlyPressed) {
var distance = Math.abs(powerTile.y - hitLineY);
if (distance <= 80 && !powerTile.hit) {
powerTile.hit = true;
activatePowerUp(powerTile.powerType);
createParticles(powerTile.x, powerTile.y, 12, 0xFFD700);
tween(powerTile, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
onFinish: function onFinish() {
if (!powerTile.destroyed) {
powerTile.destroyed = true;
powerTile.destroy();
}
}
});
hitTile = true;
break;
}
}
}
// Check regular tiles
for (var i = 0; i < tiles.length; i++) {
var tile = tiles[i];
if (tile.lane === laneIndex && !tile.missed && !tile.earlyPressed) {
var distance = Math.abs(tile.y - hitLineY);
if (distance <= 80) {
// Handle QuickTile
if (!tile.hit) {
tile.hit = true;
// Calculate combo multiplier
comboMultiplier = Math.min(4, Math.floor(comboCount / 5) + 1);
var baseScore = 10;
// Apply power-up bonuses
if (activePowerUps.doubleScore > 0) {
baseScore *= 2;
}
var scoreToAdd = baseScore * comboMultiplier;
// Check for perfect timing (within 20 pixels)
var perfectTiming = distance <= 20;
if (perfectTiming) {
scoreToAdd *= 1.5; // 1.5x bonus for perfect timing
perfectStreak++;
createParticles(tile.x, tile.y, 8, 0xFFD700);
// Screen flash for perfect streak milestones
if (perfectStreak % 10 === 0) {
LK.effects.flashScreen(0xFFD700, 200);
}
} else {
perfectStreak = 0;
createParticles(tile.x, tile.y, 5, 0x00FF00);
}
LK.setScore(LK.getScore() + Math.floor(scoreToAdd));
comboCount++;
lastHitTime = LK.ticks;
// Decrement early count on nice hit (minimum 0)
if (earlyCount > 0) {
earlyCount--;
}
showFeedback('NICE', laneIndex);
// Use random Piano1-Piano5 sounds for each tile hit
var pianoSounds = ['Piano1', 'Piano2', 'Piano3', 'Piano4', 'Piano5'];
var randomSound = pianoSounds[Math.floor(Math.random() * pianoSounds.length)];
LK.getSound(randomSound).play();
// Visual effect
tween(tile, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
onFinish: function onFinish() {
if (!tile.destroyed) {
tile.destroyed = true;
tile.destroy();
}
}
});
updateScoreDisplay();
hitTile = true;
break;
}
} else if (tile.y < hitLineY - 80) {
// Early press
tile.earlyPressed = true;
comboCount = 0; // Reset combo on early press
comboMultiplier = 1; // Reset multiplier
perfectStreak = 0; // Reset perfect streak
earlyCount++; // Increment early count
showFeedback('EARLY', laneIndex);
LK.getSound('early').play();
LK.setScore(LK.getScore() - 30); // Deduct 30 points for early press
// Check if 3 earlies reached
if (earlyCount >= 3) {
LK.showGameOver();
}
// Destroy tile immediately on early press
tween(tile, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 200,
onFinish: function onFinish() {
if (!tile.destroyed) {
tile.destroyed = true;
tile.destroy();
}
}
});
updateScoreDisplay();
hitTile = true;
break;
}
}
}
};
game.up = function (x, y, obj) {
var laneIndex = getLaneFromX(x);
deactivateLane(laneIndex);
// Add lane release animation
tween(lanes[laneIndex], {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.easeOut
});
};
// Start background music
LK.playMusic('Music');
game.update = function () {
// Update power-ups
for (var powerType in activePowerUps) {
if (activePowerUps[powerType] > 0) {
activePowerUps[powerType]--;
}
}
// Apply slow time effect
var currentGameSpeed = gameSpeed;
if (activePowerUps.slowTime > 0) {
currentGameSpeed *= 0.5;
}
// Spawn tiles
tileSpawnTimer++;
var adjustedSpawnInterval = tileSpawnInterval;
if (activePowerUps.slowTime > 0) {
adjustedSpawnInterval *= 2;
}
if (tileSpawnTimer >= adjustedSpawnInterval) {
spawnTile();
tileSpawnTimer = 0;
// Level progression system
var targetScore = currentLevel * 1000;
if (LK.getScore() >= targetScore) {
currentLevel++;
storage.currentLevel = currentLevel;
if (currentLevel > storage.unlockedLevels) {
storage.unlockedLevels = currentLevel;
}
showPowerUpNotification('Level Up! Level ' + currentLevel, 0xFF00FF);
LK.effects.flashScreen(0xFF00FF, 800);
}
// Increase difficulty over time
if (LK.ticks % 300 === 0) {
gameSpeed += 0.15;
tileSpawnInterval = Math.max(25, tileSpawnInterval - 1);
}
}
// Clean up tiles
for (var i = tiles.length - 1; i >= 0; i--) {
var tile = tiles[i];
if (!tile || tile.destroyed) {
tiles.splice(i, 1);
continue;
}
if (tile.y > 2800 || tile.hit || tile.missed && tile.y > hitLineY + 200 || tile.earlyPressed && tile.y > 2800) {
tile.destroyed = true;
tile.destroy();
tiles.splice(i, 1);
}
}
// Clean up power tiles
for (var i = powerTiles.length - 1; i >= 0; i--) {
var powerTile = powerTiles[i];
if (!powerTile || powerTile.destroyed) {
powerTiles.splice(i, 1);
continue;
}
if (powerTile.y > 2800 || powerTile.hit || powerTile.missed && powerTile.y > hitLineY + 200) {
powerTile.destroyed = true;
powerTile.destroy();
powerTiles.splice(i, 1);
}
}
// Update tile speeds based on game speed
var effectiveSpeed = gameSpeed;
if (activePowerUps.slowTime > 0) {
effectiveSpeed *= 0.5;
}
for (var i = 0; i < tiles.length; i++) {
if (tiles[i] && !tiles[i].destroyed) {
tiles[i].speed = 12 * effectiveSpeed;
}
}
// Update power tile speeds
for (var i = 0; i < powerTiles.length; i++) {
if (powerTiles[i] && !powerTiles[i].destroyed) {
powerTiles[i].speed = 12 * effectiveSpeed;
}
}
// Update particles
for (var i = particles.length - 1; i >= 0; i--) {
var particle = particles[i];
if (!particle || particle.life <= 0) {
if (particle) particle.destroy();
particles.splice(i, 1);
}
}
// Combo decay system - reduce combo if no hits for 3 seconds
if (LK.ticks - lastHitTime > 180 && comboCount > 0) {
comboCount = Math.max(0, comboCount - 1);
comboMultiplier = Math.min(4, Math.floor(comboCount / 5) + 1);
updateScoreDisplay();
lastHitTime = LK.ticks; // Reset timer to prevent rapid decay
}
};
// Override game over to save progress and unlock achievements
var originalShowGameOver = LK.showGameOver;
LK.showGameOver = function () {
// Save game stats
storage.totalGamesPlayed++;
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
}
// Unlock first win achievement if it's the first game
if (storage.totalGamesPlayed === 1 && !achievements.firstWin.unlocked) {
unlockAchievement('firstWin');
}
// Call original game over
originalShowGameOver();
}; ===================================================================
--- original.js
+++ change.js
@@ -1,8 +1,15 @@
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ highScore: 0,
+ currentLevel: 1,
+ totalGamesPlayed: 0,
+ achievements: {},
+ unlockedLevels: 1
+});
/****
* Classes
****/
@@ -32,8 +39,51 @@
}
};
return self;
});
+var PowerTile = Container.expand(function (laneIndex, powerType) {
+ var self = Container.call(this);
+ var graphics = self.attachAsset('quickTile' + laneIndex, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Tint based on power type
+ if (powerType === 'double') {
+ graphics.tint = 0xFFD700; // Gold for double score
+ } else if (powerType === 'slow') {
+ graphics.tint = 0x00FFFF; // Cyan for slow time
+ } else if (powerType === 'shield') {
+ graphics.tint = 0x00FF00; // Green for shield
+ }
+ self.speed = 12;
+ self.lane = laneIndex || 0;
+ self.powerType = powerType;
+ self.hit = false;
+ self.missed = false;
+ self.earlyPressed = false;
+ self.destroyed = false;
+ // Add pulsing effect
+ self.pulseTimer = 0;
+ self.update = function () {
+ if (self.destroyed) return;
+ self.y += self.speed;
+ // Pulsing effect
+ self.pulseTimer++;
+ graphics.scaleX = 1 + Math.sin(self.pulseTimer * 0.2) * 0.1;
+ graphics.scaleY = 1 + Math.sin(self.pulseTimer * 0.2) * 0.1;
+ // Check if tile is past hit line and not hit
+ if (self.y > hitLineY + 80 && !self.hit && !self.missed) {
+ self.missed = true;
+ comboCount = 0;
+ comboMultiplier = 1;
+ perfectStreak = 0;
+ showFeedback('MISSED', self.lane);
+ LK.getSound('miss').play();
+ LK.showGameOver();
+ }
+ };
+ return self;
+});
var QuickTile = Container.expand(function (laneIndex) {
var self = Container.call(this);
var assetName = 'quickTile' + laneIndex;
var graphics = self.attachAsset(assetName, {
@@ -87,8 +137,49 @@
var particles = [];
var comboMultiplier = 1;
var perfectStreak = 0;
var lastHitTime = 0;
+var currentLevel = storage.currentLevel || 1;
+var powerTiles = [];
+var activePowerUps = {
+ doubleScore: 0,
+ slowTime: 0,
+ shield: 0
+};
+// Achievement definitions
+var achievements = {
+ firstWin: {
+ name: "First Steps",
+ desc: "Complete your first game",
+ unlocked: false
+ },
+ perfectionist: {
+ name: "Perfectionist",
+ desc: "Get 50 perfect hits in a row",
+ unlocked: false
+ },
+ speedDemon: {
+ name: "Speed Demon",
+ desc: "Reach level 5",
+ unlocked: false
+ },
+ comboMaster: {
+ name: "Combo Master",
+ desc: "Achieve a 100+ combo",
+ unlocked: false
+ },
+ highScorer: {
+ name: "High Scorer",
+ desc: "Score 10,000 points",
+ unlocked: false
+ }
+};
+// Load saved achievements
+for (var key in achievements) {
+ if (storage.achievements && storage.achievements[key]) {
+ achievements[key].unlocked = true;
+ }
+}
// Create lanes
for (var i = 0; i < 4; i++) {
var lane = game.addChild(LK.getAsset('lane', {
anchorX: 0.5,
@@ -149,14 +240,32 @@
multiplierText.anchor.set(1, 0);
multiplierText.x = -20;
multiplierText.y = 20;
LK.gui.topRight.addChild(multiplierText);
+var levelText = new Text2('Level: ' + currentLevel, {
+ size: 50,
+ fill: 0xFFFFFF
+});
+levelText.anchor.set(0, 0);
+levelText.x = 20;
+levelText.y = 20;
+LK.gui.topLeft.addChild(levelText);
+var highScoreText = new Text2('Best: ' + storage.highScore, {
+ size: 40,
+ fill: 0xFFD700
+});
+highScoreText.anchor.set(0, 0);
+highScoreText.x = 20;
+highScoreText.y = 80;
+LK.gui.topLeft.addChild(highScoreText);
function updateScoreDisplay() {
scoreText.setText('Score: ' + LK.getScore());
comboText.setText('Combo: ' + comboCount);
earlyText.setText('Early: ' + earlyCount + '/3');
streakText.setText('Streak: ' + perfectStreak);
multiplierText.setText('x' + comboMultiplier);
+ levelText.setText('Level: ' + currentLevel);
+ highScoreText.setText('Best: ' + storage.highScore);
// Update multiplier color based on value
if (comboMultiplier >= 4) {
multiplierText.fill = 0xFF0000; // Red for 4x+
} else if (comboMultiplier >= 3) {
@@ -165,8 +274,10 @@
multiplierText.fill = 0xFFD700; // Gold for 2x
} else {
multiplierText.fill = 0xFFFFFF; // White for 1x
}
+ // Check achievements
+ checkAchievements();
}
function showFeedback(text, laneIndex) {
var assetName = 'feedback' + text.charAt(0).toUpperCase() + text.slice(1).toLowerCase();
var feedbackImage = game.addChild(LK.getAsset(assetName, {
@@ -245,10 +356,17 @@
}
});
}
function spawnTile() {
- // 30% chance to spawn two tiles simultaneously
- var spawnTwo = Math.random() < 0.3;
+ // 5% chance to spawn power tile (increases with level)
+ var powerChance = 0.05 + currentLevel * 0.01;
+ if (Math.random() < powerChance) {
+ spawnPowerTile();
+ return;
+ }
+ // Adjusted spawn chances based on level
+ var multiTileChance = 0.3 + currentLevel * 0.05; // More multi-tiles at higher levels
+ var spawnTwo = Math.random() < multiTileChance;
if (spawnTwo) {
// Spawn two tiles in different lanes
var laneIndex1 = Math.floor(Math.random() * 4);
var laneIndex2;
@@ -284,8 +402,101 @@
particles.push(particle);
game.addChild(particle);
}
}
+function checkAchievements() {
+ var currentScore = LK.getScore();
+ // High Scorer achievement
+ if (currentScore >= 10000 && !achievements.highScorer.unlocked) {
+ unlockAchievement('highScorer');
+ }
+ // Perfectionist achievement
+ if (perfectStreak >= 50 && !achievements.perfectionist.unlocked) {
+ unlockAchievement('perfectionist');
+ }
+ // Combo Master achievement
+ if (comboCount >= 100 && !achievements.comboMaster.unlocked) {
+ unlockAchievement('comboMaster');
+ }
+ // Speed Demon achievement
+ if (currentLevel >= 5 && !achievements.speedDemon.unlocked) {
+ unlockAchievement('speedDemon');
+ }
+ // Update high score
+ if (currentScore > storage.highScore) {
+ storage.highScore = currentScore;
+ }
+}
+function unlockAchievement(achievementKey) {
+ achievements[achievementKey].unlocked = true;
+ if (!storage.achievements) storage.achievements = {};
+ storage.achievements[achievementKey] = true;
+ // Show achievement notification
+ showAchievementNotification(achievements[achievementKey]);
+ LK.effects.flashScreen(0xFFD700, 500);
+}
+function showAchievementNotification(achievement) {
+ var achievementText = new Text2('Achievement Unlocked!\n' + achievement.name, {
+ size: 60,
+ fill: 0xFFD700
+ });
+ achievementText.anchor.set(0.5, 0.5);
+ achievementText.x = 1024;
+ achievementText.y = 800;
+ game.addChild(achievementText);
+ tween(achievementText, {
+ alpha: 0,
+ y: achievementText.y - 100
+ }, {
+ duration: 3000,
+ onFinish: function onFinish() {
+ achievementText.destroy();
+ }
+ });
+}
+function spawnPowerTile() {
+ var powerTypes = ['double', 'slow', 'shield'];
+ var powerType = powerTypes[Math.floor(Math.random() * powerTypes.length)];
+ var laneIndex = Math.floor(Math.random() * 4);
+ var powerTile = new PowerTile(laneIndex, powerType);
+ powerTile.x = 256 + laneIndex * 512;
+ powerTile.y = -100;
+ powerTiles.push(powerTile);
+ game.addChild(powerTile);
+}
+function activatePowerUp(powerType) {
+ if (powerType === 'double') {
+ activePowerUps.doubleScore = 600; // 10 seconds at 60fps
+ showPowerUpNotification('Double Score!', 0xFFD700);
+ } else if (powerType === 'slow') {
+ activePowerUps.slowTime = 600;
+ showPowerUpNotification('Slow Time!', 0x00FFFF);
+ } else if (powerType === 'shield') {
+ activePowerUps.shield = 600;
+ showPowerUpNotification('Shield Active!', 0x00FF00);
+ }
+}
+function showPowerUpNotification(text, color) {
+ var powerText = new Text2(text, {
+ size: 80,
+ fill: color
+ });
+ powerText.anchor.set(0.5, 0.5);
+ powerText.x = 1024;
+ powerText.y = 1000;
+ game.addChild(powerText);
+ tween(powerText, {
+ alpha: 0,
+ scaleX: 1.5,
+ scaleY: 1.5,
+ y: powerText.y - 100
+ }, {
+ duration: 2000,
+ onFinish: function onFinish() {
+ powerText.destroy();
+ }
+ });
+}
function getLaneFromX(x) {
if (x < 512) return 0;
if (x < 1024) return 1;
if (x < 1536) return 2;
@@ -331,8 +542,36 @@
easing: tween.easeOut
});
// Check for tile hits
var hitTile = false;
+ // Check power tiles first
+ for (var i = 0; i < powerTiles.length; i++) {
+ var powerTile = powerTiles[i];
+ if (powerTile.lane === laneIndex && !powerTile.missed && !powerTile.earlyPressed) {
+ var distance = Math.abs(powerTile.y - hitLineY);
+ if (distance <= 80 && !powerTile.hit) {
+ powerTile.hit = true;
+ activatePowerUp(powerTile.powerType);
+ createParticles(powerTile.x, powerTile.y, 12, 0xFFD700);
+ tween(powerTile, {
+ alpha: 0,
+ scaleX: 2,
+ scaleY: 2
+ }, {
+ duration: 300,
+ onFinish: function onFinish() {
+ if (!powerTile.destroyed) {
+ powerTile.destroyed = true;
+ powerTile.destroy();
+ }
+ }
+ });
+ hitTile = true;
+ break;
+ }
+ }
+ }
+ // Check regular tiles
for (var i = 0; i < tiles.length; i++) {
var tile = tiles[i];
if (tile.lane === laneIndex && !tile.missed && !tile.earlyPressed) {
var distance = Math.abs(tile.y - hitLineY);
@@ -342,8 +581,12 @@
tile.hit = true;
// Calculate combo multiplier
comboMultiplier = Math.min(4, Math.floor(comboCount / 5) + 1);
var baseScore = 10;
+ // Apply power-up bonuses
+ if (activePowerUps.doubleScore > 0) {
+ baseScore *= 2;
+ }
var scoreToAdd = baseScore * comboMultiplier;
// Check for perfect timing (within 20 pixels)
var perfectTiming = distance <= 20;
if (perfectTiming) {
@@ -437,13 +680,39 @@
};
// Start background music
LK.playMusic('Music');
game.update = function () {
+ // Update power-ups
+ for (var powerType in activePowerUps) {
+ if (activePowerUps[powerType] > 0) {
+ activePowerUps[powerType]--;
+ }
+ }
+ // Apply slow time effect
+ var currentGameSpeed = gameSpeed;
+ if (activePowerUps.slowTime > 0) {
+ currentGameSpeed *= 0.5;
+ }
// Spawn tiles
tileSpawnTimer++;
- if (tileSpawnTimer >= tileSpawnInterval) {
+ var adjustedSpawnInterval = tileSpawnInterval;
+ if (activePowerUps.slowTime > 0) {
+ adjustedSpawnInterval *= 2;
+ }
+ if (tileSpawnTimer >= adjustedSpawnInterval) {
spawnTile();
tileSpawnTimer = 0;
+ // Level progression system
+ var targetScore = currentLevel * 1000;
+ if (LK.getScore() >= targetScore) {
+ currentLevel++;
+ storage.currentLevel = currentLevel;
+ if (currentLevel > storage.unlockedLevels) {
+ storage.unlockedLevels = currentLevel;
+ }
+ showPowerUpNotification('Level Up! Level ' + currentLevel, 0xFF00FF);
+ LK.effects.flashScreen(0xFF00FF, 800);
+ }
// Increase difficulty over time
if (LK.ticks % 300 === 0) {
gameSpeed += 0.15;
tileSpawnInterval = Math.max(25, tileSpawnInterval - 1);
@@ -461,14 +730,37 @@
tile.destroy();
tiles.splice(i, 1);
}
}
+ // Clean up power tiles
+ for (var i = powerTiles.length - 1; i >= 0; i--) {
+ var powerTile = powerTiles[i];
+ if (!powerTile || powerTile.destroyed) {
+ powerTiles.splice(i, 1);
+ continue;
+ }
+ if (powerTile.y > 2800 || powerTile.hit || powerTile.missed && powerTile.y > hitLineY + 200) {
+ powerTile.destroyed = true;
+ powerTile.destroy();
+ powerTiles.splice(i, 1);
+ }
+ }
// Update tile speeds based on game speed
+ var effectiveSpeed = gameSpeed;
+ if (activePowerUps.slowTime > 0) {
+ effectiveSpeed *= 0.5;
+ }
for (var i = 0; i < tiles.length; i++) {
if (tiles[i] && !tiles[i].destroyed) {
- tiles[i].speed = 12 * gameSpeed;
+ tiles[i].speed = 12 * effectiveSpeed;
}
}
+ // Update power tile speeds
+ for (var i = 0; i < powerTiles.length; i++) {
+ if (powerTiles[i] && !powerTiles[i].destroyed) {
+ powerTiles[i].speed = 12 * effectiveSpeed;
+ }
+ }
// Update particles
for (var i = particles.length - 1; i >= 0; i--) {
var particle = particles[i];
if (!particle || particle.life <= 0) {
@@ -482,5 +774,20 @@
comboMultiplier = Math.min(4, Math.floor(comboCount / 5) + 1);
updateScoreDisplay();
lastHitTime = LK.ticks; // Reset timer to prevent rapid decay
}
+};
+// Override game over to save progress and unlock achievements
+var originalShowGameOver = LK.showGameOver;
+LK.showGameOver = function () {
+ // Save game stats
+ storage.totalGamesPlayed++;
+ if (LK.getScore() > storage.highScore) {
+ storage.highScore = LK.getScore();
+ }
+ // Unlock first win achievement if it's the first game
+ if (storage.totalGamesPlayed === 1 && !achievements.firstWin.unlocked) {
+ unlockAchievement('firstWin');
+ }
+ // Call original game over
+ originalShowGameOver();
};
\ No newline at end of file
A line. In-Game asset. 2d. High contrast. No shadows
A "single" tile of musical note 🎵. In-Game asset. 2d. High contrast. No shadows
A single tile of musical note 🎵 blue. In-Game asset. 2d. High contrast. No shadows
A single tile of musical note green. In-Game asset. 2d. High contrast. No shadows
A single musical tile red. In-Game asset. 2d. High contrast. No shadows
An UI written "NICE". In-Game asset. 2d. High contrast. No shadows
An UI written "Missed". In-Game asset. 2d. High contrast. No shadows
An UI written "Early". In-Game asset. 2d. High contrast. No shadows
A score display written +10 on it. In-Game asset. 2d. High contrast. No shadows
A score Ui that written -30 on it. In-Game asset. 2d. High contrast. No shadows
An image of "Perfect" Written on it. In-Game asset. 2d. High contrast. No shadows