User prompt
Pies ponle mejores efectos ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Ponlos em el escudo del rango hay.
User prompt
El contador de rnagos hay estaran los efectos.
User prompt
Mejor al supremo
User prompt
Please fix the bug: 'self.createCosmicDust is not a function' in or related to this line: 'self.createCosmicDust(0xff8800);' Line Number: 292
User prompt
Anade afectos a los rangos segun su rango el leyenda podria tener efecto de estrellitas etc.
User prompt
El multiplicador lo tengo siempre
User prompt
Pon un x10 de puntos.
User prompt
Pon mi score en 0 y mi rango ponlo en noob quita mi rango de hacker. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Quita la laderboard ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Reinia mi rango a noob ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Reinicio mi rango a noob ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Quita mis puntos. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Agrega escudos para los rangos. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Agrega escudos para los rangos. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Mucho pon mas pocos porque en si el juego es dificil agrega mas rangos como en noob puede estar noob I noob II noob III en los otros tambien. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Has que el ramgo se guarde en el sentido estamos en pro y termina la partida y empezamos otra empezamos en pro has que subir de rango sea mas dificil el rango que estemos aparesca en el menu. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Pon los rangos el score sirve el rango has que el ranga aparesca en el menu ese rango se tiene que guardar. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Has un sistema de rangos de noob pro dios hacker inparable etc. ↪💡 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[k] = tempLeaderboard[k].score;' Line Number: 668 ↪💡 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[k + '.score'] = tempLeaderboard[k].score;' Line Number: 693 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Pon la lederboar mas abajo.
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'currentLeaderboard[newIndex] = {};' Line Number: 660 ↪💡 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[newIndex] = {};' Line Number: 660 ↪💡 Consider importing and using the following plugins: @upit/storage.v1 ↪💡 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[newIndex] = {};' Line Number: 660 ↪💡 Consider importing and using the following plugins: @upit/storage.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",
playerName: "Player",
currentRank: "noob I",
lifetimeScore: 0,
lastSessionScore: 0
});
/****
* 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;
});
var RankEffect = Container.expand(function (rankData, x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.rankData = rankData;
self.effectTimer = 0;
self.particles = [];
// Create effects based on rank tier
self.createEffects = function () {
var rankName = rankData.name.toLowerCase();
if (rankName.includes('noob')) {
// Noob: Simple subtle glow
self.createBasicGlow();
} else if (rankName.includes('pro')) {
// Pro: Green energy particles
self.createEnergyParticles(0x00ff00, 3);
} else if (rankName.includes('dios')) {
// Dios: Golden aura with sparkles
self.createAura(0xffd700);
self.createSparkles(0xffd700, 5);
} else if (rankName.includes('hacker')) {
// Hacker: Digital glitch effects
self.createGlitchEffect(0xff00ff);
self.createDataStreams(0xff00ff);
} else if (rankName.includes('imparable')) {
// Imparable: Cyan lightning bolts
self.createLightning(0x00ffff);
self.createEnergyField(0x00ffff);
} else if (rankName.includes('leyenda')) {
// Leyenda: Star constellation effect
self.createStarConstellation(0xff8800);
self.createCosmicDust(0xff8800);
} else if (rankName.includes('supremo')) {
// Supremo: Enhanced rainbow prismatic effect with multiple layers
self.createPrismaticEffect();
self.createEnergyWaves(0xff0088);
self.createSupremoAura();
self.createRainbowBurst();
self.createPowerRings();
} else if (rankName.includes('infinito')) {
// Infinito: Ultimate ethereal effect
self.createInfinityEffect();
self.createDimensionalRift();
}
};
self.createBasicGlow = function () {
var glow = self.attachAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
alpha: 0.2
});
glow.tint = rankData.color;
tween(glow, {
scaleX: 0.7,
scaleY: 0.7,
alpha: 0.1
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(glow, {
scaleX: 0.5,
scaleY: 0.5,
alpha: 0.2
}, {
duration: 2000,
easing: tween.easeInOut
});
}
});
};
self.createEnergyParticles = function (color, count) {
for (var i = 0; i < count; i++) {
LK.setTimeout(function () {
var particle = self.attachAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0.8
});
particle.tint = color;
var angle = Math.random() * Math.PI * 2;
var distance = 30 + Math.random() * 50;
particle.x = Math.cos(angle) * 20;
particle.y = Math.sin(angle) * 20;
tween(particle, {
x: Math.cos(angle) * distance,
y: Math.sin(angle) * distance,
scaleX: 0.05,
scaleY: 0.05,
alpha: 0
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
}
});
}, i * 200);
}
};
self.createAura = function (color) {
var aura = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5,
alpha: 0.1
});
aura.tint = color;
tween(aura, {
scaleX: 2,
scaleY: 2,
alpha: 0.3,
rotation: Math.PI
}, {
duration: 3000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(aura, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0.1,
rotation: Math.PI * 2
}, {
duration: 3000,
easing: tween.easeInOut
});
}
});
};
self.createSparkles = function (color, count) {
for (var i = 0; i < count; i++) {
var sparkle = self.attachAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.05,
scaleY: 0.05,
alpha: 0
});
sparkle.tint = color;
var radius = 60;
var angle = i / count * Math.PI * 2;
sparkle.x = Math.cos(angle) * radius;
sparkle.y = Math.sin(angle) * radius;
self.particles.push({
obj: sparkle,
angle: angle,
radius: radius,
speed: 0.02 + Math.random() * 0.02
});
}
};
self.createStarConstellation = function (color) {
// Create multiple stars in a constellation pattern
var starPositions = [{
x: 0,
y: -40
}, {
x: 30,
y: -20
}, {
x: 40,
y: 10
}, {
x: 20,
y: 30
}, {
x: -20,
y: 30
}, {
x: -40,
y: 10
}, {
x: -30,
y: -20
}];
for (var i = 0; i < starPositions.length; i++) {
var star = self.attachAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0.6
});
star.x = starPositions[i].x;
star.y = starPositions[i].y;
star.tint = color;
// Make stars twinkle
(function (starObj) {
tween(starObj, {
scaleX: 0.15,
scaleY: 0.15,
alpha: 1
}, {
duration: 500 + Math.random() * 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(starObj, {
scaleX: 0.1,
scaleY: 0.1,
alpha: 0.6
}, {
duration: 500 + Math.random() * 1000,
easing: tween.easeInOut
});
}
});
})(star);
}
};
self.createGlitchEffect = function (color) {
var glitchLayers = [];
for (var i = 0; i < 3; i++) {
var glitch = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1,
alpha: 0.2
});
glitch.tint = color;
glitchLayers.push(glitch);
}
// Animate glitch layers
glitchLayers.forEach(function (layer, index) {
tween(layer, {
x: (Math.random() - 0.5) * 10,
y: (Math.random() - 0.5) * 10,
alpha: Math.random() * 0.3
}, {
duration: 100 + Math.random() * 200,
easing: tween.linear,
onFinish: function onFinish() {
tween(layer, {
x: 0,
y: 0,
alpha: 0.2
}, {
duration: 100 + Math.random() * 200,
easing: tween.linear
});
}
});
});
};
self.createDataStreams = function (color) {
// Create vertical data stream effect
for (var i = 0; i < 5; i++) {
LK.setTimeout(function () {
var stream = self.attachAsset('arrow_down', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.3,
alpha: 0.6
});
stream.tint = color;
stream.x = (Math.random() - 0.5) * 80;
stream.y = -40;
tween(stream, {
y: 40,
alpha: 0,
scaleY: 0.5
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
stream.destroy();
}
});
}, i * 200);
}
};
self.createLightning = function (color) {
var lightning = self.attachAsset('arrow_down', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 2,
alpha: 0
});
lightning.tint = color;
lightning.rotation = Math.random() * Math.PI * 2;
tween(lightning, {
alpha: 0.8,
scaleX: 0.5,
scaleY: 3
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(lightning, {
alpha: 0,
scaleX: 0.1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
lightning.destroy();
}
});
}
});
};
self.createEnergyField = function (color) {
// Create an energy field effect
var field = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
alpha: 0.2
});
field.tint = color;
// Animate energy field pulsing
tween(field, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0.4,
rotation: Math.PI
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(field, {
scaleX: 0.8,
scaleY: 0.8,
alpha: 0.2,
rotation: Math.PI * 2
}, {
duration: 1500,
easing: tween.easeInOut
});
}
});
};
self.createCosmicDust = function (color) {
// Create floating cosmic dust particles
for (var i = 0; i < 8; i++) {
var dust = self.attachAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.03 + Math.random() * 0.05,
scaleY: 0.03 + Math.random() * 0.05,
alpha: 0.4 + Math.random() * 0.4
});
dust.tint = color;
var radius = 40 + Math.random() * 60;
var angle = Math.random() * Math.PI * 2;
dust.x = Math.cos(angle) * radius;
dust.y = Math.sin(angle) * radius;
// Animate dust floating
tween(dust, {
x: dust.x + (Math.random() - 0.5) * 40,
y: dust.y + (Math.random() - 0.5) * 40,
alpha: 0,
scaleX: 0.01,
scaleY: 0.01
}, {
duration: 2000 + Math.random() * 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
dust.destroy();
}
});
}
};
self.createPrismaticEffect = function () {
// Create enhanced rainbow prismatic effect with multiple layers
var colors = [0xFF0000, 0xFF7F00, 0xFFFF00, 0x00FF00, 0x0000FF, 0x4B0082, 0x9400D3];
// Create three layers of prisms for depth
for (var layer = 0; layer < 3; layer++) {
for (var i = 0; i < colors.length; i++) {
var prism = self.attachAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3 + layer * 0.15,
scaleY: 0.3 + layer * 0.15,
alpha: 0.5 - layer * 0.15
});
prism.tint = colors[i];
var angle = i / colors.length * Math.PI * 2 + layer * 0.2;
var radius = 50 + layer * 20;
prism.x = Math.cos(angle) * radius;
prism.y = Math.sin(angle) * radius;
self.particles.push({
obj: prism,
angle: angle,
radius: radius,
speed: 0.03 + layer * 0.01,
layer: layer
});
}
}
// Add central crown effect
var crown = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
alpha: 0.4
});
crown.tint = 0xFFD700;
crown.rotation = 0;
self.crownEffect = crown;
};
self.createEnergyWaves = function (color) {
// Create multiple types of expanding energy waves
for (var i = 0; i < 5; i++) {
LK.setTimeout(function () {
var wave = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
alpha: 0.7
});
wave.tint = color;
// Alternate between circular and diamond shapes
if (i % 2 === 0) {
wave.rotation = Math.PI / 4;
}
tween(wave, {
scaleX: 3,
scaleY: 3,
alpha: 0,
rotation: wave.rotation + Math.PI * 2
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
wave.destroy();
}
});
}, i * 300);
}
// Add pulsing core energy
var core = self.attachAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
alpha: 0.8
});
core.tint = 0xFFFFFF;
self.energyCore = core;
};
self.createInfinityEffect = function () {
// Create infinity symbol with particles
var infinityPath = [];
for (var t = 0; t < Math.PI * 2; t += 0.3) {
var x = 50 * Math.cos(t) / (1 + Math.sin(t) * Math.sin(t));
var y = 50 * Math.sin(t) * Math.cos(t) / (1 + Math.sin(t) * Math.sin(t));
infinityPath.push({
x: x,
y: y
});
}
infinityPath.forEach(function (pos, index) {
LK.setTimeout(function () {
var particle = self.attachAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.08,
scaleY: 0.08,
alpha: 0.7
});
particle.x = pos.x;
particle.y = pos.y;
particle.tint = 0xffffff;
tween(particle, {
alpha: 0,
scaleX: 0.02,
scaleY: 0.02
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
}
});
}, index * 50);
});
};
self.createDimensionalRift = function () {
// Create swirling dimensional rift effect
var rift = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.1,
alpha: 0.5
});
rift.tint = 0x9400D3;
// Animate rift rotation and scale
tween(rift, {
rotation: Math.PI * 4,
scaleX: 0.1,
scaleY: 1.5,
alpha: 0
}, {
duration: 3000,
easing: tween.easeInOut,
onFinish: function onFinish() {
rift.destroy();
}
});
};
self.createSupremoAura = function () {
// Create multi-layered aura effect
for (var i = 0; i < 4; i++) {
var aura = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2 + i * 0.3,
scaleY: 1.2 + i * 0.3,
alpha: 0.3 - i * 0.05
});
var colors = [0xFF0088, 0xFF00FF, 0x00FFFF, 0xFFFF00];
aura.tint = colors[i % colors.length];
// Animate each aura layer differently
(function (auraObj, index) {
tween(auraObj, {
rotation: Math.PI * 2,
scaleX: auraObj.scaleX + 0.2,
scaleY: auraObj.scaleY + 0.2,
alpha: 0.1
}, {
duration: 3000 + index * 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(auraObj, {
rotation: 0,
scaleX: 1.2 + index * 0.3,
scaleY: 1.2 + index * 0.3,
alpha: 0.3 - index * 0.05
}, {
duration: 3000 + index * 500,
easing: tween.easeInOut
});
}
});
})(aura, i);
}
};
self.createRainbowBurst = function () {
// Create periodic rainbow burst effect
self.rainbowBurstTimer = 0;
};
self.createPowerRings = function () {
// Create rotating power rings around the character
var ringColors = [0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF];
for (var i = 0; i < 6; i++) {
var ring = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 2,
alpha: 0.6
});
ring.tint = ringColors[i];
ring.rotation = i * Math.PI / 3;
self.particles.push({
obj: ring,
angle: i * Math.PI / 3,
radius: 0,
speed: 0.05,
type: 'powerRing'
});
}
};
self.update = function () {
self.effectTimer++;
// Update rotating particles with enhanced animations for supremo
for (var i = 0; i < self.particles.length; i++) {
var p = self.particles[i];
p.angle += p.speed;
// Special animations for supremo particles
if (self.rankData.name.toLowerCase().includes('supremo')) {
if (p.layer !== undefined) {
// Multi-layer prismatic effect
var radiusOscillation = Math.sin(self.effectTimer * 0.02 + p.layer) * 10;
p.obj.x = Math.cos(p.angle) * (p.radius + radiusOscillation);
p.obj.y = Math.sin(p.angle) * (p.radius + radiusOscillation);
p.obj.alpha = 0.5 + 0.3 * Math.sin(self.effectTimer * 0.05 + i);
// Color shifting for rainbow effect
var hue = (self.effectTimer * 2 + i * 30) % 360;
var rgb = self.hslToRgb(hue / 360, 1, 0.5);
p.obj.tint = rgb;
} else if (p.type === 'powerRing') {
// Animate power rings
p.obj.rotation += 0.03;
p.radius = 40 + 30 * Math.sin(self.effectTimer * 0.03 + i);
p.obj.x = Math.cos(p.angle) * p.radius;
p.obj.y = Math.sin(p.angle) * p.radius;
p.obj.scaleX = 0.1 + 0.05 * Math.sin(self.effectTimer * 0.04 + i);
p.obj.alpha = 0.4 + 0.4 * Math.sin(self.effectTimer * 0.06 + i);
}
} else {
// Normal particle animation
p.obj.x = Math.cos(p.angle) * p.radius;
p.obj.y = Math.sin(p.angle) * p.radius;
p.obj.alpha = 0.3 + 0.7 * Math.sin(self.effectTimer * 0.05 + i);
}
}
// Special supremo animations
if (self.rankData.name.toLowerCase().includes('supremo')) {
// Animate crown effect
if (self.crownEffect) {
self.crownEffect.rotation += 0.02;
self.crownEffect.scaleX = 0.8 + 0.1 * Math.sin(self.effectTimer * 0.04);
self.crownEffect.scaleY = 0.8 + 0.1 * Math.sin(self.effectTimer * 0.04);
self.crownEffect.alpha = 0.4 + 0.2 * Math.sin(self.effectTimer * 0.06);
}
// Animate energy core
if (self.energyCore) {
self.energyCore.scaleX = 0.5 + 0.2 * Math.sin(self.effectTimer * 0.08);
self.energyCore.scaleY = 0.5 + 0.2 * Math.sin(self.effectTimer * 0.08);
self.energyCore.alpha = 0.8 + 0.2 * Math.sin(self.effectTimer * 0.1);
var coreHue = self.effectTimer * 3 % 360;
var coreRgb = self.hslToRgb(coreHue / 360, 1, 0.7);
self.energyCore.tint = coreRgb;
}
// Create rainbow burst periodically
if (self.rainbowBurstTimer !== undefined) {
self.rainbowBurstTimer++;
if (self.rainbowBurstTimer >= 120) {
self.createRainbowBurstEffect();
self.rainbowBurstTimer = 0;
}
}
}
// Recreate effects periodically
if (self.effectTimer % 180 === 0) {
self.createEffects();
}
};
// Helper function to convert HSL to RGB
self.hslToRgb = function (h, s, l) {
var r, g, b;
if (s === 0) {
r = g = b = l;
} else {
var hue2rgb = function hue2rgb(p, q, t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
};
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return Math.floor(r * 255) << 16 | Math.floor(g * 255) << 8 | Math.floor(b * 255);
};
self.createRainbowBurstEffect = function () {
// Create spectacular rainbow burst
var burstCount = 12;
for (var i = 0; i < burstCount; i++) {
var burst = self.attachAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 1
});
var angle = i / burstCount * Math.PI * 2;
var hue = i / burstCount * 360;
burst.tint = self.hslToRgb(hue / 360, 1, 0.5);
burst.x = 0;
burst.y = 0;
tween(burst, {
x: Math.cos(angle) * 100,
y: Math.sin(angle) * 100,
scaleX: 0.5,
scaleY: 0.5,
alpha: 0,
rotation: Math.PI * 2
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
burst.destroy();
}
});
}
};
// Initialize effects
self.createEffects();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c2c54
});
/****
* Game Code
****/
// Game constants
var COLUMN_COUNT = 4;
var currentRankEffect = null;
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
// x10 points multiplier - always active
var x10Active = true;
var x10Duration = 600; // 10 seconds at 60fps
var x10Timer = 0;
var x10Cooldown = 0;
var x10MaxCooldown = 1800; // 30 seconds cooldown
// 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 = [];
// Expanded rank system with sub-levels and reduced score requirements
var ranks = [{
name: "noob I",
minScore: 0,
color: 0x666666
}, {
name: "noob II",
minScore: 500,
color: 0x777777
}, {
name: "noob III",
minScore: 1200,
color: 0x888888
}, {
name: "pro I",
minScore: 2000,
color: 0x00aa00
}, {
name: "pro II",
minScore: 3500,
color: 0x00cc00
}, {
name: "pro III",
minScore: 5500,
color: 0x00ff00
}, {
name: "dios I",
minScore: 8000,
color: 0xccaa00
}, {
name: "dios II",
minScore: 12000,
color: 0xddbb00
}, {
name: "dios III",
minScore: 18000,
color: 0xffd700
}, {
name: "hacker I",
minScore: 25000,
color: 0xcc00cc
}, {
name: "hacker II",
minScore: 35000,
color: 0xdd00dd
}, {
name: "hacker III",
minScore: 50000,
color: 0xff00ff
}, {
name: "imparable I",
minScore: 70000,
color: 0x00cccc
}, {
name: "imparable II",
minScore: 95000,
color: 0x00dddd
}, {
name: "imparable III",
minScore: 125000,
color: 0x00ffff
}, {
name: "leyenda I",
minScore: 160000,
color: 0xff6600
}, {
name: "leyenda II",
minScore: 200000,
color: 0xff7700
}, {
name: "leyenda III",
minScore: 250000,
color: 0xff8800
}, {
name: "supremo I",
minScore: 310000,
color: 0xff0066
}, {
name: "supremo II",
minScore: 380000,
color: 0xff0077
}, {
name: "supremo III",
minScore: 460000,
color: 0xff0088
}, {
name: "infinito",
minScore: 550000,
color: 0xffffff
}];
function getRankFromScore(score) {
var currentRank = ranks[0];
for (var i = 0; i < ranks.length; i++) {
if (score >= ranks[i].minScore) {
currentRank = ranks[i];
}
}
return currentRank;
}
function updatePlayerRank(score) {
// Initialize lifetime score if it doesn't exist
if (!storage.lifetimeScore) {
storage.lifetimeScore = 0;
}
// Add current game points to lifetime total
var pointsToAdd = score - (storage.lastSessionScore || 0);
if (pointsToAdd > 0) {
storage.lifetimeScore += pointsToAdd;
storage.lastSessionScore = score;
}
var newRank = getRankFromScore(storage.lifetimeScore);
var oldRankName = storage.currentRank;
if (newRank.name !== oldRankName) {
storage.currentRank = newRank.name;
showRankUpEffect(newRank);
return true;
}
return false;
}
function showRankUpEffect(rank) {
// Create rank up text
var rankUpTxt = new Text2('RANK UP!', {
size: 100,
fill: rank.color
});
rankUpTxt.anchor.set(0.5, 0.5);
rankUpTxt.x = 0;
rankUpTxt.y = -50;
rankUpTxt.alpha = 0;
rankUpTxt.scaleX = 0.1;
rankUpTxt.scaleY = 0.1;
LK.gui.center.addChild(rankUpTxt);
// Create new rank text
var newRankTxt = new Text2(rank.name.toUpperCase(), {
size: 80,
fill: rank.color
});
newRankTxt.anchor.set(0.5, 0.5);
newRankTxt.x = 0;
newRankTxt.y = 50;
newRankTxt.alpha = 0;
newRankTxt.scaleX = 0.1;
newRankTxt.scaleY = 0.1;
LK.gui.center.addChild(newRankTxt);
// Animate rank up effect
tween(rankUpTxt, {
alpha: 1,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 800,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(rankUpTxt, {
alpha: 0,
y: -150
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
rankUpTxt.destroy();
}
});
}
});
// Animate new rank text
LK.setTimeout(function () {
tween(newRankTxt, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 600,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(newRankTxt, {
alpha: 0,
y: 150
}, {
duration: 1200,
easing: tween.easeOut,
onFinish: function onFinish() {
newRankTxt.destroy();
}
});
}
});
}, 400);
// Flash screen with rank color
LK.effects.flashScreen(rank.color, 1000);
// Create large animated shield for rank up effect
var rankUpShield = LK.getAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0
});
rankUpShield.x = 0;
rankUpShield.y = 0;
rankUpShield.tint = rank.color;
LK.gui.center.addChild(rankUpShield);
// Create multiple shield layers for enhanced effect
var shieldLayers = [];
for (var sl = 0; sl < 3; sl++) {
var shieldLayer = LK.getAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0
});
shieldLayer.x = 0;
shieldLayer.y = 0;
shieldLayer.tint = rank.color;
LK.gui.center.addChild(shieldLayer);
shieldLayers.push(shieldLayer);
}
// Animate the main rank up shield
tween(rankUpShield, {
scaleX: 4,
scaleY: 4,
alpha: 1,
rotation: Math.PI * 3
}, {
duration: 1500,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(rankUpShield, {
scaleX: 0.1,
scaleY: 0.1,
alpha: 0,
rotation: Math.PI * 6
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
rankUpShield.destroy();
}
});
}
});
// Animate shield layers with staggered timing
for (var sl = 0; sl < shieldLayers.length; sl++) {
(function (layer, index) {
LK.setTimeout(function () {
tween(layer, {
scaleX: 2 + index * 0.5,
scaleY: 2 + index * 0.5,
alpha: 0.7 - index * 0.2,
rotation: Math.PI * (2 + index)
}, {
duration: 1200 + index * 200,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(layer, {
scaleX: 0.1,
scaleY: 0.1,
alpha: 0,
rotation: Math.PI * (4 + index * 2)
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
layer.destroy();
}
});
}
});
}, index * 300);
})(shieldLayers[sl], sl);
}
// Create celebration particles
for (var i = 0; i < 20; i++) {
LK.setTimeout(function () {
var particle = game.addChild(LK.getAsset('hit_effect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.2,
alpha: 0.8
}));
particle.x = 1024 + (Math.random() - 0.5) * 600;
particle.y = 1366 + (Math.random() - 0.5) * 400;
particle.tint = rank.color;
var angle = Math.random() * Math.PI * 2;
var distance = 200 + Math.random() * 300;
tween(particle, {
x: particle.x + Math.cos(angle) * distance,
y: particle.y + Math.sin(angle) * distance,
scaleX: 0.05,
scaleY: 0.05,
alpha: 0,
rotation: Math.PI * 4
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
}
});
}, i * 50);
}
// Update rank effect to match new rank at shield position
if (currentRankEffect) {
currentRankEffect.destroy();
}
currentRankEffect = new RankEffect(rank, rankShield.x, rankShield.y);
LK.gui.topRight.addChild(currentRankEffect);
}
// 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);
// Initialize rank text with stored rank
var storedRank = storage.currentRank || "noob I";
var initialRankData = null;
for (var r = 0; r < ranks.length; r++) {
if (ranks[r].name === storedRank) {
initialRankData = ranks[r];
break;
}
}
if (!initialRankData) {
initialRankData = ranks[0]; // fallback to noob
}
var rankTxt = new Text2('RANK: ' + initialRankData.name.toUpperCase(), {
size: 45,
fill: initialRankData.color
});
rankTxt.anchor.set(1, 0);
rankTxt.x = -50;
rankTxt.y = 110;
LK.gui.topRight.addChild(rankTxt);
// Add shield icon next to rank text with enhanced properties
var rankShield = LK.getAsset('shield', {
anchorX: 1,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0
});
rankShield.x = -280;
rankShield.y = 135;
rankShield.tint = initialRankData.color;
rankShield.rotation = 0;
LK.gui.topRight.addChild(rankShield);
// Add shield glow effect
var shieldGlow = LK.getAsset('shield', {
anchorX: 1,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2,
alpha: 0.3
});
shieldGlow.x = -280;
shieldGlow.y = 135;
shieldGlow.tint = initialRankData.color;
LK.gui.topRight.addChild(shieldGlow);
// Create initial rank effect at shield position
var initialRankEffect = getRankFromScore(storage.lifetimeScore || 0);
currentRankEffect = new RankEffect(initialRankEffect, rankShield.x, rankShield.y);
LK.gui.topRight.addChild(currentRankEffect);
// Start shield glow animation
tween(shieldGlow, {
scaleX: 1.4,
scaleY: 1.4,
alpha: 0.1
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(shieldGlow, {
scaleX: 1.2,
scaleY: 1.2,
alpha: 0.3
}, {
duration: 1500,
easing: tween.easeInOut
});
}
});
// 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);
// x10 multiplier button - hidden since always active
var x10Button = LK.getAsset('target_zone', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.8,
alpha: 0
});
x10Button.tint = 0xFF00FF;
x10Button.x = 0;
x10Button.y = 100;
LK.gui.bottom.addChild(x10Button);
var x10ButtonText = new Text2('x10', {
size: 60,
fill: 0xFFFFFF
});
x10ButtonText.anchor.set(0.5, 0.5);
x10ButtonText.x = 0;
x10ButtonText.y = 100;
x10ButtonText.alpha = 0;
LK.gui.bottom.addChild(x10ButtonText);
// x10 active indicator - always visible
var x10Indicator = new Text2('x10 ALWAYS ACTIVE!', {
size: 80,
fill: 0xFF00FF
});
x10Indicator.anchor.set(0.5, 0.5);
x10Indicator.x = 0;
x10Indicator.y = -300;
x10Indicator.alpha = 1;
LK.gui.center.addChild(x10Indicator);
// 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);
// Reset Points Function
function resetPlayerPoints() {
// Reset lifetime score to zero
storage.lifetimeScore = 0;
// Reset session score
storage.lastSessionScore = 0;
// Reset current rank to noob I (not hacker)
storage.currentRank = "noob I";
// Also reset the current game score to 0
score = 0;
// Update UI to reflect changes
updateUI();
// Show confirmation message
showAccuracyText('SCORE & RANK RESET!', 0xff0000);
LK.effects.flashScreen(0xff0000, 500);
}
// Reset Rank Function
function resetPlayerRank() {
// Reset current rank to noob I
storage.currentRank = "noob I";
// Update UI to reflect rank change
updateUI();
// Show confirmation message
showAccuracyText('RANK RESET TO NOOB I!', 0xff0000);
LK.effects.flashScreen(0xff0000, 500);
}
// 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);
}
// Apply x10 multiplier if active
if (x10Active) {
points *= 10;
// Show x10 effect
var x10Effect = new Text2('x10!', {
size: 120,
fill: 0xFF00FF
});
x10Effect.anchor.set(0.5, 0.5);
x10Effect.x = arrow.x;
x10Effect.y = arrow.y - 100;
game.addChild(x10Effect);
tween(x10Effect, {
y: arrow.y - 200,
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
x10Effect.destroy();
}
});
}
score += points;
combo++;
// Check for rank up
updatePlayerRank(score);
// 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 rank display using stored rank
var storedRank = storage.currentRank || "noob I";
var currentRankData = null;
for (var r = 0; r < ranks.length; r++) {
if (ranks[r].name === storedRank) {
currentRankData = ranks[r];
break;
}
}
if (!currentRankData) {
currentRankData = ranks[0]; // fallback to noob
}
// Find next rank for progress display
var nextRank = null;
for (var nr = 0; nr < ranks.length; nr++) {
if (ranks[nr].minScore > (storage.lifetimeScore || 0)) {
nextRank = ranks[nr];
break;
}
}
var rankDisplayText = 'RANK: ' + currentRankData.name.toUpperCase();
if (nextRank) {
var progress = storage.lifetimeScore || 0;
var needed = nextRank.minScore - progress;
rankDisplayText += ' (' + needed + ' TO ' + nextRank.name.toUpperCase() + ')';
}
rankTxt.setText(rankDisplayText);
rankTxt.fill = currentRankData.color;
// Update shield color to match current rank
rankShield.tint = currentRankData.color;
shieldGlow.tint = currentRankData.color;
// Add enhanced pulsing animation to shield for visual appeal
tween(rankShield, {
scaleX: 1.1,
scaleY: 1.1,
alpha: 1,
rotation: 0.1
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(rankShield, {
scaleX: 0.9,
scaleY: 0.9,
alpha: 0.95,
rotation: -0.1
}, {
duration: 1000,
easing: tween.easeInOut
});
}
});
// Add rotation effect for higher ranks
if (currentRankData.name.includes('dios') || currentRankData.name.includes('hacker') || currentRankData.name.includes('imparable') || currentRankData.name.includes('leyenda') || currentRankData.name.includes('supremo') || currentRankData.name.includes('infinito')) {
tween(rankShield, {
rotation: rankShield.rotation + Math.PI * 2
}, {
duration: 3000,
easing: tween.easeInOut
});
}
// 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;
// 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
x10Active = true;
x10Timer = 0;
x10Cooldown = 0;
x10Indicator.alpha = 1;
x10Button.alpha = 0;
x10ButtonText.alpha = 0;
x10ButtonText.setText('x10');
gameState = 'start';
gameStarted = false;
// Reset session score tracking but keep lifetime score and current rank
storage.lastSessionScore = 0;
// 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;
// Reset shield to stored rank state
var currentStoredRank = storage.currentRank || "noob";
var currentStoredRankData = null;
for (var sr = 0; sr < ranks.length; sr++) {
if (ranks[sr].name === currentStoredRank) {
currentStoredRankData = ranks[sr];
break;
}
}
if (!currentStoredRankData) {
currentStoredRankData = ranks[0]; // fallback to noob
}
rankShield.tint = currentStoredRankData.color;
rankShield.scaleX = 1.0;
rankShield.scaleY = 1.0;
rankShield.alpha = 1.0;
rankShield.rotation = 0;
// Reset shield glow
shieldGlow.tint = currentStoredRankData.color;
shieldGlow.scaleX = 1.2;
shieldGlow.scaleY = 1.2;
shieldGlow.alpha = 0.3;
// Update UI
updateUI();
// Create rank effect for current rank at shield position
if (currentRankEffect) {
currentRankEffect.destroy();
}
var storedRankData = getRankFromScore(storage.lifetimeScore || 0);
currentRankEffect = new RankEffect(storedRankData, rankShield.x, rankShield.y);
LK.gui.topRight.addChild(currentRankEffect);
}
});
}
function showGameOverScreen() {
gameState = 'gameover';
// Flash screen with dramatic effect
LK.effects.flashScreen(0x8B0000, 1000);
// 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);
// 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);
}
// Apply x10 multiplier if active
if (x10Active) {
points *= 10;
// Show x10 effect
var x10Effect = new Text2('x10!', {
size: 120,
fill: 0xFF00FF
});
x10Effect.anchor.set(0.5, 0.5);
x10Effect.x = closestArrow.x;
x10Effect.y = closestArrow.y - 100;
game.addChild(x10Effect);
tween(x10Effect, {
y: closestArrow.y - 200,
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
x10Effect.destroy();
}
});
}
score += points;
combo++;
// Check for rank up
updatePlayerRank(score);
// 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
var titleTapCount = 0;
var titleTapTimer = 0;
var rankResetTapCount = 0;
var rankResetTapTimer = 0;
game.down = function (x, y, obj) {
// Start countdown when screen is tapped
if (gameState === 'start') {
// Check for multiple taps on title to reset points
titleTapCount++;
titleTapTimer = 0;
// If tapped 5 times quickly, reset points
if (titleTapCount >= 5) {
resetPlayerPoints();
titleTapCount = 0;
return;
}
// Check for taps on rank shield area to reset rank
if (x >= 1700 && x <= 2048 && y >= 90 && y <= 160) {
rankResetTapCount++;
rankResetTapTimer = 0;
// If tapped rank shield 3 times quickly, reset rank
if (rankResetTapCount >= 3) {
resetPlayerRank();
rankResetTapCount = 0;
return;
}
return; // Prevent starting countdown when tapping rank area
}
startCountdown();
return; // Prevent other actions when start countdown begins
}
if (gameState === 'gameover') {
restartGame();
} else if (gameState === 'playing') {
// x10 is always active, no need to check for button tap
// 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') {
// Reset title tap count after timeout
titleTapTimer++;
if (titleTapTimer > 180) {
// 3 seconds at 60fps
titleTapCount = 0;
titleTapTimer = 0;
}
// Reset rank reset tap count after timeout
rankResetTapTimer++;
if (rankResetTapTimer > 180) {
// 3 seconds at 60fps
rankResetTapCount = 0;
rankResetTapTimer = 0;
}
// Update rank display on start screen
updateUI();
// 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
// x10 multiplier is always active - just animate the indicator
if (gameState === 'playing') {
// Pulse x10 indicator
x10Indicator.alpha = 0.8 + 0.2 * Math.sin(LK.ticks * 0.3);
x10Indicator.scaleX = 1.2 + 0.1 * Math.sin(LK.ticks * 0.2);
x10Indicator.scaleY = 1.2 + 0.1 * Math.sin(LK.ticks * 0.2);
}
// 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
@@ -1297,13 +1297,13 @@
}
});
}, i * 50);
}
- // Update rank effect to match new rank
+ // Update rank effect to match new rank at shield position
if (currentRankEffect) {
currentRankEffect.destroy();
}
- currentRankEffect = new RankEffect(rank, rankTxt.x, rankTxt.y);
+ currentRankEffect = new RankEffect(rank, rankShield.x, rankShield.y);
LK.gui.topRight.addChild(currentRankEffect);
}
// Calculate column positions
for (var i = 0; i < COLUMN_COUNT; i++) {
@@ -1513,11 +1513,11 @@
shieldGlow.x = -280;
shieldGlow.y = 135;
shieldGlow.tint = initialRankData.color;
LK.gui.topRight.addChild(shieldGlow);
-// Create initial rank effect
+// Create initial rank effect at shield position
var initialRankEffect = getRankFromScore(storage.lifetimeScore || 0);
-currentRankEffect = new RankEffect(initialRankEffect, rankTxt.x, rankTxt.y);
+currentRankEffect = new RankEffect(initialRankEffect, rankShield.x, rankShield.y);
LK.gui.topRight.addChild(currentRankEffect);
// Start shield glow animation
tween(shieldGlow, {
scaleX: 1.4,
@@ -2487,14 +2487,14 @@
shieldGlow.scaleY = 1.2;
shieldGlow.alpha = 0.3;
// Update UI
updateUI();
- // Create rank effect for current rank
+ // Create rank effect for current rank at shield position
if (currentRankEffect) {
currentRankEffect.destroy();
}
var storedRankData = getRankFromScore(storage.lifetimeScore || 0);
- currentRankEffect = new RankEffect(storedRankData, rankTxt.x, rankTxt.y);
+ currentRankEffect = new RankEffect(storedRankData, rankShield.x, rankShield.y);
LK.gui.topRight.addChild(currentRankEffect);
}
});
}