User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'currentLeaderboard[currentLeaderboard.length] = {' Line Number: 659 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'currentLeaderboard[currentLeaderboard.length] = {' Line Number: 654 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'currentLeaderboard.push({' Line Number: 652 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'storage.leaderboard.push(newEntry);' Line Number: 657 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'storage.leaderboard.push(newEntry);' Line Number: 656. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Has una tabla de clasificación de todas las personas que juegene el juego. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Has que cuando la barra este llena pase de nivel cada vez mas dificil pero si no no pasara de nivel ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Has que cada vez se ponga las flechas mas rapidas y has que el juego sea mas divertido. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Has que todas las flecha tenga la misma velocidad y has que el juego sea mas animado las flechas y que sea mas adictivo. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Quita ese boton de estar y ponlo que cuando se pulse la pantalla empieze la cuenta regresiva.
User prompt
Quita el boton de opciones has el juego mas animado quiero que este juego sea el top 1. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
añadir en el menu un sistema de opciones de subir y bajar el volumen y cosas como bajar los gráficos del juego, etc. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Cuando se pulse el boton de settingg se ponga el menu de opciones. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Sigue empezando arreglalo has el boton mas grande o pon para empieze la partida se pulse un voton en vez de la pantalla.
User prompt
Y porque sigue empezando
User prompt
¡¡Cuando se pulse el boton de opciones no debe de empezarse el juego!!
User prompt
Cuando se pulse se ponen las opciones que te dije. ↪💡 Consider importing and using the following plugins: @upit/tween.v1, @upit/storage.v1
User prompt
Pon el boton mas abajo.
User prompt
Pon el boton de ajustes que se vea en la pantalla y que vaya ocultando cuando empieze el juego. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Añade al juego lo que tu quiera añade en el menu un sistema de opciones de subir y bajar el volumen y cosas como bajar los graficos del juego etc. ↪💡 Consider importing and using the following plugins: @upit/storage.v1, @upit/tween.v1
User prompt
Has que el juego sea mas divertido ponle lo que tu quieras. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Quita la particulas amarillas y azulas solo ponle major diversion al juego.
User prompt
Y el good perfect. has un sistema de combos y animaciones. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Mejora las anumaciones de good, perfect etc tambien has un poco mas pequeños los botones para que no se peguen añade cometas al fondo y has una pantalla de carga cuan se pulse pañsar para reintentar en el game over para poner el titulo de nuevo. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Esta bien pero agrega mas decoracion en el fondo como cochetes ocnnis etc. Mejora el sistema de miss de se pone fondo rojo quitalo y has una animacion de miss mejora los combos con animaciones etc ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
masterVolume: 0.7,
musicVolume: 0.8,
sfxVolume: 0.8,
graphicsQuality: "high",
leaderboard: [],
playerName: "Player"
});
/****
* Classes
****/
var Arrow = Container.expand(function (direction, column) {
var self = Container.call(this);
var arrowGraphic = self.attachAsset('arrow_' + direction, {
anchorX: 0.5,
anchorY: 0.5
});
self.direction = direction;
self.column = column;
// Calculate dynamic speed based on current level and speed multiplier
var currentSpeed = baseSpeed * speedMultiplier;
self.speed = Math.min(currentSpeed, baseSpeed * maxSpeedMultiplier); // Apply speed cap
self.hitTested = false;
self.animationPhase = Math.random() * Math.PI * 2; // Random phase for animations
self.pulseSpeed = 0.8 + Math.random() * 0.4; // Random pulse speed
self.glowIntensity = 0.3 + Math.random() * 0.7; // Random glow intensity
self.sparkleTimer = Math.random() * 60; // Random sparkle timing
// Add initial entrance animation
arrowGraphic.scaleX = 0.1;
arrowGraphic.scaleY = 0.1;
arrowGraphic.alpha = 0.5;
tween(arrowGraphic, {
scaleX: 1,
scaleY: 1,
alpha: 1
}, {
duration: 300,
easing: tween.bounceOut
});
self.update = function () {
self.y += self.speed;
// Add dynamic pulsing animation
self.animationPhase += self.pulseSpeed * 0.1;
arrowGraphic.scaleX = 1 + 0.1 * Math.sin(self.animationPhase);
arrowGraphic.scaleY = 1 + 0.1 * Math.sin(self.animationPhase + 1);
// Add rotation wobble
arrowGraphic.rotation = 0.1 * Math.sin(self.animationPhase * 0.7);
// Add glow effect
arrowGraphic.alpha = 0.8 + 0.2 * Math.sin(self.animationPhase * 1.5);
// Add sparkle effect periodically
self.sparkleTimer++;
if (self.sparkleTimer >= 30) {
self.sparkleTimer = 0;
var sparkle = LK.getAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0.8
});
sparkle.x = self.x + (Math.random() - 0.5) * 60;
sparkle.y = self.y + (Math.random() - 0.5) * 60;
sparkle.tint = self.direction === 'left' ? 0xff4757 : self.direction === 'down' ? 0x5352ed : self.direction === 'up' ? 0x2ed573 : 0xffa502;
game.addChild(sparkle);
tween(sparkle, {
scaleX: 0.3,
scaleY: 0.3,
alpha: 0,
y: sparkle.y - 50
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
sparkle.destroy();
}
});
}
};
return self;
});
var ComboEffect = Container.expand(function (x, y, comboValue) {
var self = Container.call(this);
// Create combo burst effect
var comboText = new Text2(comboValue + 'x COMBO!', {
size: 80,
fill: 0xFFD700
});
comboText.anchor.set(0.5, 0.5);
comboText.x = 0;
comboText.y = 0;
comboText.scaleX = 0.1;
comboText.scaleY = 0.1;
comboText.alpha = 1;
self.addChild(comboText);
// Create sparkle effects around combo text
for (var i = 0; i < 8; i++) {
var sparkle = self.addChild(LK.getAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0.8
}));
var angle = i / 8 * Math.PI * 2;
var radius = 80;
sparkle.x = Math.cos(angle) * radius;
sparkle.y = Math.sin(angle) * radius;
sparkle.tint = 0xFFD700;
// Animate sparkles
tween(sparkle, {
scaleX: 0.3,
scaleY: 0.3,
alpha: 0,
x: Math.cos(angle) * (radius + 100),
y: Math.sin(angle) * (radius + 100)
}, {
duration: 1000,
easing: tween.easeOut
});
}
self.x = x;
self.y = y;
// Animate combo text
tween(comboText, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(comboText, {
scaleX: 0.8,
scaleY: 0.8,
alpha: 0,
y: -50
}, {
duration: 700,
easing: tween.easeOut
});
}
});
// Destroy after animation
LK.setTimeout(function () {
self.destroy();
}, 1200);
return self;
});
var HitEffect = Container.expand(function (x, y) {
var self = Container.call(this);
var effectGraphic = self.attachAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
alpha: 0.8
});
self.x = x;
self.y = y;
// Animate the effect
tween(effectGraphic, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
return self;
});
var MissEffect = Container.expand(function (x, y) {
var self = Container.call(this);
// Create multiple miss text elements that animate outward
var missTexts = [];
var directions = [{
x: -1,
y: -1
}, {
x: 1,
y: -1
}, {
x: -1,
y: 1
}, {
x: 1,
y: 1
}, {
x: 0,
y: -1
}, {
x: 0,
y: 1
}, {
x: -1,
y: 0
}, {
x: 1,
y: 0
}];
for (var i = 0; i < 4; i++) {
var missText = new Text2('MISS', {
size: 60 + Math.random() * 40,
fill: 0xFF3333
});
missText.anchor.set(0.5, 0.5);
missText.x = 0;
missText.y = 0;
missText.alpha = 0.9;
self.addChild(missText);
missTexts.push(missText);
}
self.x = x;
self.y = y;
// Animate miss texts flying outward
for (var i = 0; i < missTexts.length; i++) {
var text = missTexts[i];
var dir = directions[i % directions.length];
var distance = 150 + Math.random() * 100;
tween(text, {
x: dir.x * distance,
y: dir.y * distance,
alpha: 0,
rotation: (Math.random() - 0.5) * Math.PI,
scaleX: 0.3,
scaleY: 0.3
}, {
duration: 800,
easing: tween.easeOut
});
}
// Destroy after animation
LK.setTimeout(function () {
self.destroy();
}, 900);
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c2c54
});
/****
* Game Code
****/
// Game constants
var COLUMN_COUNT = 4;
var COLUMN_WIDTH = 2048 / COLUMN_COUNT;
var TARGET_Y = 2400;
var SPAWN_Y = -100;
var HIT_ZONE_HEIGHT = 80;
// Game state
var arrows = [];
var score = 0;
var combo = 0;
var missCount = 0;
var maxMisses = 10;
var gameStarted = false;
var gameState = 'start'; // 'start', 'countdown', 'playing', 'gameover'
var countdownValue = 3;
var countdownTimer = 0;
var arrowSpawnTimer = 0;
var spawnInterval = 45; // frames between arrow spawns
// Health bar system
var healthBar = 50; // Current health (0-100)
var maxHealth = 100;
var healthPerHit = 15; // Health gained per successful hit (increased)
var healthPerMiss = 8; // Health lost per miss (reduced for fairness)
var currentLevelHits = 0; // Current hits in this level (tracking for statistics)
// Level system with progressive speed increases
var level = 1;
var baseSpeed = 8;
var baseSpawnInterval = 45;
var speedMultiplier = 1.0; // Speed multiplier that increases with level
var maxSpeedMultiplier = 3.0; // Maximum speed cap for balance
var scoresPerLevel = [0, 1000, 2500, 5000, 8000, 12000, 17000, 23000, 30000, 40000];
// Direction mapping
var directions = ['left', 'down', 'up', 'right'];
var columnPositions = [];
// Calculate column positions
for (var i = 0; i < COLUMN_COUNT; i++) {
columnPositions.push(COLUMN_WIDTH * i + COLUMN_WIDTH / 2);
}
// Create target zones
var targetZones = [];
for (var i = 0; i < COLUMN_COUNT; i++) {
var targetZone = game.addChild(LK.getAsset('target_zone', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
}));
targetZone.x = columnPositions[i];
targetZone.y = TARGET_Y;
targetZones.push(targetZone);
// Add enhanced pulsing animation to target zones with particle effects
tween(targetZone, {
scaleX: 1.2,
scaleY: 1.2,
alpha: 0.6
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(targetZone, {
scaleX: 0.9,
scaleY: 0.9,
alpha: 0.2
}, {
duration: 800,
easing: tween.easeInOut
});
}
});
// Add floating particles around target zone
LK.setTimeout(function () {
for (var p = 0; p < 4; p++) {
var particle = game.addChild(LK.getAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.05,
scaleY: 0.05,
alpha: 0.8
}));
var angle = p / 4 * Math.PI * 2;
var radius = 80;
particle.x = targetZone.x + Math.cos(angle) * radius;
particle.y = targetZone.y + Math.sin(angle) * radius;
particle.tint = i === 0 ? 0xff4757 : i === 1 ? 0x5352ed : i === 2 ? 0x2ed573 : 0xffa502;
tween(particle, {
scaleX: 0.15,
scaleY: 0.15,
alpha: 0,
x: targetZone.x + Math.cos(angle) * (radius + 60),
y: targetZone.y + Math.sin(angle) * (radius + 60)
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
}
});
}
}, Math.random() * 1000);
}
// Create control zones at bottom of screen
var controlZones = [];
// Position control zones at the very bottom for better mobile reach
var controlZoneY = TARGET_Y + 200; // Moved even further down
// Make the control zones smaller to prevent overlapping but still comfortable for mobile
var controlZoneWidth = COLUMN_WIDTH * 0.9;
var controlZoneHeight = 350; // Reduced height to prevent button overlap
for (var i = 0; i < COLUMN_COUNT; i++) {
var controlZone = game.addChild(LK.getAsset('target_zone', {
anchorX: 0.5,
anchorY: 0.5,
// Slightly visible for better feedback
alpha: 0.15,
width: controlZoneWidth,
height: controlZoneHeight
}));
controlZone.x = columnPositions[i];
controlZone.y = controlZoneY;
controlZone.columnIndex = i;
// Color coding for visual feedback
controlZone.tint = i === 0 ? 0xff4757 : i === 1 ? 0x5352ed : i === 2 ? 0x2ed573 : 0xffa502;
controlZones.push(controlZone);
}
// Add decorative background elements
var rockets = [];
var confetti = [];
var comets = [];
// Create rocket decorations
for (var i = 0; i < 8; i++) {
var rocket = game.addChild(LK.getAsset('arrow_up', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.8,
alpha: 0.15
}));
rocket.x = Math.random() * 2048;
rocket.y = Math.random() * 2732;
rocket.speed = 1 + Math.random() * 2;
rocket.tint = Math.random() > 0.5 ? 0xFF6B6B : 0x4ECDC4;
rockets.push(rocket);
}
// Create confetti pieces with enhanced colors
for (var i = 0; i < 25; i++) {
var confettiPiece = game.addChild(LK.getAsset('target_zone', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0.2
}));
confettiPiece.x = Math.random() * 2048;
confettiPiece.y = Math.random() * 2732;
confettiPiece.speed = 0.3 + Math.random() * 1;
confettiPiece.rotationSpeed = (Math.random() - 0.5) * 0.1;
var colors = [0xFF6B6B, 0xF9CA24, 0xF0932B, 0xEB4D4B, 0x6C5CE7, 0xFF00FF, 0x00FF00];
confettiPiece.tint = colors[Math.floor(Math.random() * colors.length)];
confetti.push(confettiPiece);
}
// Create comet decorations
for (var i = 0; i < 6; i++) {
var comet = game.addChild(LK.getAsset('arrow_right', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.2,
alpha: 0.25
}));
comet.x = Math.random() * 2048;
comet.y = Math.random() * 2732;
comet.speed = 2 + Math.random() * 3;
comet.rotation = Math.random() * Math.PI * 2;
comet.tint = Math.random() > 0.5 ? 0x00FFFF : 0xFFFFFF;
comets.push(comet);
}
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = 50;
scoreTxt.y = 50;
LK.gui.topLeft.addChild(scoreTxt);
var comboTxt = new Text2('Combo: 0', {
size: 50,
fill: 0xFFD700
});
comboTxt.anchor.set(0.5, 0);
comboTxt.x = 0;
comboTxt.y = 120;
LK.gui.top.addChild(comboTxt);
var levelTxt = new Text2('Level: 1', {
size: 50,
fill: 0xFF6B6B
});
levelTxt.anchor.set(1, 0);
levelTxt.x = -50;
levelTxt.y = 50;
LK.gui.topRight.addChild(levelTxt);
// Health bar UI with improved visuals
var healthBarBg = LK.getAsset('target_zone', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 0.8,
alpha: 0.6
});
healthBarBg.tint = 0x333333;
healthBarBg.x = 0;
healthBarBg.y = 150;
LK.gui.top.addChild(healthBarBg);
var healthBarBorder = LK.getAsset('target_zone', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4.2,
scaleY: 1,
alpha: 0.8
});
healthBarBorder.tint = 0xFFFFFF;
healthBarBorder.x = 0;
healthBarBorder.y = 150;
LK.gui.top.addChild(healthBarBorder);
var healthBarFill = LK.getAsset('target_zone', {
anchorX: 0,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.6
});
healthBarFill.tint = 0x00FF88;
healthBarFill.x = -280;
healthBarFill.y = 150;
LK.gui.top.addChild(healthBarFill);
var healthTxt = new Text2('FILL TO LEVEL UP', {
size: 45,
fill: 0xFFFFFF
});
healthTxt.anchor.set(0.5, 0.5);
healthTxt.x = 0;
healthTxt.y = 200;
LK.gui.top.addChild(healthTxt);
var accuracyTxt = new Text2('', {
size: 80,
fill: 0xFFFFFF
});
accuracyTxt.anchor.set(0.5, 0.5);
accuracyTxt.x = 0;
accuracyTxt.y = -200;
accuracyTxt.alpha = 0;
LK.gui.center.addChild(accuracyTxt);
// Start screen elements
var startTxt = new Text2('TAP TO START', {
size: 100,
fill: 0xFFFFFF
});
startTxt.anchor.set(0.5, 0.5);
startTxt.x = 0;
startTxt.y = 0;
LK.gui.center.addChild(startTxt);
var titleTxt = new Text2('RHYTHM ARROWS', {
size: 120,
fill: 0x00FFFF
});
titleTxt.anchor.set(0.5, 0.5);
titleTxt.x = 0;
titleTxt.y = -300;
LK.gui.center.addChild(titleTxt);
var subtitleTxt = new Text2('Hit the arrows in rhythm!', {
size: 50,
fill: 0xFFD700
});
subtitleTxt.anchor.set(0.5, 0.5);
subtitleTxt.x = 0;
subtitleTxt.y = 100;
LK.gui.center.addChild(subtitleTxt);
var countdownTxt = new Text2('3', {
size: 200,
fill: 0xFFD700
});
countdownTxt.anchor.set(0.5, 0.5);
countdownTxt.x = 0;
countdownTxt.y = 0;
countdownTxt.alpha = 0;
LK.gui.center.addChild(countdownTxt);
// Game over screen elements
var gameOverTxt = new Text2('GAME OVER', {
size: 100,
fill: 0xFF0000
});
gameOverTxt.anchor.set(0.5, 0.5);
gameOverTxt.x = 0;
gameOverTxt.y = -200;
gameOverTxt.alpha = 0;
LK.gui.center.addChild(gameOverTxt);
var finalComboTxt = new Text2('', {
size: 60,
fill: 0xFFD700
});
finalComboTxt.anchor.set(0.5, 0.5);
finalComboTxt.x = 0;
finalComboTxt.y = -100;
finalComboTxt.alpha = 0;
LK.gui.center.addChild(finalComboTxt);
var finalMissTxt = new Text2('', {
size: 60,
fill: 0xFF6B6B
});
finalMissTxt.anchor.set(0.5, 0.5);
finalMissTxt.x = 0;
finalMissTxt.y = -40;
finalMissTxt.alpha = 0;
LK.gui.center.addChild(finalMissTxt);
var restartTxt = new Text2('TAP TO PLAY AGAIN', {
size: 80,
fill: 0x00FFFF
});
restartTxt.anchor.set(0.5, 0.5);
restartTxt.x = 0;
restartTxt.y = 100;
restartTxt.alpha = 0;
LK.gui.center.addChild(restartTxt);
// Loading screen elements
var loadingTxt = new Text2('LOADING...', {
size: 80,
fill: 0x00FFFF
});
loadingTxt.anchor.set(0.5, 0.5);
loadingTxt.x = 0;
loadingTxt.y = 0;
loadingTxt.alpha = 0;
LK.gui.center.addChild(loadingTxt);
var loadingBar = LK.getAsset('target_zone', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0,
scaleY: 0.5,
alpha: 0
});
loadingBar.tint = 0x00FFFF;
loadingBar.x = 0;
loadingBar.y = 100;
LK.gui.center.addChild(loadingBar);
// Leaderboard UI elements
var leaderboardTxt = new Text2('LEADERBOARD', {
size: 80,
fill: 0xFFD700
});
leaderboardTxt.anchor.set(0.5, 0.5);
leaderboardTxt.x = 0;
leaderboardTxt.y = -350;
leaderboardTxt.alpha = 0;
LK.gui.center.addChild(leaderboardTxt);
var leaderboardEntries = [];
for (var i = 0; i < 5; i++) {
var entryTxt = new Text2('', {
size: 50,
fill: 0xFFFFFF
});
entryTxt.anchor.set(0.5, 0.5);
entryTxt.x = 0;
entryTxt.y = -250 + i * 60;
entryTxt.alpha = 0;
LK.gui.center.addChild(entryTxt);
leaderboardEntries.push(entryTxt);
}
var newRecordTxt = new Text2('NEW RECORD!', {
size: 90,
fill: 0xFFD700
});
newRecordTxt.anchor.set(0.5, 0.5);
newRecordTxt.x = 0;
newRecordTxt.y = -300;
newRecordTxt.alpha = 0;
LK.gui.center.addChild(newRecordTxt);
// Leaderboard Functions
function addScoreToLeaderboard(playerScore, playerLevel, playerCombo) {
// Initialize leaderboard if it doesn't exist
if (!storage.leaderboard) {
storage.leaderboard = [];
}
// Create a simple date string using only literal operations
var now = new Date();
var dateString = now.getMonth() + 1 + '/' + now.getDate() + '/' + now.getFullYear();
// Get current leaderboard
var currentLeaderboard = storage.leaderboard;
// Add new entry using only literal values - avoid object creation in push
currentLeaderboard[currentLeaderboard.length] = {
score: playerScore,
level: playerLevel,
combo: playerCombo,
date: dateString
};
// Update storage with the modified array
storage.leaderboard = currentLeaderboard;
// Sort by score (highest first)
storage.leaderboard.sort(function (a, b) {
return b.score - a.score;
});
// Keep only top 10 scores
if (storage.leaderboard.length > 10) {
storage.leaderboard = storage.leaderboard.slice(0, 10);
}
// Check if this is a new record (top score)
return storage.leaderboard[0].score === playerScore;
}
function displayLeaderboard() {
// Show leaderboard title
leaderboardTxt.alpha = 1;
tween(leaderboardTxt, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(leaderboardTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
}
});
// Display top 5 scores
for (var i = 0; i < Math.min(5, storage.leaderboard.length); i++) {
var entry = storage.leaderboard[i];
var entryText = i + 1 + '. Score: ' + entry.score + ' (Lv.' + entry.level + ')';
leaderboardEntries[i].setText(entryText);
leaderboardEntries[i].alpha = 0;
// Animate each entry with delay
(function (index, entryElement) {
LK.setTimeout(function () {
tween(entryElement, {
alpha: 1,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(entryElement, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
}
});
}, index * 200);
})(i, leaderboardEntries[i]);
}
// Hide unused entries
for (var i = storage.leaderboard.length; i < 5; i++) {
leaderboardEntries[i].alpha = 0;
}
}
function hideLeaderboard() {
// Hide all leaderboard elements
tween(leaderboardTxt, {
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
for (var i = 0; i < leaderboardEntries.length; i++) {
tween(leaderboardEntries[i], {
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
}
tween(newRecordTxt, {
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
}
// Functions
function spawnArrow() {
var column = Math.floor(Math.random() * COLUMN_COUNT);
var direction = directions[column];
var arrow = new Arrow(direction, column);
arrow.x = columnPositions[column];
arrow.y = SPAWN_Y;
arrows.push(arrow);
game.addChild(arrow);
// Add enhanced entrance trail effect based on speed level
var trailCount = Math.min(5, 3 + Math.floor(speedMultiplier));
for (var t = 0; t < trailCount; t++) {
var trail = game.addChild(LK.getAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2 + speedMultiplier * 0.1,
scaleY: 0.2 + speedMultiplier * 0.1,
alpha: 0.6 + speedMultiplier * 0.2
}));
trail.x = arrow.x + (Math.random() - 0.5) * (40 + speedMultiplier * 10);
trail.y = arrow.y - t * (30 + speedMultiplier * 5);
trail.tint = direction === 'left' ? 0xff4757 : direction === 'down' ? 0x5352ed : direction === 'up' ? 0x2ed573 : 0xffa502;
// Add intensity glow for higher speeds
if (speedMultiplier > 1.5) {
trail.tint = 0xFFFFFF; // White hot trail for high speeds
}
var trailDuration = Math.max(400, 600 - speedMultiplier * 50);
tween(trail, {
scaleX: 0.05,
scaleY: 0.05,
alpha: 0,
y: trail.y + (100 + speedMultiplier * 20)
}, {
duration: trailDuration,
easing: tween.easeOut,
onFinish: function onFinish() {
trail.destroy();
}
});
}
// Add entrance burst effect
var burst = game.addChild(LK.getAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 1
}));
burst.x = arrow.x;
burst.y = arrow.y;
burst.tint = 0xFFFFFF;
tween(burst, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
burst.destroy();
}
});
}
function checkHit(arrow) {
var distance = Math.abs(arrow.y - TARGET_Y);
if (distance <= HIT_ZONE_HEIGHT * 0.8) {
// Perfect hit - more generous perfect zone
return 'perfect';
} else if (distance <= HIT_ZONE_HEIGHT * 3) {
// Good hit - much more generous good zone
return 'good';
}
return null;
}
function processHit(arrow, accuracy) {
var points = 0;
var comboMultiplier = Math.floor(combo / 10) + 1;
if (accuracy === 'perfect') {
points = 100 * comboMultiplier;
var perfectSound = LK.getSound('hit_perfect');
perfectSound.volume = storage.masterVolume * storage.sfxVolume;
perfectSound.play();
showAccuracyText('PERFECT!', 0x00ff00);
// Extra effect for perfect hits
LK.effects.flashScreen(0x00ff00, 100);
} else if (accuracy === 'good') {
points = 50 * comboMultiplier;
var goodSound = LK.getSound('hit_good');
goodSound.volume = storage.masterVolume * storage.sfxVolume;
goodSound.play();
showAccuracyText('GOOD', 0xffff00);
}
score += points;
combo++;
// Increase health bar
healthBar = Math.min(maxHealth, healthBar + healthPerHit);
currentLevelHits++;
// Check if health bar is full to advance to next level
if (healthBar >= maxHealth) {
level++;
currentLevelHits = 0;
// Reset health bar to starting level for next challenge
healthBar = 50;
// Increase speed multiplier progressively with each level
speedMultiplier = Math.min(1.0 + (level - 1) * 0.15, maxSpeedMultiplier);
// Slightly reduce spawn interval for more challenge but keep it balanced
spawnInterval = Math.max(25, baseSpawnInterval - Math.floor((level - 1) * 1.2));
// Show enhanced level up effect with speed notification
showAccuracyText('LEVEL ' + level + '! HEALTH FULL!', 0x00ffff);
LK.effects.flashScreen(0x00ffff, 700);
// Add speed burst visual effect
tween(game, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 200,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(game, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 300,
easing: tween.easeOut
});
}
});
}
// Create multiple hit effects for high combos
var effectCount = Math.min(3, Math.floor(combo / 25) + 1);
for (var i = 0; i < effectCount; i++) {
LK.setTimeout(function () {
var effect = new HitEffect(arrow.x + (Math.random() - 0.5) * 50, arrow.y + (Math.random() - 0.5) * 50);
game.addChild(effect);
}, i * 50);
}
// Enhanced combo system with multiple milestone effects
if (combo % 5 === 0 && combo > 0) {
// Create spectacular combo effect
var comboEffect = new ComboEffect(arrow.x, arrow.y - 100, combo);
game.addChild(comboEffect);
// Different effects based on combo milestones
if (combo >= 100) {
// LEGENDARY combo (100+)
LK.effects.flashScreen(0xFFD700, 800);
tween(comboTxt, {
scaleX: 3,
scaleY: 3,
tint: 0xFFD700,
rotation: 0.5
}, {
duration: 500,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFD700,
rotation: 0
}, {
duration: 600,
easing: tween.easeOut
});
}
});
} else if (combo >= 50) {
// EPIC combo (50+)
LK.effects.flashScreen(0xFF6B6B, 500);
tween(comboTxt, {
scaleX: 2.5,
scaleY: 2.5,
tint: 0xFF6B6B,
rotation: 0.3
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xFFD700,
rotation: 0
}, {
duration: 500,
easing: tween.easeOut
});
}
});
} else if (combo >= 25) {
// SUPER combo (25+)
LK.effects.flashScreen(0x4ECDC4, 300);
tween(comboTxt, {
scaleX: 2.2,
scaleY: 2.2,
tint: 0x4ECDC4
}, {
duration: 350,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1.2,
scaleY: 1.2,
tint: 0xFFD700
}, {
duration: 450,
easing: tween.easeOut
});
}
});
} else {
// Regular combo milestone (5, 10, 15, 20)
tween(comboTxt, {
scaleX: 2,
scaleY: 2,
tint: 0x00FFFF
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1,
scaleY: 1,
tint: 0xFFD700
}, {
duration: 400,
easing: tween.easeOut
});
}
});
}
// Create confetti burst for high combos
if (combo >= 25) {
var confettiCount = Math.min(30, combo / 2);
for (var c = 0; c < confettiCount; c++) {
LK.setTimeout(function () {
var burstConfetti = game.addChild(LK.getAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.15,
scaleY: 0.15,
alpha: 0.9
}));
burstConfetti.x = arrow.x + (Math.random() - 0.5) * 300;
burstConfetti.y = arrow.y + (Math.random() - 0.5) * 300;
var colors = [0xFF6B6B, 0x4ECDC4, 0x45B7D1, 0xF9CA24, 0xF0932B, 0xFFD700, 0x00FFFF];
burstConfetti.tint = colors[Math.floor(Math.random() * colors.length)];
tween(burstConfetti, {
y: burstConfetti.y - 400,
x: burstConfetti.x + (Math.random() - 0.5) * 200,
alpha: 0,
rotation: Math.random() * Math.PI * 4,
scaleX: 0.02,
scaleY: 0.02
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
burstConfetti.destroy();
}
});
}, c * 20);
}
}
// Create firework effect for mega combos
if (combo >= 75) {
for (var f = 0; f < 5; f++) {
var firework = game.addChild(LK.getAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 1
}));
firework.x = arrow.x + (Math.random() - 0.5) * 400;
firework.y = arrow.y + (Math.random() - 0.5) * 200;
firework.tint = 0xFFFFFF;
tween(firework, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
firework.destroy();
}
});
}
}
}
// Remove arrow
arrow.destroy();
var arrowIndex = arrows.indexOf(arrow);
if (arrowIndex > -1) {
arrows.splice(arrowIndex, 1);
}
updateUI();
}
function processMiss() {
combo = 0;
missCount++;
var missSound = LK.getSound('miss');
missSound.volume = storage.masterVolume * storage.sfxVolume;
missSound.play();
showAccuracyText('MISS', 0xff0000);
// Create miss effect animation instead of screen flash
var missEffect = new MissEffect(1024, 1366);
game.addChild(missEffect);
// Shake the screen slightly for miss feedback
tween(game, {
x: 10
}, {
duration: 50,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(game, {
x: -10
}, {
duration: 50,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(game, {
x: 0
}, {
duration: 100,
easing: tween.easeOut
});
}
});
}
});
// Decrease health bar
healthBar = Math.max(0, healthBar - healthPerMiss);
// Check if health bar reached 0
if (healthBar <= 0) {
showGameOverScreen();
}
updateUI();
}
function showAccuracyText(text, color) {
accuracyTxt.setText(text);
accuracyTxt.fill = color;
accuracyTxt.alpha = 1;
accuracyTxt.scaleX = 0.2;
accuracyTxt.scaleY = 0.2;
accuracyTxt.rotation = 0;
// Create spectacular effects based on accuracy type
if (text === 'PERFECT!') {
// Create burst of sparkles for perfect hits
for (var s = 0; s < 12; s++) {
var sparkle = game.addChild(LK.getAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 1
}));
sparkle.x = 1024;
sparkle.y = 1366;
sparkle.tint = s % 2 === 0 ? 0x00FFFF : 0xFFD700;
var angle = s / 12 * Math.PI * 2;
var distance = 200 + Math.random() * 100;
tween(sparkle, {
x: 1024 + Math.cos(angle) * distance,
y: 1366 + Math.sin(angle) * distance,
scaleX: 0.5,
scaleY: 0.5,
alpha: 0,
rotation: Math.PI * 2
}, {
duration: 1200,
easing: tween.easeOut,
onFinish: function onFinish() {
sparkle.destroy();
}
});
}
// Enhanced perfect text animation
tween(accuracyTxt, {
scaleX: 2.5,
scaleY: 2.5,
rotation: 0.5
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(accuracyTxt, {
scaleX: 1.8,
scaleY: 1.8,
rotation: 0,
alpha: 0
}, {
duration: 1000,
easing: tween.easeOut
});
}
});
} else if (text === 'GOOD') {
// Create ring effect for good hits
for (var r = 0; r < 8; r++) {
var ring = game.addChild(LK.getAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.2,
alpha: 0.8
}));
ring.x = 1024;
ring.y = 1366;
ring.tint = 0xFFFF00;
var ringAngle = r / 8 * Math.PI * 2;
var ringDistance = 120;
tween(ring, {
x: 1024 + Math.cos(ringAngle) * ringDistance,
y: 1366 + Math.sin(ringAngle) * ringDistance,
scaleX: 0.4,
scaleY: 0.4,
alpha: 0
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
ring.destroy();
}
});
}
// Enhanced good text animation
tween(accuracyTxt, {
scaleX: 2.0,
scaleY: 2.0,
rotation: 0.2
}, {
duration: 250,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(accuracyTxt, {
scaleX: 1.2,
scaleY: 1.2,
rotation: 0,
alpha: 0
}, {
duration: 700,
easing: tween.easeOut
});
}
});
} else {
// Default animation for MISS
tween(accuracyTxt, {
scaleX: 1.5,
scaleY: 1.5,
rotation: text === 'PERFECT!' ? 0.3 : 0.1
}, {
duration: 200,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(accuracyTxt, {
scaleX: 1,
scaleY: 1,
rotation: 0,
alpha: 0
}, {
duration: 800,
easing: tween.easeOut
});
}
});
}
}
function updateUI() {
scoreTxt.setText('Score: ' + score);
comboTxt.setText('Combo: ' + combo);
levelTxt.setText('Level: ' + level);
// Update health bar with smooth animation
var healthPercent = healthBar / maxHealth;
var targetScaleX = 2 * healthPercent;
// Animate health bar changes smoothly
tween(healthBarFill, {
scaleX: targetScaleX
}, {
duration: 300,
easing: tween.easeOut
});
// Change color based on health level with smooth transitions
var targetColor;
if (healthPercent > 0.7) {
targetColor = 0x00FF88; // Bright green
} else if (healthPercent > 0.5) {
targetColor = 0x88FF00; // Yellow-green
} else if (healthPercent > 0.3) {
targetColor = 0xFFAA00; // Orange
} else {
targetColor = 0xFF3333; // Bright red
}
// Animate color change
tween(healthBarFill, {
tint: targetColor
}, {
duration: 200,
easing: tween.easeOut
});
// Pulse effect when health is critical
if (healthPercent <= 0.2) {
tween(healthBarFill, {
alpha: 0.3
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(healthBarFill, {
alpha: 1
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
}
}
function startCountdown() {
gameState = 'countdown';
startTxt.alpha = 0;
// Hide leaderboard if visible
hideLeaderboard();
// Fade out title elements
tween(titleTxt, {
alpha: 0,
y: -400
}, {
duration: 800,
easing: tween.easeOut
});
tween(subtitleTxt, {
alpha: 0,
y: 200
}, {
duration: 800,
easing: tween.easeOut
});
countdownTxt.alpha = 1;
countdownValue = 3;
countdownTimer = 0;
}
function showCountdownNumber() {
if (countdownValue > 0) {
countdownTxt.setText(countdownValue.toString());
countdownTxt.fill = countdownValue === 3 ? 0xFF0000 : countdownValue === 2 ? 0xFFA500 : 0x00FF00;
} else {
countdownTxt.setText('GO!');
countdownTxt.fill = 0x00FFFF;
}
countdownTxt.scaleX = 3;
countdownTxt.scaleY = 3;
countdownTxt.rotation = 0.5;
countdownTxt.alpha = 1;
// Animate scale down with bounce effect
tween(countdownTxt, {
scaleX: 1,
scaleY: 1,
rotation: 0
}, {
duration: 800,
easing: tween.bounceOut
});
// Animate alpha fade out after scale animation
LK.setTimeout(function () {
tween(countdownTxt, {
alpha: 0
}, {
duration: 200,
easing: tween.easeOut
});
}, 600);
}
function restartGame() {
// Show loading screen first
gameState = 'loading';
loadingTxt.alpha = 1;
loadingBar.alpha = 1;
loadingBar.scaleX = 0;
// Animate loading bar
tween(loadingBar, {
scaleX: 3
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// After loading, reset game
// Reset all game variables
score = 0;
combo = 0;
missCount = 0;
level = 1;
healthBar = 50;
currentLevelHits = 0;
arrowSpawnTimer = 0;
spawnInterval = 45;
speedMultiplier = 1.0; // Reset speed multiplier to base level
gameState = 'start';
gameStarted = false;
// Clear all arrows
for (var i = arrows.length - 1; i >= 0; i--) {
arrows[i].destroy();
}
arrows = [];
// Stop music
LK.stopMusic();
// Reset UI visibility - show title again
startTxt.alpha = 1;
titleTxt.alpha = 1; // Show title again
titleTxt.y = -300;
titleTxt.rotation = 0;
subtitleTxt.alpha = 1;
subtitleTxt.y = 100;
countdownTxt.alpha = 0;
// Properly hide all game over elements
gameOverTxt.alpha = 0;
gameOverTxt.scaleX = 1;
gameOverTxt.scaleY = 1;
finalComboTxt.alpha = 0;
finalComboTxt.y = -100;
finalMissTxt.alpha = 0;
finalMissTxt.y = -40;
restartTxt.alpha = 0;
accuracyTxt.alpha = 0;
// Stop any active tweens on game over elements
tween.stop(gameOverTxt);
tween.stop(finalComboTxt);
tween.stop(finalMissTxt);
tween.stop(restartTxt);
// Hide loading screen
loadingTxt.alpha = 0;
loadingBar.alpha = 0;
// Hide leaderboard
hideLeaderboard();
// Update UI
updateUI();
}
});
}
function showGameOverScreen() {
gameState = 'gameover';
// Add score to leaderboard and check for new record
var isNewRecord = addScoreToLeaderboard(score, level, combo);
// Flash screen with dramatic effect
LK.effects.flashScreen(0x8B0000, 1000);
// Show new record notification if applicable
if (isNewRecord) {
newRecordTxt.alpha = 0;
newRecordTxt.scaleX = 0.1;
newRecordTxt.scaleY = 0.1;
tween(newRecordTxt, {
alpha: 1,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 1000,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Add sparkle effect for new record
for (var s = 0; s < 15; s++) {
var sparkle = game.addChild(LK.getAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 1
}));
sparkle.x = 1024 + (Math.random() - 0.5) * 400;
sparkle.y = 1366 - 300 + (Math.random() - 0.5) * 100;
sparkle.tint = 0xFFD700;
var angle = Math.random() * Math.PI * 2;
tween(sparkle, {
x: sparkle.x + Math.cos(angle) * 200,
y: sparkle.y + Math.sin(angle) * 200,
scaleX: 0.4,
scaleY: 0.4,
alpha: 0,
rotation: Math.PI * 2
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
sparkle.destroy();
}
});
}
}
});
LK.effects.flashScreen(0xFFD700, 1500);
}
// Show game over elements with staggered animations
gameOverTxt.alpha = 0;
gameOverTxt.scaleX = 0.1;
gameOverTxt.scaleY = 0.1;
tween(gameOverTxt, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 800,
easing: tween.bounceOut
});
// Animate final stats with delay
LK.setTimeout(function () {
finalComboTxt.setText('Level Reached: ' + level);
finalComboTxt.alpha = 0;
finalComboTxt.y = -50;
tween(finalComboTxt, {
alpha: 1,
y: -100
}, {
duration: 600,
easing: tween.easeOut
});
}, 400);
LK.setTimeout(function () {
finalMissTxt.setText('Misses: ' + missCount);
finalMissTxt.alpha = 0;
finalMissTxt.y = 10;
tween(finalMissTxt, {
alpha: 1,
y: -40
}, {
duration: 600,
easing: tween.easeOut
});
}, 800);
// Show leaderboard after stats
LK.setTimeout(function () {
displayLeaderboard();
}, 1400);
// Remove restart text animation - keep it hidden
restartTxt.alpha = 0;
}
function handleColumnTap(columnIndex) {
// Find the closest arrow in the specified column
var closestArrow = null;
var closestDistance = Infinity;
var closestArrowIndex = -1;
for (var i = 0; i < arrows.length; i++) {
var arrow = arrows[i];
if (!arrow.hitTested && arrow.column === columnIndex) {
var distance = Math.abs(arrow.y - TARGET_Y);
if (distance < closestDistance) {
closestDistance = distance;
closestArrow = arrow;
closestArrowIndex = i;
}
}
}
if (closestArrow) {
// Check if arrow is close enough to the target zone to register a hit
// Use a larger detection range (150 pixels) to detect arrows approaching the target
if (closestDistance <= 150) {
var accuracy = checkHit(closestArrow);
if (accuracy) {
// Remove arrow from array and destroy it
closestArrow.destroy();
arrows.splice(closestArrowIndex, 1);
// Process the hit without calling processHit (which also destroys the arrow)
var points = 0;
var comboMultiplier = Math.floor(combo / 10) + 1;
if (accuracy === 'perfect') {
points = 100 * comboMultiplier;
var perfectSound = LK.getSound('hit_perfect');
perfectSound.volume = storage.masterVolume * storage.sfxVolume;
perfectSound.play();
showAccuracyText('PERFECT!', 0x00ff00);
// Extra effect for perfect hits
LK.effects.flashScreen(0x00ff00, 100);
} else if (accuracy === 'good') {
points = 50 * comboMultiplier;
var goodSound = LK.getSound('hit_good');
goodSound.volume = storage.masterVolume * storage.sfxVolume;
goodSound.play();
showAccuracyText('GOOD', 0xffff00);
}
score += points;
combo++;
// Increase health bar
healthBar = Math.min(maxHealth, healthBar + healthPerHit);
currentLevelHits++;
// Check if health bar is full to advance to next level
if (healthBar >= maxHealth) {
level++;
currentLevelHits = 0;
// Reset health bar to starting level for next challenge
healthBar = 50;
// Increase speed multiplier progressively with each level
speedMultiplier = Math.min(1.0 + (level - 1) * 0.15, maxSpeedMultiplier);
// Slightly reduce spawn interval for more challenge but keep it balanced
spawnInterval = Math.max(25, baseSpawnInterval - Math.floor((level - 1) * 1.2));
// Show enhanced level up effect with speed notification
showAccuracyText('LEVEL ' + level + '! HEALTH FULL!', 0x00ffff);
LK.effects.flashScreen(0x00ffff, 700);
// Add speed burst visual effect
tween(game, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 200,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(game, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 300,
easing: tween.easeOut
});
}
});
}
// Create multiple hit effects for high combos
var effectCount = Math.min(3, Math.floor(combo / 25) + 1);
for (var i = 0; i < effectCount; i++) {
LK.setTimeout(function () {
var effect = new HitEffect(closestArrow.x + (Math.random() - 0.5) * 50, closestArrow.y + (Math.random() - 0.5) * 50);
game.addChild(effect);
}, i * 50);
}
// Enhanced combo animations with milestone effects
if (combo % 5 === 0 && combo > 0) {
// Create combo effect at hit location
var comboEffect = new ComboEffect(closestArrow.x, closestArrow.y - 100, combo);
game.addChild(comboEffect);
// Scale combo text animation based on milestone
var targetScale = combo >= 50 ? 2.5 : combo >= 25 ? 2.0 : 1.8;
var targetColor = combo >= 100 ? 0xFFD700 : combo >= 50 ? 0xFF6B6B : combo >= 25 ? 0x4ECDC4 : 0x00FFFF;
tween(comboTxt, {
scaleX: targetScale,
scaleY: targetScale,
tint: targetColor
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: combo >= 25 ? 1.2 : 1,
scaleY: combo >= 25 ? 1.2 : 1,
tint: 0xFFD700
}, {
duration: 500,
easing: tween.easeOut
});
}
});
}
updateUI();
} else {
processMiss();
}
} else {
// Arrow exists but is too far from target zone - count as miss
processMiss();
}
} else {
// Tapped when no arrow was in range for this column
processMiss();
}
}
// Input handling
game.down = function (x, y, obj) {
// Start countdown when screen is tapped
if (gameState === 'start') {
startCountdown();
return; // Prevent other actions when start countdown begins
}
if (gameState === 'gameover') {
restartGame();
} else if (gameState === 'playing') {
// Determine which column was tapped based on x position
var tappedColumn = -1;
for (var i = 0; i < COLUMN_COUNT; i++) {
var columnLeft = columnPositions[i] - COLUMN_WIDTH / 2;
var columnRight = columnPositions[i] + COLUMN_WIDTH / 2;
if (x >= columnLeft && x <= columnRight) {
tappedColumn = i;
break;
}
}
if (tappedColumn >= 0) {
// Enhanced visual feedback for control zone tap
var controlZone = controlZones[tappedColumn];
var originalAlpha = controlZone.alpha;
var originalScale = controlZone.scaleX;
// Flash and scale effect
controlZone.alpha = 0.8;
controlZone.scaleX = originalScale * 1.1;
controlZone.scaleY = controlZone.scaleY * 1.1;
tween(controlZone, {
alpha: originalAlpha,
scaleX: originalScale,
scaleY: originalScale
}, {
duration: 150,
easing: tween.easeOut
});
// Add ripple effect
var effect = new HitEffect(controlZone.x, controlZone.y - 50);
game.addChild(effect);
handleColumnTap(tappedColumn);
} else {
processMiss();
}
}
};
// Main game loop
game.update = function () {
// Enhanced rocket animations with trails and speed variation
for (var i = 0; i < rockets.length; i++) {
var rocket = rockets[i];
rocket.y -= rocket.speed + Math.sin(LK.ticks * 0.05 + i) * 0.5;
rocket.rotation += 0.02 + Math.sin(LK.ticks * 0.03 + i) * 0.01;
// Enhanced wobble with varying amplitude
rocket.x += Math.sin(LK.ticks * 0.02 + i) * (1 + Math.cos(LK.ticks * 0.01 + i));
// Scale pulsing effect
rocket.scaleX = 0.3 + 0.05 * Math.sin(LK.ticks * 0.08 + i);
rocket.scaleY = 0.8 + 0.1 * Math.sin(LK.ticks * 0.06 + i);
// Color shifting
var colorPhase = LK.ticks * 0.03 + i;
if (i % 2 === 0) {
rocket.alpha = 0.15 + 0.1 * Math.sin(colorPhase);
}
if (rocket.y < -100) {
rocket.y = 2732 + 100;
rocket.x = Math.random() * 2048;
rocket.speed = 1 + Math.random() * 3; // Randomize speed on reset
}
}
// Enhanced confetti with spiral motion and color cycling
for (var i = 0; i < confetti.length; i++) {
var piece = confetti[i];
piece.y -= piece.speed;
piece.rotation += piece.rotationSpeed + Math.sin(LK.ticks * 0.02 + i) * 0.02;
// Enhanced spiral motion
var spiralRadius = 20 + 10 * Math.sin(LK.ticks * 0.015 + i);
piece.x += Math.sin(LK.ticks * 0.01 + i) * 0.5 + Math.cos(LK.ticks * 0.02 + i) * spiralRadius * 0.02;
// Scale animation
piece.scaleX = 0.1 + 0.05 * Math.sin(LK.ticks * 0.05 + i);
piece.scaleY = 0.1 + 0.05 * Math.cos(LK.ticks * 0.04 + i);
// Alpha pulsing
piece.alpha = 0.2 + 0.15 * Math.sin(LK.ticks * 0.06 + i);
if (piece.y < -50) {
piece.y = 2732 + 50;
piece.x = Math.random() * 2048;
}
}
// Enhanced comets with dynamic trails and speed bursts
for (var i = 0; i < comets.length; i++) {
var comet = comets[i];
// Enhanced movement with speed bursts
var speedMultiplier = 1 + 0.5 * Math.sin(LK.ticks * 0.02 + i);
comet.x += Math.cos(comet.rotation) * comet.speed * speedMultiplier;
comet.y += Math.sin(comet.rotation) * comet.speed * speedMultiplier;
// Enhanced trail effect with varying opacity and scale
comet.alpha = 0.15 + 0.15 * Math.sin(LK.ticks * 0.1 + i);
comet.scaleX = 0.6 + 0.2 * Math.sin(LK.ticks * 0.08 + i);
comet.scaleY = 0.2 + 0.1 * Math.cos(LK.ticks * 0.06 + i);
// Slight rotation wobble
comet.rotation += Math.sin(LK.ticks * 0.03 + i) * 0.01;
// Reset position when off screen
if (comet.x < -100 || comet.x > 2148 || comet.y < -100 || comet.y > 2832) {
comet.x = Math.random() * 2048;
comet.y = Math.random() * 2732;
comet.rotation = Math.random() * Math.PI * 2;
comet.speed = 2 + Math.random() * 4; // Randomize speed on reset
}
}
if (gameState === 'loading') {
// Animate loading text
loadingTxt.alpha = 0.7 + 0.3 * Math.sin(LK.ticks * 0.15);
return;
}
if (gameState === 'start') {
// Show leaderboard on start screen if it has entries
if (storage.leaderboard && storage.leaderboard.length > 0 && LK.ticks % 300 === 0) {
displayLeaderboard();
}
// Animate start text with rainbow effect and enhanced pulsing
startTxt.alpha = 0.7 + 0.3 * Math.sin(LK.ticks * 0.15);
startTxt.scaleX = 1 + 0.1 * Math.sin(LK.ticks * 0.12);
startTxt.scaleY = 1 + 0.1 * Math.sin(LK.ticks * 0.12);
var colorPhase = LK.ticks * 0.08;
var r = Math.sin(colorPhase) * 127 + 128;
var g = Math.sin(colorPhase + 2) * 127 + 128;
var b = Math.sin(colorPhase + 4) * 127 + 128;
startTxt.fill = Math.floor(r) << 16 | Math.floor(g) << 8 | Math.floor(b);
// Enhanced title animation with floating and rotation
titleTxt.y = -300 + 15 * Math.sin(LK.ticks * 0.08);
titleTxt.rotation = 0.15 * Math.sin(LK.ticks * 0.06);
titleTxt.scaleX = 1 + 0.05 * Math.sin(LK.ticks * 0.1);
titleTxt.scaleY = 1 + 0.05 * Math.sin(LK.ticks * 0.1);
// Enhanced subtitle animation with color shifting
subtitleTxt.alpha = 0.6 + 0.4 * Math.sin(LK.ticks * 0.12);
subtitleTxt.y = 100 + 5 * Math.sin(LK.ticks * 0.1);
var subColorPhase = LK.ticks * 0.06;
var subR = Math.sin(subColorPhase + 1) * 127 + 128;
var subG = Math.sin(subColorPhase + 3) * 127 + 128;
var subB = Math.sin(subColorPhase + 5) * 127 + 128;
subtitleTxt.fill = Math.floor(subR) << 16 | Math.floor(subG) << 8 | Math.floor(subB);
return;
}
if (gameState === 'countdown') {
countdownTimer++;
if (countdownTimer === 1) {
showCountdownNumber();
} else if (countdownTimer >= 60) {
countdownValue--;
if (countdownValue > 0) {
countdownTimer = 0;
showCountdownNumber();
} else {
// Start the game
gameState = 'playing';
gameStarted = true;
countdownTxt.alpha = 0;
LK.playMusic('background_music');
}
}
return;
}
if (gameState === 'gameover') {
// Keep restart text hidden and add animated background effects
restartTxt.alpha = 0;
// Add swirling particles effect during game over
for (var p = 0; p < 3; p++) {
if (Math.random() < 0.1) {
var particle = game.addChild(LK.getAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0.3
}));
particle.x = Math.random() * 2048;
particle.y = 2732 + 50;
particle.tint = Math.random() > 0.5 ? 0xFF6B6B : 0x4ECDC4;
tween(particle, {
y: -50,
rotation: Math.PI * 4,
alpha: 0,
scaleX: 0.3,
scaleY: 0.3
}, {
duration: 3000,
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
}
});
}
}
return;
}
// Game playing state
// Spawn arrows
arrowSpawnTimer++;
if (arrowSpawnTimer >= spawnInterval) {
spawnArrow();
arrowSpawnTimer = 0;
}
// Update arrows and check for misses
for (var i = arrows.length - 1; i >= 0; i--) {
var arrow = arrows[i];
// Check if arrow passed the target zone without being hit
if (!arrow.hitTested && arrow.y > TARGET_Y + HIT_ZONE_HEIGHT) {
arrow.hitTested = true;
processMiss();
}
// Remove arrows that are off screen
if (arrow.y > 2732 + 100) {
arrow.destroy();
arrows.splice(i, 1);
}
}
}; ===================================================================
--- original.js
+++ change.js
@@ -630,18 +630,21 @@
// Initialize leaderboard if it doesn't exist
if (!storage.leaderboard) {
storage.leaderboard = [];
}
- // Create new score entry with only literal values
- var dateString = new Date().toLocaleDateString();
- // Add to leaderboard using direct assignment to avoid object creation issues
+ // Create a simple date string using only literal operations
+ var now = new Date();
+ var dateString = now.getMonth() + 1 + '/' + now.getDate() + '/' + now.getFullYear();
+ // Get current leaderboard
var currentLeaderboard = storage.leaderboard;
- currentLeaderboard.push({
+ // Add new entry using only literal values - avoid object creation in push
+ currentLeaderboard[currentLeaderboard.length] = {
score: playerScore,
level: playerLevel,
combo: playerCombo,
date: dateString
- });
+ };
+ // Update storage with the modified array
storage.leaderboard = currentLeaderboard;
// Sort by score (highest first)
storage.leaderboard.sort(function (a, b) {
return b.score - a.score;