User prompt
ahora quisiera que los objetos que no podemos tocar aparezcan cada vez mas si seguimos pasando de nivel, maximo 5 objetos
User prompt
Que las flechas se borren de la infraestructura que se choco solo cuando hallamos pasado el nivel
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: 381
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: 381
User prompt
Pero al atinarle a las frutas, las flechas que se quedan en la infrastructura deberian borrarse
User prompt
Elimina la linea roja
User prompt
Quiero que esa linea roja nos indique hacia donde ira la flecha y que forma tomara ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Que esa linea tambien se doble, que se mueva, agranda o doble dependiendo de que forma tendra la flecha cuando se dispara ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Pero que lo que no podemos tocar tenga su propia plataforma
User prompt
Que sean 5 flechas y la persona este en el medio al lado izquierdo
User prompt
Ahora quisiera que pongas otro objeto que si la flecha le da, pierde el nivel
User prompt
Un poco mas de fuerza y que haya como una linea indicandonos la direccion que hara la flecha
User prompt
Un poco menos de fuerza para la flecha
User prompt
Quiero que la felcha no traspase la infraestructura donde esta la fruta
User prompt
mas potencia al disparo de la flecha y que las infraestructuras no choquen entre si
User prompt
Que el personaje y la infrestructura tengan la distancia adecuada para que la felcha les pueda dar
User prompt
Quiero que si el mouse esta mas lejos o mas cerca del personaje sea la potencia del disparo de la felcha
Code edit (1 edits merged)
Please save this source code
User prompt
Fruit Archer - Bow and Arrow Shooting Game
Initial prompt
Quisiera que una persona con arco y flecha este al lado izquierdo y que con el mouse podamos decidir la direccion donde disparara la felcha hacia infraestructuras con frutas donde la flecha le debe dar a las frutas.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Archer = Container.expand(function () {
var self = Container.call(this);
var archerGraphics = self.attachAsset('archer', {
anchorX: 0.5,
anchorY: 1.0
});
var bowGraphics = self.attachAsset('bow', {
anchorX: 0.2,
anchorY: 0.5
});
bowGraphics.x = 20;
bowGraphics.y = -60;
self.bow = bowGraphics;
self.aimAngle = 0;
var trajectoryGraphics = self.attachAsset('trajectoryLine', {
anchorX: 0,
anchorY: 0.5
});
trajectoryGraphics.alpha = 0.6;
trajectoryGraphics.visible = false;
self.trajectoryLine = trajectoryGraphics;
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;
// Show trajectory line
self.trajectoryLine.visible = true;
self.trajectoryLine.x = self.bow.x + Math.cos(self.aimAngle) * 30;
self.trajectoryLine.y = self.bow.y + Math.sin(self.aimAngle) * 30;
// Calculate trajectory curve based on power and gravity
var distance = Math.sqrt(dx * dx + dy * dy);
var power = Math.min(28, Math.max(12, distance / 25));
var velocityX = Math.cos(self.aimAngle) * power;
var velocityY = Math.sin(self.aimAngle) * power;
// Create curved trajectory visualization with multiple segments
var trajectoryPoints = [];
var simX = 0;
var simY = 0;
var simVelX = velocityX;
var simVelY = velocityY;
var gravity = 0.3;
var steps = 0;
var maxSteps = 60;
// Store initial point
trajectoryPoints.push({
x: simX,
y: simY
});
// Simulate trajectory and store points for curve visualization
while (steps < maxSteps && simY < 800 && simX < 1000 && simY > -200) {
simX += simVelX;
simY += simVelY;
simVelY += gravity;
// Store trajectory points every few steps for smoother curve
if (steps % 3 === 0) {
trajectoryPoints.push({
x: simX,
y: simY
});
}
steps++;
}
// Calculate the trajectory line properties based on the full simulated path
if (trajectoryPoints.length > 1) {
var lastPoint = trajectoryPoints[trajectoryPoints.length - 1];
var trajectoryLength = Math.sqrt(lastPoint.x * lastPoint.x + lastPoint.y * lastPoint.y);
// Calculate average angle considering the curve
var midPoint = trajectoryPoints[Math.floor(trajectoryPoints.length / 2)];
var trajectoryAngle = Math.atan2(midPoint.y, midPoint.x);
// Scale trajectory line to show the curved path length
self.trajectoryLine.width = Math.min(800, trajectoryLength * 0.6);
self.trajectoryLine.rotation = trajectoryAngle;
// Dynamic curve visualization based on gravity effect
var gravityEffect = Math.abs(simVelY) / power; // How much gravity affected the path
var curveFactor = gravityEffect * 1.5 + Math.abs(trajectoryAngle - self.aimAngle) * 3;
self.trajectoryLine.scaleY = 1 + Math.min(curveFactor, 4); // Limit maximum curve
// Adjust line opacity based on trajectory length - longer shots are more uncertain
var baseAlpha = Math.max(0.3, 0.8 - trajectoryLength / 1000);
self.trajectoryLine.alpha = baseAlpha;
}
// Animate trajectory line with dynamic pulsing based on power and curve
tween.stop(self.trajectoryLine, {
alpha: true,
scaleX: true
});
// Calculate animation parameters based on trajectory properties
var animationSpeed = Math.max(150, 400 - power * 10); // Faster animation for higher power
var maxAlpha = Math.min(0.9, baseAlpha + 0.2);
var minAlpha = Math.max(0.2, baseAlpha - 0.2);
var scaleVariation = 1 + curveFactor * 0.1; // Slight scale pulsing for curved shots
tween(self.trajectoryLine, {
alpha: maxAlpha,
scaleX: scaleVariation
}, {
duration: animationSpeed,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self.trajectoryLine, {
alpha: minAlpha,
scaleX: 1.0
}, {
duration: animationSpeed,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Continue pulsing animation
if (self.trajectoryLine.visible) {
self.aimAt(targetX, targetY); // Restart animation if still aiming
}
}
});
}
});
};
self.shoot = function () {
if (arrows.length >= maxArrows) return;
// Hide trajectory line when shooting
self.trajectoryLine.visible = false;
var arrow = new Arrow();
var bowWorldX = self.x + self.bow.x + Math.cos(self.aimAngle) * 30;
var bowWorldY = self.y + self.bow.y + Math.sin(self.aimAngle) * 30;
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 based on velocity
self.rotation = Math.atan2(self.velocityY, self.velocityX);
// Check collision with platforms
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
if (self.intersects(platform)) {
self.active = false;
// Stop the arrow at the platform
self.velocityX = 0;
self.velocityY = 0;
break;
}
}
// Remove arrow if it goes off screen
if (self.x > 2100 || self.y > 2800 || self.x < -50 || self.y < -50) {
self.destroy();
for (var i = arrows.length - 1; i >= 0; i--) {
if (arrows[i] === self) {
arrows.splice(i, 1);
break;
}
}
}
};
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;
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;
}
}
// Animate fruit disappearing
tween(self, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
LK.getSound('hit').play();
// Check win condition
if (fruits.length === 0) {
LK.setTimeout(function () {
if (LK.getScore() >= targetScore) {
LK.showYouWin();
} else {
spawnFruits();
}
}, 500);
}
};
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;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
var archer = new Archer();
var arrows = [];
var fruits = [];
var platforms = [];
var bombs = [];
var maxArrows = 5;
var targetScore = 200;
// Position archer in the middle-left area
archer.x = 300;
archer.y = 1366; // Middle of screen vertically (2732/2)
game.addChild(archer);
// Create score display
var scoreTxt = new Text2('0', {
size: 100,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create target score display
var 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
var arrowsTxt = new Text2('Arrows: ' + maxArrows, {
size: 60,
fill: 0xFFFFFF
});
arrowsTxt.anchor.set(0, 0);
arrowsTxt.y = 120;
LK.gui.topLeft.addChild(arrowsTxt);
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 platforms
for (var i = 0; i < platforms.length; i++) {
platforms[i].destroy();
}
platforms = [];
var fruitTypes = ['apple', 'orange', 'banana'];
var numFruits = Math.min(8, Math.floor(LK.getScore() / 50) + 4);
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) {
platform.x = 600 + Math.random() * 800;
platform.y = 1000 + Math.random() * 1200;
validPosition = true;
// 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 < 200) {
// 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 - 35;
fruits.push(fruit);
game.addChild(fruit);
}
// Create separate platforms for bombs
var numBombs = Math.min(3, Math.floor(numFruits * 0.4) + 1); // 40% of fruits count, minimum 1
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) {
bombPlatform.x = 600 + Math.random() * 800;
bombPlatform.y = 1000 + Math.random() * 1200;
validPosition = true;
// 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 < 200) {
// 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 - 35;
bombs.push(bomb);
game.addChild(bomb);
}
}
// Initialize first level
spawnFruits();
// Mouse controls
var mouseX = 0;
var mouseY = 0;
var currentPower = 12; // Default power
game.move = function (x, y, obj) {
mouseX = x;
mouseY = y;
archer.aimAt(x, y);
// Calculate power based on distance from archer
var dx = x - archer.x;
var dy = y - archer.y;
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) {
mouseX = x;
mouseY = y;
archer.aimAt(x, y);
// Calculate power based on distance from archer
var dx = x - archer.x;
var dy = y - archer.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Scale power based on distance from archer (minimum 12, maximum 28)
currentPower = Math.min(28, Math.max(12, distance / 25));
archer.shoot();
// Update arrows remaining display
arrowsTxt.setText('Arrows: ' + (maxArrows - arrows.length));
};
game.update = function () {
// 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 && arrow.intersects(bomb)) {
arrow.active = false;
bomb.getHit();
arrow.destroy();
arrows.splice(i, 1);
return; // Exit immediately as game will be over
}
}
for (var j = 0; j < fruits.length; j++) {
var fruit = fruits[j];
if (!fruit.hit && arrow.intersects(fruit)) {
arrow.active = false;
fruit.getHit();
arrow.destroy();
arrows.splice(i, 1);
break;
}
}
}
// 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 we still have fruits but no arrows
LK.showGameOver();
}
}
}
// Update arrows remaining display
arrowsTxt.setText('Arrows: ' + Math.max(0, maxArrows - arrows.length));
}; ===================================================================
--- original.js
+++ change.js
@@ -40,47 +40,83 @@
var distance = Math.sqrt(dx * dx + dy * dy);
var power = Math.min(28, Math.max(12, distance / 25));
var velocityX = Math.cos(self.aimAngle) * power;
var velocityY = Math.sin(self.aimAngle) * power;
- // Simulate trajectory to find the curve angle and length
+ // Create curved trajectory visualization with multiple segments
+ var trajectoryPoints = [];
var simX = 0;
var simY = 0;
var simVelX = velocityX;
var simVelY = velocityY;
var gravity = 0.3;
var steps = 0;
- var maxSteps = 100;
- // Simulate until arrow would hit ground or go off screen
- while (steps < maxSteps && simY < 500 && simX < 800) {
+ var maxSteps = 60;
+ // Store initial point
+ trajectoryPoints.push({
+ x: simX,
+ y: simY
+ });
+ // Simulate trajectory and store points for curve visualization
+ while (steps < maxSteps && simY < 800 && simX < 1000 && simY > -200) {
simX += simVelX;
simY += simVelY;
simVelY += gravity;
+ // Store trajectory points every few steps for smoother curve
+ if (steps % 3 === 0) {
+ trajectoryPoints.push({
+ x: simX,
+ y: simY
+ });
+ }
steps++;
}
- // Calculate the trajectory line properties
- var trajectoryLength = Math.sqrt(simX * simX + simY * simY);
- var trajectoryAngle = Math.atan2(simY, simX);
- // Scale trajectory line based on simulation
- self.trajectoryLine.width = Math.min(600, trajectoryLength * 0.8);
- self.trajectoryLine.rotation = trajectoryAngle;
- // Add visual curve effect by scaling height based on distance
- var curveFactor = Math.abs(trajectoryAngle - self.aimAngle) * 2;
- self.trajectoryLine.scaleY = 1 + curveFactor;
- // Animate trajectory line with pulsing effect
+ // Calculate the trajectory line properties based on the full simulated path
+ if (trajectoryPoints.length > 1) {
+ var lastPoint = trajectoryPoints[trajectoryPoints.length - 1];
+ var trajectoryLength = Math.sqrt(lastPoint.x * lastPoint.x + lastPoint.y * lastPoint.y);
+ // Calculate average angle considering the curve
+ var midPoint = trajectoryPoints[Math.floor(trajectoryPoints.length / 2)];
+ var trajectoryAngle = Math.atan2(midPoint.y, midPoint.x);
+ // Scale trajectory line to show the curved path length
+ self.trajectoryLine.width = Math.min(800, trajectoryLength * 0.6);
+ self.trajectoryLine.rotation = trajectoryAngle;
+ // Dynamic curve visualization based on gravity effect
+ var gravityEffect = Math.abs(simVelY) / power; // How much gravity affected the path
+ var curveFactor = gravityEffect * 1.5 + Math.abs(trajectoryAngle - self.aimAngle) * 3;
+ self.trajectoryLine.scaleY = 1 + Math.min(curveFactor, 4); // Limit maximum curve
+ // Adjust line opacity based on trajectory length - longer shots are more uncertain
+ var baseAlpha = Math.max(0.3, 0.8 - trajectoryLength / 1000);
+ self.trajectoryLine.alpha = baseAlpha;
+ }
+ // Animate trajectory line with dynamic pulsing based on power and curve
tween.stop(self.trajectoryLine, {
- alpha: true
+ alpha: true,
+ scaleX: true
});
+ // Calculate animation parameters based on trajectory properties
+ var animationSpeed = Math.max(150, 400 - power * 10); // Faster animation for higher power
+ var maxAlpha = Math.min(0.9, baseAlpha + 0.2);
+ var minAlpha = Math.max(0.2, baseAlpha - 0.2);
+ var scaleVariation = 1 + curveFactor * 0.1; // Slight scale pulsing for curved shots
tween(self.trajectoryLine, {
- alpha: 0.8
+ alpha: maxAlpha,
+ scaleX: scaleVariation
}, {
- duration: 200,
+ duration: animationSpeed,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self.trajectoryLine, {
- alpha: 0.4
+ alpha: minAlpha,
+ scaleX: 1.0
}, {
- duration: 200,
- easing: tween.easeInOut
+ duration: animationSpeed,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ // Continue pulsing animation
+ if (self.trajectoryLine.visible) {
+ self.aimAt(targetX, targetY); // Restart animation if still aiming
+ }
+ }
});
}
});
};
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