User prompt
No es necesario que agreges el texto (+2) y que ese bonus solo sea para el mismo nivel y no mas
User prompt
No me esta dando mas fhleas cuando le doy al bonus flecha
User prompt
pero quiero que el bonus flehca te de 2 o 3 flechas mas de manera aleatoria (2-3)
User prompt
Quiero que si el bonus de flechas te de mas de 5 arrows, no imparta pero solo si es el que te da el bonus flecha
User prompt
Asi esta perfecto
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'active')' in or related to this line: 'if (!arrow.active) {' Line Number: 1105
User prompt
quiero que el bonus flecha aumente aleatoriamente 2 o 3 flehcas mas y que en arrows: 5 aparezcan las 2 o 3 felchas exytras
User prompt
cuando disparo, los arrows no bajan su numero
User prompt
Revierte lo que te dije
User prompt
Pero ahora en arrows: hay NaN
User prompt
pero cuando agarrlo el bonus de flehca, arriba en arrows: solo hay 5 y no 2 o 3 mas
User prompt
Quiero que el bonus flecha me de aleatoriamente de 2 a 3 flehcas mas
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'active')' in or related to this line: 'if (!arrow.active) {' Line Number: 1105
User prompt
mejor que sean de 2 a 3 felchas mas
User prompt
Quiero que el bonus flechas me den aleatoriamente de 1 a 3 flechas mas
User prompt
Quiero que solo tengamos 5 flechas y que el arco solo pueda disparar 5 flehcas, no mas
User prompt
Quiero que tire varias flechas pero si en arrows: 5 esta 0, ya no pueda torar mas felchas hasta que tenga flechas
User prompt
elimina lo ultimo que dije
User prompt
pero si tengo 2 o 3 o 4 o 5, si pueda tirar las flechas varias veces
User prompt
Siguen saliendo flehcas infinitas cuando no dejo de disparar, solo quiero que salgan 5
User prompt
si en arrows: hay 0 flehcas, que el arco no pueda volver a disparar mas flechas
User prompt
Como te explico, las flechas que salen del arco son infinitas, solo quiero que salgan 5 flehcas
User prompt
Hablo que el arco (bow) sale flechas infinitas y no las 5 que tenemos
User prompt
cuando disparo muchoas veces, sale varias flechas, deberia salir solo las 5 o depedndiendo de cuantas me quedan
User prompt
Solo quiero que salga la misma cantidad de flehcas que tenemos en el arco
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Archer = Container.expand(function () {
var self = Container.call(this);
var bowGraphics = self.attachAsset('bow', {
anchorX: 0.5,
anchorY: 0.5
});
self.bow = bowGraphics;
self.aimAngle = 0;
self.aimAt = function (targetX, targetY) {
var dx = targetX - (self.x + self.bow.x);
var dy = targetY - (self.y + self.bow.y);
self.aimAngle = Math.atan2(dy, dx);
self.bow.rotation = self.aimAngle;
};
self.shoot = function () {
// Only allow shooting if we haven't reached the maximum number of arrows
if (arrows.length >= maxArrows) return; // No more arrows can be shot
var arrow = new Arrow();
var bowWorldX = self.x + self.bow.x + Math.cos(self.aimAngle) * 40;
var bowWorldY = self.y + self.bow.y + Math.sin(self.aimAngle) * 40;
arrow.x = bowWorldX;
arrow.y = bowWorldY;
arrow.rotation = self.aimAngle;
var power = currentPower; // Use dynamic power based on mouse distance
arrow.velocityX = Math.cos(self.aimAngle) * power;
arrow.velocityY = Math.sin(self.aimAngle) * power;
arrows.push(arrow);
game.addChild(arrow);
LK.getSound('shoot').play();
};
return self;
});
var Arrow = Container.expand(function () {
var self = Container.call(this);
var arrowGraphics = self.attachAsset('arrow', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.gravity = 0.3;
self.active = true;
self.update = function () {
if (!self.active) return;
self.x += self.velocityX;
self.y += self.velocityY;
self.velocityY += self.gravity;
// Update arrow rotation to follow movement direction
if (self.velocityX !== 0 || self.velocityY !== 0) {
self.rotation = Math.atan2(self.velocityY, self.velocityX);
}
// Check platform collisions with smaller collision area
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
// Calculate distance between arrow and platform center
var dx = self.x - platform.x;
var dy = self.y - platform.y;
// Reduce vertical collision sensitivity by using separate X and Y checks
var horizontalDistance = Math.abs(dx);
var verticalDistance = Math.abs(dy);
// Use collision radius for platforms (100 pixels horizontal, 60 pixels vertical)
if (horizontalDistance < 100 && verticalDistance < 60) {
self.active = false;
self.velocityX = 0;
self.velocityY = 0;
break;
}
}
// Remove arrow if it goes off screen
// Remove arrow if it goes off screen
if (self.x > 2100 || self.y > 2800 || self.x < -50 || self.y < -50) {
// Give bonus points if arrow didn't hit any platform
if (self.active) {
LK.setScore(LK.getScore() + 5);
scoreTxt.setText(LK.getScore());
}
self.destroy();
for (var i = arrows.length - 1; i >= 0; i--) {
if (arrows[i] === self) {
arrows.splice(i, 1);
break;
}
}
}
};
return self;
});
var ArrowBonus = Container.expand(function () {
var self = Container.call(this);
var bonusGraphics = self.attachAsset('arrowBonus', {
anchorX: 0.5,
anchorY: 0.5
});
self.hit = false;
self.getHit = function () {
if (self.hit) return;
self.hit = true;
// Add random amount of arrows (2-4) directly to available arrows
var bonusArrows = Math.floor(Math.random() * 3) + 2;
maxArrows = Math.min(5, maxArrows + bonusArrows);
// Flash effect
LK.effects.flashObject(self, 0x00ff00, 300);
// Remove from arrowBonuses array
for (var i = arrowBonuses.length - 1; i >= 0; i--) {
if (arrowBonuses[i] === self) {
arrowBonuses.splice(i, 1);
break;
}
}
// Animate bonus disappearing
tween(self, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
LK.getSound('arrowBonus').play();
// Update arrows display
var remainingArrows = Math.max(0, Math.min(5, maxArrows || 5) - arrows.length);
arrowsTxt.setText('Arrows: ' + remainingArrows);
};
return self;
});
var Bomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
self.hit = false;
self.getHit = function () {
if (self.hit) return;
self.hit = true;
// Flash effect
LK.effects.flashObject(self, 0xff0000, 300);
// Remove from bombs array
for (var i = bombs.length - 1; i >= 0; i--) {
if (bombs[i] === self) {
bombs.splice(i, 1);
break;
}
}
// Flash screen red and show game over
LK.effects.flashScreen(0xff0000, 1000);
LK.getSound('explosion').play();
// Animate bomb explosion
tween(self, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
// Show game over after explosion animation
LK.setTimeout(function () {
LK.showGameOver();
}, 200);
}
});
};
return self;
});
var Fruit = Container.expand(function (type) {
var self = Container.call(this);
var fruitType = type || 'apple';
var fruitGraphics = self.attachAsset(fruitType, {
anchorX: 0.5,
anchorY: 0.5
});
self.fruitType = fruitType;
self.points = fruitType === 'apple' ? 10 : fruitType === 'orange' ? 15 : 20;
self.hit = false;
// Start idle floating animation
self.startIdleAnimation = function () {
var animationDuration = 1500 + Math.random() * 1000; // 1.5-2.5 seconds
var moveRange = 8 + Math.random() * 12; // 8-20 pixels movement
if (self.initialY === undefined) {
self.initialY = self.y; // Store the original position only once
}
// Find the platform this fruit is on
var platformY = self.initialY + 60; // Platform is 60 pixels below fruit
// Limit upward movement to not go above initial position too much
var upwardY = self.initialY - moveRange;
// Limit downward movement to not go below platform level
var downwardY = Math.min(self.initialY + moveRange, platformY - 50);
tween(self, {
y: upwardY
}, {
duration: animationDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (!self.hit) {
tween(self, {
y: downwardY
}, {
duration: animationDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (!self.hit) {
self.startIdleAnimation();
}
}
});
}
}
});
};
self.getHit = function () {
if (self.hit) return;
self.hit = true;
LK.setScore(LK.getScore() + self.points);
scoreTxt.setText(LK.getScore());
// Flash effect
LK.effects.flashObject(self, 0xFFFFFF, 300);
// Remove from fruits array
for (var i = fruits.length - 1; i >= 0; i--) {
if (fruits[i] === self) {
fruits.splice(i, 1);
break;
}
}
// Only remove arrows when level is completed (no fruits remain)
// The arrows will be cleared when spawnFruits() is called for next level
// Create explosion/disintegration effect
tween(self, {
scaleX: 1.5,
scaleY: 1.5,
rotation: Math.PI * 2
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
// Second phase: shrink and fade out
tween(self, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
self.destroy();
}
});
}
});
LK.getSound('hit').play();
// Check win condition
if (fruits.length === 0) {
// Show level complete animation immediately
showLevelCompleteAnimation();
}
};
return self;
});
var Menu = Container.expand(function () {
var self = Container.call(this);
// Animated background layers
var menuBg1 = self.attachAsset('menuBg1', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
alpha: 1
});
var menuBg2 = self.attachAsset('menuBg2', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
alpha: 0.7
});
self.addChild(menuBg2);
// Background stars removed as requested
// Animate background layers
tween(menuBg2, {
alpha: 0.3
}, {
duration: 3000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(menuBg2, {
alpha: 0.7
}, {
duration: 3000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Continue background animation loop
}
});
}
});
// Animated title image
var titleImage = self.attachAsset('titleImage', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0,
scaleY: 0,
rotation: 0
});
titleImage.x = 1024;
titleImage.y = 700;
// Title entrance animation with continuous effects
tween(titleImage, {
scaleX: 1.2,
scaleY: 1.2,
rotation: Math.PI * 0.1
}, {
duration: 1000,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Continuous title animation loop
function animateTitle() {
tween(titleImage, {
scaleX: 1.1,
scaleY: 1.1,
rotation: -Math.PI * 0.05
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(titleImage, {
scaleX: 1.3,
scaleY: 1.3,
rotation: Math.PI * 0.05
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: animateTitle
});
}
});
}
animateTitle();
}
});
// Title glow effect with enhanced animation using duplicate image
var titleGlow = self.attachAsset('titleImage', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0,
scaleY: 0,
alpha: 0.2,
tint: 0xFFFFFF
});
titleGlow.x = 1024;
titleGlow.y = 700;
self.addChildAt(titleGlow, self.getChildIndex(titleImage));
// Enhanced glow animation
tween(titleGlow, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 1100,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Continuous pulsing glow effect
function pulseGlow() {
tween(titleGlow, {
alpha: 0.8,
scaleX: 1.4,
scaleY: 1.4
}, {
duration: 1800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(titleGlow, {
alpha: 0.2,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1800,
easing: tween.easeInOut,
onFinish: pulseGlow
});
}
});
}
pulseGlow();
}
});
// Enhanced start button with image background
var startButtonBg = self.attachAsset('startButtonBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1
});
startButtonBg.x = 1024;
startButtonBg.y = 1950;
self.addChild(startButtonBg);
// Start button image overlay - removed bow as requested
// Button entrance animation
LK.setTimeout(function () {
tween(startButtonBg, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 600,
easing: tween.elasticOut
});
// Bow animation removed as bow is no longer present
}, 1200);
// Button hover effect
function animateButton() {
tween(startButtonBg, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(startButtonBg, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: animateButton
});
}
});
}
LK.setTimeout(animateButton, 2000);
// Start button click handler - make the whole button area clickable
startButtonBg.down = function (x, y, obj) {
// Button press animation
tween(startButtonBg, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(startButtonBg, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
// Transition to game scene
showGameScene();
}
});
}
});
};
return self;
});
var Platform = Container.expand(function () {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var Star = Container.expand(function () {
var self = Container.call(this);
var starGraphics = self.attachAsset('starBonus', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
tint: 0xFFD700 // Golden color
});
self.hit = false;
self.getHit = function () {
if (self.hit) return;
self.hit = true;
// Clear all fruits to complete level immediately
for (var i = fruits.length - 1; i >= 0; i--) {
var fruit = fruits[i];
LK.setScore(LK.getScore() + fruit.points);
fruit.destroy();
fruits.splice(i, 1);
}
scoreTxt.setText(LK.getScore());
// Flash effect
LK.effects.flashObject(self, 0xFFD700, 300);
// Remove from stars array
for (var i = stars.length - 1; i >= 0; i--) {
if (stars[i] === self) {
stars.splice(i, 1);
break;
}
}
// Animate star disappearing
tween(self, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
LK.getSound('starBonus').play();
// Update arrows display to show bonus effect
var remainingArrows = Math.max(0, Math.min(5, maxArrows || 5) - arrows.length);
arrowsTxt.setText('Arrows: ' + remainingArrows);
// Show level complete animation immediately
showLevelCompleteAnimation();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000 // Black background as fallback
});
/****
* Game Code
****/
// Menu scene
var menuScene = null;
var gameStarted = false;
function showMenuScene() {
// Clear game elements if they exist
if (gameStarted) {
// Clear all game objects
for (var i = 0; i < arrows.length; i++) {
arrows[i].destroy();
}
arrows = [];
for (var i = 0; i < fruits.length; i++) {
fruits[i].destroy();
}
fruits = [];
for (var i = 0; i < platforms.length; i++) {
platforms[i].destroy();
}
platforms = [];
for (var i = 0; i < bombs.length; i++) {
bombs[i].destroy();
}
bombs = [];
for (var i = 0; i < arrowBonuses.length; i++) {
arrowBonuses[i].destroy();
}
arrowBonuses = [];
for (var i = 0; i < stars.length; i++) {
stars[i].destroy();
}
stars = [];
for (var i = 0; i < clouds.length; i++) {
clouds[i].destroy();
}
clouds = [];
if (archer) {
archer.destroy();
archer = null;
}
}
// Create and show menu
menuScene = new Menu();
game.addChild(menuScene);
gameStarted = false;
}
// Define showLevelCompleteAnimation in global scope
function showLevelCompleteAnimation() {
// Play level complete sound for level completion
LK.getSound('levelComplete').play();
// Create a large golden star in the center of the screen
var star = LK.getAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0,
scaleY: 0,
alpha: 0,
tint: 0xFFD700 // Golden color
});
star.x = 1024; // Center of screen horizontally (2048/2)
star.y = 1366; // Center of screen vertically (2732/2)
game.addChild(star);
// Simple growing animation
tween(star, {
scaleX: 2.5,
scaleY: 2.5,
alpha: 1
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
// Fade out after growing
tween(star, {
alpha: 0
}, {
duration: 400,
easing: tween.easeIn,
onFinish: function onFinish() {
star.destroy();
// After star animation completes, proceed to next level
LK.setTimeout(function () {
var currentLevel = Math.floor(LK.getScore() / 200) + 1;
var nextTargetScore = currentLevel * 200;
if (LK.getScore() >= targetScore) {
targetScore = nextTargetScore + 200;
targetTxt.setText('Target: ' + targetScore);
spawnFruits();
} else {
spawnFruits();
}
}, 100);
}
});
}
});
}
// Define spawnFruits function in global scope so it can be accessed from anywhere
function spawnFruits() {
// Clear existing fruits
for (var i = 0; i < fruits.length; i++) {
fruits[i].destroy();
}
fruits = [];
// Clear existing bombs
for (var i = 0; i < bombs.length; i++) {
bombs[i].destroy();
}
bombs = [];
// Clear existing arrow bonuses
for (var i = 0; i < arrowBonuses.length; i++) {
arrowBonuses[i].destroy();
}
arrowBonuses = [];
// Clear existing stars
for (var i = 0; i < stars.length; i++) {
stars[i].destroy();
}
stars = [];
// Clear all arrows (including those stuck on platforms)
for (var i = 0; i < arrows.length; i++) {
arrows[i].destroy();
}
arrows = [];
// Ensure enough arrows for the number of fruits (minimum 3, but at least equal to fruits)
var currentLevel = Math.floor(LK.getScore() / 200) + 1;
var baseArrows = Math.max(3, 6 - Math.floor(currentLevel / 2));
var calculatedArrows = Math.max(baseArrows, numFruits + 1);
maxArrows = Math.min(5, calculatedArrows); // Always have at least 1 more arrow than fruits, but max 5
// Clear existing platforms
for (var i = 0; i < platforms.length; i++) {
platforms[i].destroy();
}
platforms = [];
var fruitTypes = ['apple', 'orange', 'banana'];
// Calculate level based on score progression
var currentLevel = Math.floor(LK.getScore() / 200) + 1;
// Increase number of fruits with each level (start with 2, add 1 every 2 levels, max 6)
var numFruits = Math.min(6, 2 + Math.floor(currentLevel / 2));
for (var i = 0; i < numFruits; i++) {
// Create platform with collision detection
var platform = new Platform();
var validPosition = false;
var attempts = 0;
while (!validPosition && attempts < 50) {
// Make platforms more spread out and harder to reach in higher levels
var currentLevel = Math.floor(LK.getScore() / 200) + 1;
var spreadFactor = Math.min(2, 1 + currentLevel * 0.2);
// Ensure platforms stay within screen boundaries and don't appear too low
var maxX = 2048 - 150; // Right boundary
var maxY = 1800; // Bottom boundary - prevent platforms from appearing too low
var minX = 150; // Left boundary
var minY = 600; // Top boundary - keep platforms in middle area
platform.x = Math.max(minX, Math.min(maxX, 600 + Math.random() * (800 * spreadFactor)));
platform.y = Math.max(minY, Math.min(maxY, 800 + Math.random() * (1000 * spreadFactor)));
validPosition = true;
// Check distance from character to ensure platforms spawn far away
var distanceFromCharacter = Math.sqrt((platform.x - 300) * (platform.x - 300) + (platform.y - 1366) * (platform.y - 1366));
if (distanceFromCharacter < 500) {
validPosition = false;
}
// Check collision with existing platforms
for (var j = 0; j < platforms.length; j++) {
var existingPlatform = platforms[j];
var dx = platform.x - existingPlatform.x;
var dy = platform.y - existingPlatform.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 400) {
// Minimum distance between platforms
validPosition = false;
break;
}
}
attempts++;
}
platforms.push(platform);
game.addChild(platform);
// Create fruit on platform
var fruitType = fruitTypes[Math.floor(Math.random() * fruitTypes.length)];
var fruit = new Fruit(fruitType);
fruit.x = platform.x;
fruit.y = platform.y - 80; // Position above platform
fruits.push(fruit);
game.addChild(fruit);
// Start idle animation immediately for all fruits
fruit.startIdleAnimation();
}
// Create separate platforms for bombs
// Calculate level based on score progression (every 200 points is roughly a level)
var currentLevel = Math.floor(LK.getScore() / 200) + 1;
// Increase bomb count with each level, starting with 1 every 2 levels, maximum 3
var numBombs = Math.min(3, Math.floor(currentLevel / 2));
for (var i = 0; i < numBombs; i++) {
// Create bomb platform with collision detection
var bombPlatform = new Platform();
var validPosition = false;
var attempts = 0;
while (!validPosition && attempts < 50) {
// Make bomb platforms more spread out and harder to avoid in higher levels
var currentLevel = Math.floor(LK.getScore() / 200) + 1;
var spreadFactor = Math.min(2, 1 + currentLevel * 0.2);
// Ensure bomb platforms stay within screen boundaries and don't appear too low
var maxX = 2048 - 150; // Right boundary
var maxY = 1800; // Bottom boundary - prevent platforms from appearing too low
var minX = 150; // Left boundary
var minY = 600; // Top boundary - keep platforms in middle area
bombPlatform.x = Math.max(minX, Math.min(maxX, 600 + Math.random() * (800 * spreadFactor)));
bombPlatform.y = Math.max(minY, Math.min(maxY, 800 + Math.random() * (1000 * spreadFactor)));
validPosition = true;
// Check distance from character to ensure bomb platforms spawn far away
var distanceFromCharacter = Math.sqrt((bombPlatform.x - 300) * (bombPlatform.x - 300) + (bombPlatform.y - 1366) * (bombPlatform.y - 1366));
if (distanceFromCharacter < 500) {
validPosition = false;
}
// Check collision with existing platforms (both fruit and bomb platforms)
for (var j = 0; j < platforms.length; j++) {
var existingPlatform = platforms[j];
var dx = bombPlatform.x - existingPlatform.x;
var dy = bombPlatform.y - existingPlatform.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 400) {
// Minimum distance between platforms
validPosition = false;
break;
}
}
attempts++;
}
platforms.push(bombPlatform);
game.addChild(bombPlatform);
// Create bomb on its own platform
var bomb = new Bomb();
bomb.x = bombPlatform.x;
bomb.y = bombPlatform.y - 75; // Position above platform
bombs.push(bomb);
game.addChild(bomb);
}
// Create arrow bonuses (only sometimes, based on level)
var currentLevel = Math.floor(LK.getScore() / 200) + 1;
// 60% chance to spawn arrow bonus, but only every 2-3 levels
var shouldSpawnBonus = Math.random() < 0.6 && currentLevel > 1 && (currentLevel % 2 === 0 || currentLevel % 3 === 0);
if (shouldSpawnBonus) {
// Create arrow bonus platform with collision detection
var bonusPlatform = new Platform();
var validPosition = false;
var attempts = 0;
while (!validPosition && attempts < 50) {
// Ensure bonus platforms stay within screen boundaries and don't appear too low
var maxX = 2048 - 150; // Right boundary
var maxY = 1800; // Bottom boundary - prevent platforms from appearing too low
var minX = 150; // Left boundary
var minY = 600; // Top boundary - keep platforms in middle area
bonusPlatform.x = Math.max(minX, Math.min(maxX, 600 + Math.random() * 800));
bonusPlatform.y = Math.max(minY, Math.min(maxY, 800 + Math.random() * 1200));
validPosition = true;
// Check distance from character to ensure bonus platforms spawn far away
var distanceFromCharacter = Math.sqrt((bonusPlatform.x - 300) * (bonusPlatform.x - 300) + (bonusPlatform.y - 1366) * (bonusPlatform.y - 1366));
if (distanceFromCharacter < 500) {
validPosition = false;
}
// Check collision with existing platforms
for (var j = 0; j < platforms.length; j++) {
var existingPlatform = platforms[j];
var dx = bonusPlatform.x - existingPlatform.x;
var dy = bonusPlatform.y - existingPlatform.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 400) {
validPosition = false;
break;
}
}
attempts++;
}
platforms.push(bonusPlatform);
game.addChild(bonusPlatform);
// Create arrow bonus on platform
var arrowBonus = new ArrowBonus();
arrowBonus.x = bonusPlatform.x;
arrowBonus.y = bonusPlatform.y - 75; // Position above platform
arrowBonuses.push(arrowBonus);
game.addChild(arrowBonus);
}
// Create star bonuses (more frequent random appearance)
var currentLevel = Math.floor(LK.getScore() / 200) + 1;
// 30% chance to spawn, completely random regardless of level
var shouldSpawnStar = Math.random() < 0.30 && currentLevel > 1;
if (shouldSpawnStar) {
// Create star platform in a very difficult to reach position
var starPlatform = new Platform();
var validPosition = false;
var attempts = 0;
while (!validPosition && attempts < 50) {
// Place in very hard to reach areas - corners and edges of map
var cornerChoice = Math.floor(Math.random() * 4);
// Define screen boundaries and prevent stars from appearing too low
var maxX = 2048 - 150; // Right boundary
var maxY = 1600; // Bottom boundary - prevent stars from appearing too low
var minX = 150; // Left boundary
var minY = 500; // Top boundary - keep stars in middle-upper area
if (cornerChoice === 0) {
// Top right corner
starPlatform.x = Math.max(minX, Math.min(maxX, 1400 + Math.random() * 500));
starPlatform.y = Math.max(minY, Math.min(maxY, 600 + Math.random() * 400));
} else if (cornerChoice === 1) {
// Bottom right corner
starPlatform.x = Math.max(minX, Math.min(maxX, 1300 + Math.random() * 600));
starPlatform.y = Math.max(minY, Math.min(maxY, 1200 + Math.random() * 400));
} else if (cornerChoice === 2) {
// Top center (high up)
starPlatform.x = Math.max(minX, Math.min(maxX, 800 + Math.random() * 800));
starPlatform.y = Math.max(minY, Math.min(maxY, 500 + Math.random() * 300));
} else {
// Far right edge
starPlatform.x = Math.max(minX, Math.min(maxX, 1600 + Math.random() * 300));
starPlatform.y = Math.max(minY, Math.min(maxY, 1000 + Math.random() * 600));
}
validPosition = true;
// Ensure star platforms spawn very far from character (harder to reach)
var distanceFromCharacter = Math.sqrt((starPlatform.x - 300) * (starPlatform.x - 300) + (starPlatform.y - 1366) * (starPlatform.y - 1366));
if (distanceFromCharacter < 700) {
validPosition = false;
}
// Check collision with existing platforms
for (var j = 0; j < platforms.length; j++) {
var existingPlatform = platforms[j];
var dx = starPlatform.x - existingPlatform.x;
var dy = starPlatform.y - existingPlatform.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 350) {
validPosition = false;
break;
}
}
attempts++;
}
platforms.push(starPlatform);
game.addChild(starPlatform);
// Create star on platform - make it smaller and harder to hit
var star = new Star();
star.x = starPlatform.x;
star.y = starPlatform.y - 75; // Position above platform
// Make star smaller and harder to hit
star.scaleX = 0.8;
star.scaleY = 0.8;
stars.push(star);
game.addChild(star);
}
}
function showGameScene() {
// Remove menu scene
if (menuScene) {
menuScene.destroy();
menuScene = null;
}
// Initialize game scene
gameStarted = true;
// Add background image
var backgroundImage = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
scaleX: 1,
scaleY: 1
});
game.addChildAt(backgroundImage, 0); // Add to back layer
// Initialize game variables
arrows = [];
fruits = [];
platforms = [];
bombs = [];
arrowBonuses = [];
stars = [];
clouds = [];
groundVegetation = [];
maxArrows = 5;
targetScore = 200;
// Create ground vegetation (no bushes)
function createGroundVegetation() {
// No ground vegetation to create
}
// Create background clouds
function createClouds() {
for (var i = 0; i < 8; i++) {
var cloud = LK.getAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7,
scaleX: 0.8 + Math.random() * 0.6,
scaleY: 0.6 + Math.random() * 0.4
});
cloud.x = Math.random() * 2200; // Spread across screen width plus some overflow
cloud.y = 300 + Math.random() * 600; // Position clouds in more visible area
cloud.speed = 0.3 + Math.random() * 0.7; // Random slow speed
clouds.push(cloud);
game.addChildAt(cloud, 1); // Add above background layer
// Start floating animation
animateCloud(cloud);
}
}
function animateCloud(cloud) {
var floatRange = 30 + Math.random() * 40;
var originalY = cloud.y;
tween(cloud, {
y: originalY - floatRange
}, {
duration: 3000 + Math.random() * 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(cloud, {
y: originalY + floatRange
}, {
duration: 3000 + Math.random() * 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
animateCloud(cloud);
}
});
}
});
}
// Create archer
archer = new Archer();
archer.x = 300;
archer.y = 1366;
game.addChild(archer);
// Create score display
scoreTxt = new Text2('0', {
size: 100,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create target score display
targetTxt = new Text2('Target: ' + targetScore, {
size: 60,
fill: 0xFFFF00
});
targetTxt.anchor.set(1, 0);
targetTxt.y = 120;
LK.gui.topRight.addChild(targetTxt);
// Create arrows remaining display
arrowsTxt = new Text2('Arrows: ' + maxArrows, {
size: 60,
fill: 0xFFFFFF
});
arrowsTxt.anchor.set(0, 0);
arrowsTxt.y = 120;
LK.gui.topLeft.addChild(arrowsTxt);
// Initialize clouds background
createClouds();
// Initialize ground vegetation
createGroundVegetation();
// Play background music
LK.playMusic('Fondo');
// Initialize first level
spawnFruits();
}
// Declare game variables in global scope
var arrows = [];
var fruits = [];
var platforms = [];
var bombs = [];
var arrowBonuses = [];
var stars = [];
var clouds = [];
var groundVegetation = [];
var maxArrows = 5;
var targetScore = 200;
var archer = null;
var scoreTxt = null;
var targetTxt = null;
var arrowsTxt = null;
// Start with menu scene
showMenuScene();
// Mouse controls
var mouseX = 0;
var mouseY = 0;
var currentPower = 12; // Default power
game.move = function (x, y, obj) {
if (!gameStarted || !archer) return;
mouseX = x;
mouseY = y;
// Update archer aiming
archer.aimAt(x, y);
// Calculate power based on distance from archer position
var dx = x - 300;
var dy = y - 1366;
var distance = Math.sqrt(dx * dx + dy * dy);
// Scale power based on distance (minimum 12, maximum 28)
currentPower = Math.min(28, Math.max(12, distance / 25));
};
game.down = function (x, y, obj) {
if (!gameStarted || !archer) return;
mouseX = x;
mouseY = y;
// Update archer aiming
archer.aimAt(x, y);
// Calculate power based on distance from archer position
var dx = x - 300;
var dy = y - 1366;
var distance = Math.sqrt(dx * dx + dy * dy);
// Scale power based on distance from archer position (minimum 12, maximum 28)
currentPower = Math.min(28, Math.max(12, distance / 25));
// Use archer's shoot method
archer.shoot();
// Update arrows remaining display
if (arrowsTxt) {
arrowsTxt.setText('Arrows: ' + (maxArrows - arrows.length));
}
};
game.update = function () {
if (!gameStarted) return;
// Check arrow-fruit collisions
for (var i = arrows.length - 1; i >= 0; i--) {
var arrow = arrows[i];
if (!arrow.active) continue;
// Check bomb collisions first
for (var j = 0; j < bombs.length; j++) {
var bomb = bombs[j];
if (!bomb.hit) {
// Use distance-based collision for larger bomb sprites
var dx = arrow.x - bomb.x;
var dy = arrow.y - bomb.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 80) {
arrow.active = false;
bomb.getHit();
arrow.destroy();
arrows.splice(i, 1);
return; // Exit immediately as game will be over
}
}
}
// Check arrow bonus collisions
for (var j = 0; j < arrowBonuses.length; j++) {
var arrowBonus = arrowBonuses[j];
if (!arrowBonus.hit) {
// Use distance-based collision for larger arrow bonus sprites
var dx = arrow.x - arrowBonus.x;
var dy = arrow.y - arrowBonus.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 70) {
arrow.active = false;
arrowBonus.getHit();
arrow.destroy();
arrows.splice(i, 1);
break;
}
}
}
// Check star collisions with smaller hit area (harder to hit)
for (var j = 0; j < stars.length; j++) {
var star = stars[j];
if (!star.hit) {
// Use distance-based collision with smaller radius for stars (harder to hit)
var dx = arrow.x - star.x;
var dy = arrow.y - star.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Collision radius for star sprites (40 pixels)
if (distance < 40) {
arrow.active = false;
star.getHit();
arrow.destroy();
arrows.splice(i, 1);
break;
}
}
}
for (var j = 0; j < fruits.length; j++) {
var fruit = fruits[j];
if (!fruit.hit) {
// Calculate distance between arrow and fruit center for larger collision
var dx = arrow.x - fruit.x;
var dy = arrow.y - fruit.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Use collision radius for fruits (80 pixels)
if (distance < 80) {
arrow.active = false;
fruit.getHit();
arrow.destroy();
arrows.splice(i, 1);
break;
}
}
}
}
// Give bonus arrows if player is struggling (every 10 seconds when out of arrows)
if (arrows.length >= maxArrows && fruits.length > 0) {
if (!game.lastBonusTime) game.lastBonusTime = 0;
if (LK.ticks - game.lastBonusTime > 600) {
// 10 seconds at 60fps
maxArrows = Math.min(5, maxArrows + 2); // Give 2 bonus arrows but respect maximum
game.lastBonusTime = LK.ticks;
arrowsTxt.setText('Arrows: ' + Math.max(0, maxArrows - arrows.length));
}
}
// Check if out of arrows and no fruits hit recently
if (arrows.length >= maxArrows && fruits.length > 0) {
var allArrowsStopped = true;
for (var i = 0; i < arrows.length; i++) {
if (arrows[i].active && (Math.abs(arrows[i].velocityX) > 0.5 || Math.abs(arrows[i].velocityY) > 0.5)) {
allArrowsStopped = false;
break;
}
}
if (allArrowsStopped) {
// Clear all arrows
for (var i = 0; i < arrows.length; i++) {
arrows[i].destroy();
}
arrows = [];
arrowsTxt.setText('Arrows: ' + maxArrows);
// Check if we have enough score to win
if (LK.getScore() >= targetScore) {
LK.showYouWin();
} else if (fruits.length > 0) {
// Game over if no arrows left and fruits still remain
LK.showGameOver();
}
}
}
// Update clouds movement
for (var i = 0; i < clouds.length; i++) {
var cloud = clouds[i];
cloud.x += cloud.speed;
// Reset cloud position when it goes off screen
if (cloud.x > 2200) {
cloud.x = -200;
cloud.y = 300 + Math.random() * 600; // Match new cloud positioning
}
}
// Update arrows remaining display
var remainingArrows = Math.max(0, Math.min(5, maxArrows || 5) - arrows.length);
arrowsTxt.setText('Arrows: ' + remainingArrows);
// Check for game over only when all arrows have been shot AND all arrows have settled
if (remainingArrows <= 0 && fruits.length > 0) {
// Only trigger game over if all arrows have stopped moving (settled on platforms)
var allArrowsStopped = true;
for (var i = 0; i < arrows.length; i++) {
if (arrows[i].active && (Math.abs(arrows[i].velocityX) > 0.5 || Math.abs(arrows[i].velocityY) > 0.5)) {
allArrowsStopped = false;
break;
}
}
if (allArrowsStopped) {
// Game over if no arrows left, all arrows settled, and fruits still remain
LK.showGameOver();
}
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Archer = Container.expand(function () {
var self = Container.call(this);
var bowGraphics = self.attachAsset('bow', {
anchorX: 0.5,
anchorY: 0.5
});
self.bow = bowGraphics;
self.aimAngle = 0;
self.aimAt = function (targetX, targetY) {
var dx = targetX - (self.x + self.bow.x);
var dy = targetY - (self.y + self.bow.y);
self.aimAngle = Math.atan2(dy, dx);
self.bow.rotation = self.aimAngle;
};
self.shoot = function () {
// Only allow shooting if we haven't reached the maximum number of arrows
if (arrows.length >= maxArrows) return; // No more arrows can be shot
var arrow = new Arrow();
var bowWorldX = self.x + self.bow.x + Math.cos(self.aimAngle) * 40;
var bowWorldY = self.y + self.bow.y + Math.sin(self.aimAngle) * 40;
arrow.x = bowWorldX;
arrow.y = bowWorldY;
arrow.rotation = self.aimAngle;
var power = currentPower; // Use dynamic power based on mouse distance
arrow.velocityX = Math.cos(self.aimAngle) * power;
arrow.velocityY = Math.sin(self.aimAngle) * power;
arrows.push(arrow);
game.addChild(arrow);
LK.getSound('shoot').play();
};
return self;
});
var Arrow = Container.expand(function () {
var self = Container.call(this);
var arrowGraphics = self.attachAsset('arrow', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.gravity = 0.3;
self.active = true;
self.update = function () {
if (!self.active) return;
self.x += self.velocityX;
self.y += self.velocityY;
self.velocityY += self.gravity;
// Update arrow rotation to follow movement direction
if (self.velocityX !== 0 || self.velocityY !== 0) {
self.rotation = Math.atan2(self.velocityY, self.velocityX);
}
// Check platform collisions with smaller collision area
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
// Calculate distance between arrow and platform center
var dx = self.x - platform.x;
var dy = self.y - platform.y;
// Reduce vertical collision sensitivity by using separate X and Y checks
var horizontalDistance = Math.abs(dx);
var verticalDistance = Math.abs(dy);
// Use collision radius for platforms (100 pixels horizontal, 60 pixels vertical)
if (horizontalDistance < 100 && verticalDistance < 60) {
self.active = false;
self.velocityX = 0;
self.velocityY = 0;
break;
}
}
// Remove arrow if it goes off screen
// Remove arrow if it goes off screen
if (self.x > 2100 || self.y > 2800 || self.x < -50 || self.y < -50) {
// Give bonus points if arrow didn't hit any platform
if (self.active) {
LK.setScore(LK.getScore() + 5);
scoreTxt.setText(LK.getScore());
}
self.destroy();
for (var i = arrows.length - 1; i >= 0; i--) {
if (arrows[i] === self) {
arrows.splice(i, 1);
break;
}
}
}
};
return self;
});
var ArrowBonus = Container.expand(function () {
var self = Container.call(this);
var bonusGraphics = self.attachAsset('arrowBonus', {
anchorX: 0.5,
anchorY: 0.5
});
self.hit = false;
self.getHit = function () {
if (self.hit) return;
self.hit = true;
// Add random amount of arrows (2-4) directly to available arrows
var bonusArrows = Math.floor(Math.random() * 3) + 2;
maxArrows = Math.min(5, maxArrows + bonusArrows);
// Flash effect
LK.effects.flashObject(self, 0x00ff00, 300);
// Remove from arrowBonuses array
for (var i = arrowBonuses.length - 1; i >= 0; i--) {
if (arrowBonuses[i] === self) {
arrowBonuses.splice(i, 1);
break;
}
}
// Animate bonus disappearing
tween(self, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
LK.getSound('arrowBonus').play();
// Update arrows display
var remainingArrows = Math.max(0, Math.min(5, maxArrows || 5) - arrows.length);
arrowsTxt.setText('Arrows: ' + remainingArrows);
};
return self;
});
var Bomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
self.hit = false;
self.getHit = function () {
if (self.hit) return;
self.hit = true;
// Flash effect
LK.effects.flashObject(self, 0xff0000, 300);
// Remove from bombs array
for (var i = bombs.length - 1; i >= 0; i--) {
if (bombs[i] === self) {
bombs.splice(i, 1);
break;
}
}
// Flash screen red and show game over
LK.effects.flashScreen(0xff0000, 1000);
LK.getSound('explosion').play();
// Animate bomb explosion
tween(self, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
// Show game over after explosion animation
LK.setTimeout(function () {
LK.showGameOver();
}, 200);
}
});
};
return self;
});
var Fruit = Container.expand(function (type) {
var self = Container.call(this);
var fruitType = type || 'apple';
var fruitGraphics = self.attachAsset(fruitType, {
anchorX: 0.5,
anchorY: 0.5
});
self.fruitType = fruitType;
self.points = fruitType === 'apple' ? 10 : fruitType === 'orange' ? 15 : 20;
self.hit = false;
// Start idle floating animation
self.startIdleAnimation = function () {
var animationDuration = 1500 + Math.random() * 1000; // 1.5-2.5 seconds
var moveRange = 8 + Math.random() * 12; // 8-20 pixels movement
if (self.initialY === undefined) {
self.initialY = self.y; // Store the original position only once
}
// Find the platform this fruit is on
var platformY = self.initialY + 60; // Platform is 60 pixels below fruit
// Limit upward movement to not go above initial position too much
var upwardY = self.initialY - moveRange;
// Limit downward movement to not go below platform level
var downwardY = Math.min(self.initialY + moveRange, platformY - 50);
tween(self, {
y: upwardY
}, {
duration: animationDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (!self.hit) {
tween(self, {
y: downwardY
}, {
duration: animationDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (!self.hit) {
self.startIdleAnimation();
}
}
});
}
}
});
};
self.getHit = function () {
if (self.hit) return;
self.hit = true;
LK.setScore(LK.getScore() + self.points);
scoreTxt.setText(LK.getScore());
// Flash effect
LK.effects.flashObject(self, 0xFFFFFF, 300);
// Remove from fruits array
for (var i = fruits.length - 1; i >= 0; i--) {
if (fruits[i] === self) {
fruits.splice(i, 1);
break;
}
}
// Only remove arrows when level is completed (no fruits remain)
// The arrows will be cleared when spawnFruits() is called for next level
// Create explosion/disintegration effect
tween(self, {
scaleX: 1.5,
scaleY: 1.5,
rotation: Math.PI * 2
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
// Second phase: shrink and fade out
tween(self, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
self.destroy();
}
});
}
});
LK.getSound('hit').play();
// Check win condition
if (fruits.length === 0) {
// Show level complete animation immediately
showLevelCompleteAnimation();
}
};
return self;
});
var Menu = Container.expand(function () {
var self = Container.call(this);
// Animated background layers
var menuBg1 = self.attachAsset('menuBg1', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
alpha: 1
});
var menuBg2 = self.attachAsset('menuBg2', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
alpha: 0.7
});
self.addChild(menuBg2);
// Background stars removed as requested
// Animate background layers
tween(menuBg2, {
alpha: 0.3
}, {
duration: 3000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(menuBg2, {
alpha: 0.7
}, {
duration: 3000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Continue background animation loop
}
});
}
});
// Animated title image
var titleImage = self.attachAsset('titleImage', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0,
scaleY: 0,
rotation: 0
});
titleImage.x = 1024;
titleImage.y = 700;
// Title entrance animation with continuous effects
tween(titleImage, {
scaleX: 1.2,
scaleY: 1.2,
rotation: Math.PI * 0.1
}, {
duration: 1000,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Continuous title animation loop
function animateTitle() {
tween(titleImage, {
scaleX: 1.1,
scaleY: 1.1,
rotation: -Math.PI * 0.05
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(titleImage, {
scaleX: 1.3,
scaleY: 1.3,
rotation: Math.PI * 0.05
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: animateTitle
});
}
});
}
animateTitle();
}
});
// Title glow effect with enhanced animation using duplicate image
var titleGlow = self.attachAsset('titleImage', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0,
scaleY: 0,
alpha: 0.2,
tint: 0xFFFFFF
});
titleGlow.x = 1024;
titleGlow.y = 700;
self.addChildAt(titleGlow, self.getChildIndex(titleImage));
// Enhanced glow animation
tween(titleGlow, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 1100,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Continuous pulsing glow effect
function pulseGlow() {
tween(titleGlow, {
alpha: 0.8,
scaleX: 1.4,
scaleY: 1.4
}, {
duration: 1800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(titleGlow, {
alpha: 0.2,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1800,
easing: tween.easeInOut,
onFinish: pulseGlow
});
}
});
}
pulseGlow();
}
});
// Enhanced start button with image background
var startButtonBg = self.attachAsset('startButtonBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1
});
startButtonBg.x = 1024;
startButtonBg.y = 1950;
self.addChild(startButtonBg);
// Start button image overlay - removed bow as requested
// Button entrance animation
LK.setTimeout(function () {
tween(startButtonBg, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 600,
easing: tween.elasticOut
});
// Bow animation removed as bow is no longer present
}, 1200);
// Button hover effect
function animateButton() {
tween(startButtonBg, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(startButtonBg, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: animateButton
});
}
});
}
LK.setTimeout(animateButton, 2000);
// Start button click handler - make the whole button area clickable
startButtonBg.down = function (x, y, obj) {
// Button press animation
tween(startButtonBg, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(startButtonBg, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
// Transition to game scene
showGameScene();
}
});
}
});
};
return self;
});
var Platform = Container.expand(function () {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var Star = Container.expand(function () {
var self = Container.call(this);
var starGraphics = self.attachAsset('starBonus', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
tint: 0xFFD700 // Golden color
});
self.hit = false;
self.getHit = function () {
if (self.hit) return;
self.hit = true;
// Clear all fruits to complete level immediately
for (var i = fruits.length - 1; i >= 0; i--) {
var fruit = fruits[i];
LK.setScore(LK.getScore() + fruit.points);
fruit.destroy();
fruits.splice(i, 1);
}
scoreTxt.setText(LK.getScore());
// Flash effect
LK.effects.flashObject(self, 0xFFD700, 300);
// Remove from stars array
for (var i = stars.length - 1; i >= 0; i--) {
if (stars[i] === self) {
stars.splice(i, 1);
break;
}
}
// Animate star disappearing
tween(self, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
LK.getSound('starBonus').play();
// Update arrows display to show bonus effect
var remainingArrows = Math.max(0, Math.min(5, maxArrows || 5) - arrows.length);
arrowsTxt.setText('Arrows: ' + remainingArrows);
// Show level complete animation immediately
showLevelCompleteAnimation();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000 // Black background as fallback
});
/****
* Game Code
****/
// Menu scene
var menuScene = null;
var gameStarted = false;
function showMenuScene() {
// Clear game elements if they exist
if (gameStarted) {
// Clear all game objects
for (var i = 0; i < arrows.length; i++) {
arrows[i].destroy();
}
arrows = [];
for (var i = 0; i < fruits.length; i++) {
fruits[i].destroy();
}
fruits = [];
for (var i = 0; i < platforms.length; i++) {
platforms[i].destroy();
}
platforms = [];
for (var i = 0; i < bombs.length; i++) {
bombs[i].destroy();
}
bombs = [];
for (var i = 0; i < arrowBonuses.length; i++) {
arrowBonuses[i].destroy();
}
arrowBonuses = [];
for (var i = 0; i < stars.length; i++) {
stars[i].destroy();
}
stars = [];
for (var i = 0; i < clouds.length; i++) {
clouds[i].destroy();
}
clouds = [];
if (archer) {
archer.destroy();
archer = null;
}
}
// Create and show menu
menuScene = new Menu();
game.addChild(menuScene);
gameStarted = false;
}
// Define showLevelCompleteAnimation in global scope
function showLevelCompleteAnimation() {
// Play level complete sound for level completion
LK.getSound('levelComplete').play();
// Create a large golden star in the center of the screen
var star = LK.getAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0,
scaleY: 0,
alpha: 0,
tint: 0xFFD700 // Golden color
});
star.x = 1024; // Center of screen horizontally (2048/2)
star.y = 1366; // Center of screen vertically (2732/2)
game.addChild(star);
// Simple growing animation
tween(star, {
scaleX: 2.5,
scaleY: 2.5,
alpha: 1
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
// Fade out after growing
tween(star, {
alpha: 0
}, {
duration: 400,
easing: tween.easeIn,
onFinish: function onFinish() {
star.destroy();
// After star animation completes, proceed to next level
LK.setTimeout(function () {
var currentLevel = Math.floor(LK.getScore() / 200) + 1;
var nextTargetScore = currentLevel * 200;
if (LK.getScore() >= targetScore) {
targetScore = nextTargetScore + 200;
targetTxt.setText('Target: ' + targetScore);
spawnFruits();
} else {
spawnFruits();
}
}, 100);
}
});
}
});
}
// Define spawnFruits function in global scope so it can be accessed from anywhere
function spawnFruits() {
// Clear existing fruits
for (var i = 0; i < fruits.length; i++) {
fruits[i].destroy();
}
fruits = [];
// Clear existing bombs
for (var i = 0; i < bombs.length; i++) {
bombs[i].destroy();
}
bombs = [];
// Clear existing arrow bonuses
for (var i = 0; i < arrowBonuses.length; i++) {
arrowBonuses[i].destroy();
}
arrowBonuses = [];
// Clear existing stars
for (var i = 0; i < stars.length; i++) {
stars[i].destroy();
}
stars = [];
// Clear all arrows (including those stuck on platforms)
for (var i = 0; i < arrows.length; i++) {
arrows[i].destroy();
}
arrows = [];
// Ensure enough arrows for the number of fruits (minimum 3, but at least equal to fruits)
var currentLevel = Math.floor(LK.getScore() / 200) + 1;
var baseArrows = Math.max(3, 6 - Math.floor(currentLevel / 2));
var calculatedArrows = Math.max(baseArrows, numFruits + 1);
maxArrows = Math.min(5, calculatedArrows); // Always have at least 1 more arrow than fruits, but max 5
// Clear existing platforms
for (var i = 0; i < platforms.length; i++) {
platforms[i].destroy();
}
platforms = [];
var fruitTypes = ['apple', 'orange', 'banana'];
// Calculate level based on score progression
var currentLevel = Math.floor(LK.getScore() / 200) + 1;
// Increase number of fruits with each level (start with 2, add 1 every 2 levels, max 6)
var numFruits = Math.min(6, 2 + Math.floor(currentLevel / 2));
for (var i = 0; i < numFruits; i++) {
// Create platform with collision detection
var platform = new Platform();
var validPosition = false;
var attempts = 0;
while (!validPosition && attempts < 50) {
// Make platforms more spread out and harder to reach in higher levels
var currentLevel = Math.floor(LK.getScore() / 200) + 1;
var spreadFactor = Math.min(2, 1 + currentLevel * 0.2);
// Ensure platforms stay within screen boundaries and don't appear too low
var maxX = 2048 - 150; // Right boundary
var maxY = 1800; // Bottom boundary - prevent platforms from appearing too low
var minX = 150; // Left boundary
var minY = 600; // Top boundary - keep platforms in middle area
platform.x = Math.max(minX, Math.min(maxX, 600 + Math.random() * (800 * spreadFactor)));
platform.y = Math.max(minY, Math.min(maxY, 800 + Math.random() * (1000 * spreadFactor)));
validPosition = true;
// Check distance from character to ensure platforms spawn far away
var distanceFromCharacter = Math.sqrt((platform.x - 300) * (platform.x - 300) + (platform.y - 1366) * (platform.y - 1366));
if (distanceFromCharacter < 500) {
validPosition = false;
}
// Check collision with existing platforms
for (var j = 0; j < platforms.length; j++) {
var existingPlatform = platforms[j];
var dx = platform.x - existingPlatform.x;
var dy = platform.y - existingPlatform.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 400) {
// Minimum distance between platforms
validPosition = false;
break;
}
}
attempts++;
}
platforms.push(platform);
game.addChild(platform);
// Create fruit on platform
var fruitType = fruitTypes[Math.floor(Math.random() * fruitTypes.length)];
var fruit = new Fruit(fruitType);
fruit.x = platform.x;
fruit.y = platform.y - 80; // Position above platform
fruits.push(fruit);
game.addChild(fruit);
// Start idle animation immediately for all fruits
fruit.startIdleAnimation();
}
// Create separate platforms for bombs
// Calculate level based on score progression (every 200 points is roughly a level)
var currentLevel = Math.floor(LK.getScore() / 200) + 1;
// Increase bomb count with each level, starting with 1 every 2 levels, maximum 3
var numBombs = Math.min(3, Math.floor(currentLevel / 2));
for (var i = 0; i < numBombs; i++) {
// Create bomb platform with collision detection
var bombPlatform = new Platform();
var validPosition = false;
var attempts = 0;
while (!validPosition && attempts < 50) {
// Make bomb platforms more spread out and harder to avoid in higher levels
var currentLevel = Math.floor(LK.getScore() / 200) + 1;
var spreadFactor = Math.min(2, 1 + currentLevel * 0.2);
// Ensure bomb platforms stay within screen boundaries and don't appear too low
var maxX = 2048 - 150; // Right boundary
var maxY = 1800; // Bottom boundary - prevent platforms from appearing too low
var minX = 150; // Left boundary
var minY = 600; // Top boundary - keep platforms in middle area
bombPlatform.x = Math.max(minX, Math.min(maxX, 600 + Math.random() * (800 * spreadFactor)));
bombPlatform.y = Math.max(minY, Math.min(maxY, 800 + Math.random() * (1000 * spreadFactor)));
validPosition = true;
// Check distance from character to ensure bomb platforms spawn far away
var distanceFromCharacter = Math.sqrt((bombPlatform.x - 300) * (bombPlatform.x - 300) + (bombPlatform.y - 1366) * (bombPlatform.y - 1366));
if (distanceFromCharacter < 500) {
validPosition = false;
}
// Check collision with existing platforms (both fruit and bomb platforms)
for (var j = 0; j < platforms.length; j++) {
var existingPlatform = platforms[j];
var dx = bombPlatform.x - existingPlatform.x;
var dy = bombPlatform.y - existingPlatform.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 400) {
// Minimum distance between platforms
validPosition = false;
break;
}
}
attempts++;
}
platforms.push(bombPlatform);
game.addChild(bombPlatform);
// Create bomb on its own platform
var bomb = new Bomb();
bomb.x = bombPlatform.x;
bomb.y = bombPlatform.y - 75; // Position above platform
bombs.push(bomb);
game.addChild(bomb);
}
// Create arrow bonuses (only sometimes, based on level)
var currentLevel = Math.floor(LK.getScore() / 200) + 1;
// 60% chance to spawn arrow bonus, but only every 2-3 levels
var shouldSpawnBonus = Math.random() < 0.6 && currentLevel > 1 && (currentLevel % 2 === 0 || currentLevel % 3 === 0);
if (shouldSpawnBonus) {
// Create arrow bonus platform with collision detection
var bonusPlatform = new Platform();
var validPosition = false;
var attempts = 0;
while (!validPosition && attempts < 50) {
// Ensure bonus platforms stay within screen boundaries and don't appear too low
var maxX = 2048 - 150; // Right boundary
var maxY = 1800; // Bottom boundary - prevent platforms from appearing too low
var minX = 150; // Left boundary
var minY = 600; // Top boundary - keep platforms in middle area
bonusPlatform.x = Math.max(minX, Math.min(maxX, 600 + Math.random() * 800));
bonusPlatform.y = Math.max(minY, Math.min(maxY, 800 + Math.random() * 1200));
validPosition = true;
// Check distance from character to ensure bonus platforms spawn far away
var distanceFromCharacter = Math.sqrt((bonusPlatform.x - 300) * (bonusPlatform.x - 300) + (bonusPlatform.y - 1366) * (bonusPlatform.y - 1366));
if (distanceFromCharacter < 500) {
validPosition = false;
}
// Check collision with existing platforms
for (var j = 0; j < platforms.length; j++) {
var existingPlatform = platforms[j];
var dx = bonusPlatform.x - existingPlatform.x;
var dy = bonusPlatform.y - existingPlatform.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 400) {
validPosition = false;
break;
}
}
attempts++;
}
platforms.push(bonusPlatform);
game.addChild(bonusPlatform);
// Create arrow bonus on platform
var arrowBonus = new ArrowBonus();
arrowBonus.x = bonusPlatform.x;
arrowBonus.y = bonusPlatform.y - 75; // Position above platform
arrowBonuses.push(arrowBonus);
game.addChild(arrowBonus);
}
// Create star bonuses (more frequent random appearance)
var currentLevel = Math.floor(LK.getScore() / 200) + 1;
// 30% chance to spawn, completely random regardless of level
var shouldSpawnStar = Math.random() < 0.30 && currentLevel > 1;
if (shouldSpawnStar) {
// Create star platform in a very difficult to reach position
var starPlatform = new Platform();
var validPosition = false;
var attempts = 0;
while (!validPosition && attempts < 50) {
// Place in very hard to reach areas - corners and edges of map
var cornerChoice = Math.floor(Math.random() * 4);
// Define screen boundaries and prevent stars from appearing too low
var maxX = 2048 - 150; // Right boundary
var maxY = 1600; // Bottom boundary - prevent stars from appearing too low
var minX = 150; // Left boundary
var minY = 500; // Top boundary - keep stars in middle-upper area
if (cornerChoice === 0) {
// Top right corner
starPlatform.x = Math.max(minX, Math.min(maxX, 1400 + Math.random() * 500));
starPlatform.y = Math.max(minY, Math.min(maxY, 600 + Math.random() * 400));
} else if (cornerChoice === 1) {
// Bottom right corner
starPlatform.x = Math.max(minX, Math.min(maxX, 1300 + Math.random() * 600));
starPlatform.y = Math.max(minY, Math.min(maxY, 1200 + Math.random() * 400));
} else if (cornerChoice === 2) {
// Top center (high up)
starPlatform.x = Math.max(minX, Math.min(maxX, 800 + Math.random() * 800));
starPlatform.y = Math.max(minY, Math.min(maxY, 500 + Math.random() * 300));
} else {
// Far right edge
starPlatform.x = Math.max(minX, Math.min(maxX, 1600 + Math.random() * 300));
starPlatform.y = Math.max(minY, Math.min(maxY, 1000 + Math.random() * 600));
}
validPosition = true;
// Ensure star platforms spawn very far from character (harder to reach)
var distanceFromCharacter = Math.sqrt((starPlatform.x - 300) * (starPlatform.x - 300) + (starPlatform.y - 1366) * (starPlatform.y - 1366));
if (distanceFromCharacter < 700) {
validPosition = false;
}
// Check collision with existing platforms
for (var j = 0; j < platforms.length; j++) {
var existingPlatform = platforms[j];
var dx = starPlatform.x - existingPlatform.x;
var dy = starPlatform.y - existingPlatform.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 350) {
validPosition = false;
break;
}
}
attempts++;
}
platforms.push(starPlatform);
game.addChild(starPlatform);
// Create star on platform - make it smaller and harder to hit
var star = new Star();
star.x = starPlatform.x;
star.y = starPlatform.y - 75; // Position above platform
// Make star smaller and harder to hit
star.scaleX = 0.8;
star.scaleY = 0.8;
stars.push(star);
game.addChild(star);
}
}
function showGameScene() {
// Remove menu scene
if (menuScene) {
menuScene.destroy();
menuScene = null;
}
// Initialize game scene
gameStarted = true;
// Add background image
var backgroundImage = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
scaleX: 1,
scaleY: 1
});
game.addChildAt(backgroundImage, 0); // Add to back layer
// Initialize game variables
arrows = [];
fruits = [];
platforms = [];
bombs = [];
arrowBonuses = [];
stars = [];
clouds = [];
groundVegetation = [];
maxArrows = 5;
targetScore = 200;
// Create ground vegetation (no bushes)
function createGroundVegetation() {
// No ground vegetation to create
}
// Create background clouds
function createClouds() {
for (var i = 0; i < 8; i++) {
var cloud = LK.getAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7,
scaleX: 0.8 + Math.random() * 0.6,
scaleY: 0.6 + Math.random() * 0.4
});
cloud.x = Math.random() * 2200; // Spread across screen width plus some overflow
cloud.y = 300 + Math.random() * 600; // Position clouds in more visible area
cloud.speed = 0.3 + Math.random() * 0.7; // Random slow speed
clouds.push(cloud);
game.addChildAt(cloud, 1); // Add above background layer
// Start floating animation
animateCloud(cloud);
}
}
function animateCloud(cloud) {
var floatRange = 30 + Math.random() * 40;
var originalY = cloud.y;
tween(cloud, {
y: originalY - floatRange
}, {
duration: 3000 + Math.random() * 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(cloud, {
y: originalY + floatRange
}, {
duration: 3000 + Math.random() * 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
animateCloud(cloud);
}
});
}
});
}
// Create archer
archer = new Archer();
archer.x = 300;
archer.y = 1366;
game.addChild(archer);
// Create score display
scoreTxt = new Text2('0', {
size: 100,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create target score display
targetTxt = new Text2('Target: ' + targetScore, {
size: 60,
fill: 0xFFFF00
});
targetTxt.anchor.set(1, 0);
targetTxt.y = 120;
LK.gui.topRight.addChild(targetTxt);
// Create arrows remaining display
arrowsTxt = new Text2('Arrows: ' + maxArrows, {
size: 60,
fill: 0xFFFFFF
});
arrowsTxt.anchor.set(0, 0);
arrowsTxt.y = 120;
LK.gui.topLeft.addChild(arrowsTxt);
// Initialize clouds background
createClouds();
// Initialize ground vegetation
createGroundVegetation();
// Play background music
LK.playMusic('Fondo');
// Initialize first level
spawnFruits();
}
// Declare game variables in global scope
var arrows = [];
var fruits = [];
var platforms = [];
var bombs = [];
var arrowBonuses = [];
var stars = [];
var clouds = [];
var groundVegetation = [];
var maxArrows = 5;
var targetScore = 200;
var archer = null;
var scoreTxt = null;
var targetTxt = null;
var arrowsTxt = null;
// Start with menu scene
showMenuScene();
// Mouse controls
var mouseX = 0;
var mouseY = 0;
var currentPower = 12; // Default power
game.move = function (x, y, obj) {
if (!gameStarted || !archer) return;
mouseX = x;
mouseY = y;
// Update archer aiming
archer.aimAt(x, y);
// Calculate power based on distance from archer position
var dx = x - 300;
var dy = y - 1366;
var distance = Math.sqrt(dx * dx + dy * dy);
// Scale power based on distance (minimum 12, maximum 28)
currentPower = Math.min(28, Math.max(12, distance / 25));
};
game.down = function (x, y, obj) {
if (!gameStarted || !archer) return;
mouseX = x;
mouseY = y;
// Update archer aiming
archer.aimAt(x, y);
// Calculate power based on distance from archer position
var dx = x - 300;
var dy = y - 1366;
var distance = Math.sqrt(dx * dx + dy * dy);
// Scale power based on distance from archer position (minimum 12, maximum 28)
currentPower = Math.min(28, Math.max(12, distance / 25));
// Use archer's shoot method
archer.shoot();
// Update arrows remaining display
if (arrowsTxt) {
arrowsTxt.setText('Arrows: ' + (maxArrows - arrows.length));
}
};
game.update = function () {
if (!gameStarted) return;
// Check arrow-fruit collisions
for (var i = arrows.length - 1; i >= 0; i--) {
var arrow = arrows[i];
if (!arrow.active) continue;
// Check bomb collisions first
for (var j = 0; j < bombs.length; j++) {
var bomb = bombs[j];
if (!bomb.hit) {
// Use distance-based collision for larger bomb sprites
var dx = arrow.x - bomb.x;
var dy = arrow.y - bomb.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 80) {
arrow.active = false;
bomb.getHit();
arrow.destroy();
arrows.splice(i, 1);
return; // Exit immediately as game will be over
}
}
}
// Check arrow bonus collisions
for (var j = 0; j < arrowBonuses.length; j++) {
var arrowBonus = arrowBonuses[j];
if (!arrowBonus.hit) {
// Use distance-based collision for larger arrow bonus sprites
var dx = arrow.x - arrowBonus.x;
var dy = arrow.y - arrowBonus.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 70) {
arrow.active = false;
arrowBonus.getHit();
arrow.destroy();
arrows.splice(i, 1);
break;
}
}
}
// Check star collisions with smaller hit area (harder to hit)
for (var j = 0; j < stars.length; j++) {
var star = stars[j];
if (!star.hit) {
// Use distance-based collision with smaller radius for stars (harder to hit)
var dx = arrow.x - star.x;
var dy = arrow.y - star.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Collision radius for star sprites (40 pixels)
if (distance < 40) {
arrow.active = false;
star.getHit();
arrow.destroy();
arrows.splice(i, 1);
break;
}
}
}
for (var j = 0; j < fruits.length; j++) {
var fruit = fruits[j];
if (!fruit.hit) {
// Calculate distance between arrow and fruit center for larger collision
var dx = arrow.x - fruit.x;
var dy = arrow.y - fruit.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Use collision radius for fruits (80 pixels)
if (distance < 80) {
arrow.active = false;
fruit.getHit();
arrow.destroy();
arrows.splice(i, 1);
break;
}
}
}
}
// Give bonus arrows if player is struggling (every 10 seconds when out of arrows)
if (arrows.length >= maxArrows && fruits.length > 0) {
if (!game.lastBonusTime) game.lastBonusTime = 0;
if (LK.ticks - game.lastBonusTime > 600) {
// 10 seconds at 60fps
maxArrows = Math.min(5, maxArrows + 2); // Give 2 bonus arrows but respect maximum
game.lastBonusTime = LK.ticks;
arrowsTxt.setText('Arrows: ' + Math.max(0, maxArrows - arrows.length));
}
}
// Check if out of arrows and no fruits hit recently
if (arrows.length >= maxArrows && fruits.length > 0) {
var allArrowsStopped = true;
for (var i = 0; i < arrows.length; i++) {
if (arrows[i].active && (Math.abs(arrows[i].velocityX) > 0.5 || Math.abs(arrows[i].velocityY) > 0.5)) {
allArrowsStopped = false;
break;
}
}
if (allArrowsStopped) {
// Clear all arrows
for (var i = 0; i < arrows.length; i++) {
arrows[i].destroy();
}
arrows = [];
arrowsTxt.setText('Arrows: ' + maxArrows);
// Check if we have enough score to win
if (LK.getScore() >= targetScore) {
LK.showYouWin();
} else if (fruits.length > 0) {
// Game over if no arrows left and fruits still remain
LK.showGameOver();
}
}
}
// Update clouds movement
for (var i = 0; i < clouds.length; i++) {
var cloud = clouds[i];
cloud.x += cloud.speed;
// Reset cloud position when it goes off screen
if (cloud.x > 2200) {
cloud.x = -200;
cloud.y = 300 + Math.random() * 600; // Match new cloud positioning
}
}
// Update arrows remaining display
var remainingArrows = Math.max(0, Math.min(5, maxArrows || 5) - arrows.length);
arrowsTxt.setText('Arrows: ' + remainingArrows);
// Check for game over only when all arrows have been shot AND all arrows have settled
if (remainingArrows <= 0 && fruits.length > 0) {
// Only trigger game over if all arrows have stopped moving (settled on platforms)
var allArrowsStopped = true;
for (var i = 0; i < arrows.length; i++) {
if (arrows[i].active && (Math.abs(arrows[i].velocityX) > 0.5 || Math.abs(arrows[i].velocityY) > 0.5)) {
allArrowsStopped = false;
break;
}
}
if (allArrowsStopped) {
// Game over if no arrows left, all arrows settled, and fruits still remain
LK.showGameOver();
}
}
};
Estrella animada. In-Game asset. 2d. High contrast. No shadows
Estrella. In-Game asset. 2d. High contrast. No shadows
Nube. In-Game asset. 2d. High contrast. No shadows
Bush. In-Game asset. 2d. High contrast. No shadows
tree. In-Game asset. 2d. High contrast. No shadows
Quita los arboles y las nubes
Boton de start. In-Game asset. 2d. High contrast. No shadows
Fondo para un juego de fruit archer. In-Game asset. 2d. High contrast. No shadows
Fruit Archer titulo. In-Game asset. 2d. High contrast. No shadows