User prompt
agrega una musica a la Batalla contra el ENEMIGO
User prompt
haz que los proyectiles de rombo que lanza el enemigo sean mas rapidos
User prompt
haz que el color de los circulos del enemigo no tengan ese filtro morado, ademas agrega un sonido para cada vez que el enemigo lanze un proyectil
User prompt
haz que los dos circulos que se alejan del circulo del medio se dirijan hacia adelante pero un poco a la izquierda y otro a la derecha como si fuese la forma de un avanico ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
bajale la velocidad de alejamiento de 1,5 a 0,5 a los circulos que lanza el enemigo, y que no se vayan en direccion derecha o izquierda, haz que vayan en direccion a donde estaba el jugador y se vayan alejando una por cada lado ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que los circulos lanzados por el enemigo no se separen el uno del otro tan rapido, ponle velocidad de 1,5 de alejamiento de uno al otro ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
que los circulos lanzados por el enemigo no se dispercen a los lados tan rapido, ponles 3 de velocidad de separacion ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que los circulos de el enemigo no se separen tanto el uno del otro, sino que vayan juntos al inicio y se separen de a poco, el maximo que se pueden separar es de 15 centimetros, y se separan de a poquito lentamente, tambien haz que los circulos tengan su punta mirando en direccion a donde son lanzados (osea en direccion al jugador) ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que los circulos que el enemigo lanza no se separen uno del otro tan rapido, sino que sean lanzados como uno normal y a la misma velocidad pero que poco a poco se vayan alejando ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que el segundo ataque de el enemigo los circulos sean un poco mas pequeños, que vayan mas rapido y que los circulos se separen unos a otros a medida que son lanzados ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que el enemigo en su segundo turno lanze 3 circulos grandes juntos, uno hacia el jugador otro hacia el jugador pero un poco en direccion hacia arriba y otro hacia el jugador pero un poco hacia abajo (dicho ataque debe lanzar los 3 proyectiles al mismo tiempo) ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
que los circulos lanzados por el ENEMIGO tengan el diseño de el elemento: Pica
User prompt
ahora, haz que cada turno, sus ataques sean diferentes, asi que, la segunda vez que le toque a el enemigo atacar, haz que lanza 3 circulos grandes juntos, uno hacia el jugador otro hacia el jugador pero un poco en direccion hacia arriba y otro hacia el jugador pero un poco hacia abajo (dicho ataque debe lanzar los 3 proyectiles al mismo tiempo) ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
cuando sea el turno del enemigo de atacar, se teletransportara en ubicaciones random de la pantalla sin salirse de la plantilla ni meterse dentro de la BattleBox, y apenas termine de atacar vuelva a su lugar inicial y se quede levitando como al inicio (asi siempre que ataque) ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que el ENEMIGO cuando vuelva a su posicion incicial y quede levitando como normalmente luego de atacar, no se bugee mirando en ambas direcciones, sino que dependiendo en que direccion levite, sera la direccion en la que verá, y su levitacion sea de izquierda a derecha levitando libremente, no se puede quedar quieto en un solo lugar ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que el ENEMIGO cuando vuelva a su posicion incicial y quede levitando como normalmente luego de atacar, no se bugee mirando en ambas direcciones, sino que dependiendo en que direccion levite, sera la direccion en la que verá, que levite lentamente de izquierda a derecha (no puede quedarse menos de 1 segundo levitando en la misma posicion) ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que el ENEMIGO cuando vuelva a su posicion incicial y quede levitando como normalmente luego de atacar, no se bugee mirando en ambas direcciones, sino que dependiendo en que direccion levite, sera la direccion en la que verá ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
que cuando el ENEMIGO vuelva a su posicion inicial luego de atacar, se quede levitando como al inicuo ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
que cuando el ENEMIGO deje de disparar automaticamente vaya a su lugar inicial (arriba de la battlebox) rrapidamente ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'ReferenceError: startEnemyLevitation is not defined' in or related to this line: 'startEnemyLevitation();' Line Number: 3436 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'ReferenceError: startEnemyLevitation is not defined' in or related to this line: 'startEnemyLevitation();' Line Number: 3466 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'ReferenceError: startEnemyLevitation is not defined' in or related to this line: 'startEnemyLevitation();' Line Number: 3435 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que el ENEMIGO se teletransporte a su lugar inicial levitando normalmente apenas termine de lanzar sus ataques ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que apenas el enemigo deje de lanzar ataques, se posicione en su lugar inicial (arriba de la battlebox) ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
hay un error que cuando el turno de que el enemigo ataque termina, no se puede hacer nada, arreglalo y dejalo como antes (y haz que cuando el enemigo termina de atacar, vuelve a su posicion inicial arriba de la BattleBox) ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/****
* Plugins
****/
var storage = LK.import("@upit/storage.v1");
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Circle = Container.expand(function (circleType) {
var self = Container.call(this);
var circleGraphics = self.attachAsset('circle' + circleType, {
anchorX: 0.5,
anchorY: 0.5
});
self.circleType = circleType;
self.size = circleType;
self.velocityX = 0;
self.velocityY = 0;
self.radius = [90, 120, 150, 180, 210, 240, 270, 320, 370][circleType - 1];
self.lastY = 0;
self.lastIntersecting = false;
self.spawnImmunity = false;
self.spawnTime = 0;
self.isSelected = false;
self.originalTint = 0xFFFFFF;
// Add selection handler
self.down = function (x, y, obj) {
if (selectionMode && gameState === 'playing') {
if (self.isSelected) {
// Deselect circle
self.isSelected = false;
circleGraphics.tint = self.originalTint;
var index = selectedCircles.indexOf(self);
if (index > -1) {
selectedCircles.splice(index, 1);
}
} else if (selectedCircles.length < maxSelectableCircles) {
// Select circle
self.isSelected = true;
circleGraphics.tint = 0xFF0000; // Red tint for selection
selectedCircles.push(self);
// If we have selected enough circles, remove them
if (selectedCircles.length >= maxSelectableCircles) {
// Deduct cost for using button1
score -= 750;
scoreText.setText('Score: ' + score);
scoreCounter.setText('Puntos: ' + score);
// Remove selected circles
for (var i = selectedCircles.length - 1; i >= 0; i--) {
var circle = selectedCircles[i];
game.removeChild(circle);
var circleIndex = circles.indexOf(circle);
if (circleIndex > -1) {
circles.splice(circleIndex, 1);
}
}
// Reset selection state
selectedCircles = [];
selectionMode = false;
}
}
}
};
self.update = function () {
// Apply gravity with slight variation based on size (heavier objects fall slightly faster)
var gravityForce = 0.4 + self.radius / 1000; // Larger circles have slightly more gravity
self.velocityY += gravityForce;
// Apply velocity
self.x += self.velocityX;
self.y += self.velocityY;
// Apply air resistance (less friction for more realistic movement)
self.velocityX *= 0.995; // Very slight air resistance
self.velocityY *= 0.999; // Even less resistance on Y axis
// Add rotation based on horizontal velocity to make circles look more natural
circleGraphics.rotation += self.velocityX * 0.01;
// Container collision detection
var containerLeft = containerX + 20;
var containerRight = containerX + containerWidth - 20;
var containerBottom = containerY + containerHeight - 20;
var containerTop = containerY;
// Side walls collision with improved bouncing
if (self.x - self.radius < containerLeft) {
self.x = containerLeft + self.radius;
self.velocityX = Math.abs(self.velocityX) * 0.7; // More bounce
}
if (self.x + self.radius > containerRight) {
self.x = containerRight - self.radius;
self.velocityX = -Math.abs(self.velocityX) * 0.7; // More bounce
}
// Allow circles to move above the container when spawning, no collision with top
// Bottom collision with better restitution
if (self.y + self.radius > containerBottom) {
self.y = containerBottom - self.radius;
// Add some bounce to vertical velocity instead of stopping completely
self.velocityY = -Math.abs(self.velocityY) * 0.3; // Small bounce
self.velocityX *= 0.85; // Less friction loss
}
// Circle-to-circle collision with other circles
for (var i = 0; i < circles.length; i++) {
var other = circles[i];
if (other !== self) {
var dx = self.x - other.x;
var dy = self.y - other.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Use consistent radius for collision detection
var minDistance = self.radius + other.radius;
if (distance < minDistance && distance > 0) {
// Same size circles merge
if (self.circleType === other.circleType && self.circleType < 9) {
// Prevent multiple merges of the same circles
if (self.shouldMerge || other.shouldMerge) {
return;
}
// Create new larger circle
var newCircle = new Circle(self.circleType + 1);
newCircle.x = (self.x + other.x) / 2;
newCircle.y = (self.y + other.y) / 2;
newCircle.velocityX = (self.velocityX + other.velocityX) / 2;
newCircle.velocityY = (self.velocityY + other.velocityY) / 2;
// Start small and animate to full size
newCircle.scaleX = 0.3;
newCircle.scaleY = 0.3;
tween(newCircle, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.bounceOut
});
// Play fusion sound
LK.getSound('circleFusion').play();
// Mark both circles for merging into the same new circle
self.shouldMerge = true;
other.shouldMerge = true;
self.mergeInto = newCircle;
other.mergeInto = newCircle;
score += self.circleType * 10;
scoreText.setText('Score: ' + score);
scoreCounter.setText('Puntos: ' + score);
return;
}
// Simple and consistent collision response
var overlap = minDistance - distance;
var normalX = dx / distance;
var normalY = dy / distance;
// Calculate mass based on radius
var mass1 = self.radius;
var mass2 = other.radius;
var totalMass = mass1 + mass2;
// Separate circles proportionally to their masses
var pushForce = overlap * 0.5; // Split the overlap correction
var ratio1 = mass2 / totalMass; // Lighter objects move more
var ratio2 = mass1 / totalMass;
// Apply position correction with small buffer
var buffer = 2; // Small buffer to prevent immediate re-collision
var correctionX = normalX * (pushForce + buffer);
var correctionY = normalY * (pushForce + buffer);
self.x += correctionX * ratio1;
self.y += correctionY * ratio1;
other.x -= correctionX * ratio2;
other.y -= correctionY * ratio2;
// Keep circles within container bounds after collision
var containerLeft = containerX + 20;
var containerRight = containerX + containerWidth - 20;
var containerBottom = containerY + containerHeight - 20;
if (self.x - self.radius < containerLeft) {
self.x = containerLeft + self.radius;
}
if (self.x + self.radius > containerRight) {
self.x = containerRight - self.radius;
}
if (self.y + self.radius > containerBottom) {
self.y = containerBottom - self.radius;
}
if (other.x - other.radius < containerLeft) {
other.x = containerLeft + other.radius;
}
if (other.x + other.radius > containerRight) {
other.x = containerRight - other.radius;
}
if (other.y + other.radius > containerBottom) {
other.y = containerBottom - other.radius;
}
// Simple velocity exchange for realistic bouncing
var relativeVelocityX = self.velocityX - other.velocityX;
var relativeVelocityY = self.velocityY - other.velocityY;
var separatingVelocity = relativeVelocityX * normalX + relativeVelocityY * normalY;
// Only resolve if objects are moving towards each other
if (separatingVelocity < 0) {
var restitution = 0.6; // Moderate bounciness
var impulse = -(1 + restitution) * separatingVelocity / (1 / mass1 + 1 / mass2);
var impulseX = impulse * normalX;
var impulseY = impulse * normalY;
self.velocityX += impulseX / mass1;
self.velocityY += impulseY / mass1;
other.velocityX -= impulseX / mass2;
other.velocityY -= impulseY / mass2;
}
}
}
}
};
return self;
});
var EnemyDiamond = Container.expand(function () {
var self = Container.call(this);
var diamondGraphics = self.attachAsset('enemyDiamond', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.3,
scaleY: 1.3
});
// Keep diamond straight initially
diamondGraphics.rotation = 0;
self.speed = 8.0;
self.velocityX = 0;
self.velocityY = 0;
self.lastY = 0;
self.lastX = 0;
// Method to set launch direction and rotation
self.setLaunchDirection = function (targetX, targetY) {
// Calculate direction towards target
var deltaX = targetX - self.x;
var deltaY = targetY - self.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
// Set velocity
if (distance > 0) {
self.velocityX = deltaX / distance * self.speed;
self.velocityY = deltaY / distance * self.speed;
// Set rotation to point towards target
diamondGraphics.rotation = Math.atan2(deltaY, deltaX);
} else {
self.velocityX = 0;
self.velocityY = self.speed;
diamondGraphics.rotation = Math.PI / 2; // Point downward
}
};
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
// Do not change rotation during movement - keep it fixed
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000011
});
/****
* Game Code
****/
// Game state management
// Suika Game assets
// Keep menu assets
var gameState = 'menu'; // 'menu', 'playing', 'paused', or 'settings'
var sensitivity = storage.sensitivity || 0.5; // Default sensitivity
// Suika Game variables
var containerX = (2048 - 1600) / 2;
var containerY = 200;
var containerWidth = 1600;
var containerHeight = 2000;
var circles = [];
var score = 0;
var nextCircleType = 1;
var currentCircle = null;
var dropLine = null;
var gameStarted = false;
// Individual circle immunity will be handled per circle
// Create container walls
var leftWall = LK.getAsset('containerWall', {
anchorX: 0,
anchorY: 0
});
leftWall.x = containerX;
leftWall.y = containerY;
var rightWall = LK.getAsset('containerWall', {
anchorX: 0,
anchorY: 0
});
rightWall.x = containerX + containerWidth - 20;
rightWall.y = containerY;
var bottomWall = LK.getAsset('containerBottom', {
anchorX: 0,
anchorY: 0
});
bottomWall.x = containerX;
bottomWall.y = containerY + containerHeight - 20;
var topWall = LK.getAsset('containerTop', {
anchorX: 0,
anchorY: 0
});
topWall.x = containerX;
topWall.y = containerY - 20;
// Score display
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0x000000
});
scoreText.anchor.set(0.5, 0);
scoreText.x = containerX + containerWidth / 2;
scoreText.y = containerY - 80; // Position above the red line
// Additional score counter above red line
var scoreCounter = new Text2('Puntos: 0', {
size: 50,
fill: 0xFFFFFF
});
scoreCounter.anchor.set(0.5, 0.5);
scoreCounter.x = containerX + containerWidth / 2;
scoreCounter.y = containerY - 40; // Just above the red line
// Next circle preview
var nextCirclePreview = LK.getAsset('nextCirclePreview', {
anchorX: 0.5,
anchorY: 0.5
});
nextCirclePreview.x = containerX + containerWidth + 100;
nextCirclePreview.y = 400;
var nextCircleText = new Text2('Next:', {
size: 40,
fill: 0x000000
});
nextCircleText.anchor.set(0.5, 0.5);
nextCircleText.x = nextCirclePreview.x;
nextCircleText.y = nextCirclePreview.y - 60;
// Create city background elements
var cityElements = [];
// Create starry night background
for (var i = 0; i < 100; i++) {
var star = LK.getAsset('nextCirclePreview', {
anchorX: 0.5,
anchorY: 0.5
});
star.x = Math.random() * 2048;
star.y = Math.random() * 1500; // Only in upper portion of screen
star.scaleX = 0.05 + Math.random() * 0.1;
star.scaleY = star.scaleX;
star.tint = 0xffffff;
star.alpha = 0.3 + Math.random() * 0.7;
game.addChild(star);
cityElements.push(star);
}
// Create buildings
for (var i = 0; i < 8; i++) {
var building = LK.getAsset('building', {
anchorX: 0.5,
anchorY: 1
});
building.x = i * 280 + 140;
building.y = 2732;
building.scaleX = 1 + Math.random() * 0.5;
building.scaleY = 1 + Math.random() * 1.2;
building.tint = 0x333333 + Math.random() * 0x333333; // Random dark colors
game.addChild(building);
cityElements.push(building);
}
// Create city fog/smog effects
var fogElements = [];
for (var i = 0; i < 6; i++) {
var fog = LK.getAsset('cityFog', {
anchorX: 0.5,
anchorY: 0.5
});
fog.x = Math.random() * 2048;
fog.y = 1800 + Math.random() * 400;
fog.tint = 0x666666; // Gray city smog
fog.alpha = 0.15 + Math.random() * 0.25;
fog.scaleX = 1 + Math.random() * 2;
fog.scaleY = 0.6 + Math.random() * 0.8;
fog.fogSpeed = 0.3 + Math.random() * 0.7;
fog.fogDirection = Math.random() * Math.PI * 2;
game.addChild(fog);
fogElements.push(fog);
}
// Create moon
var moon = LK.getAsset('moon', {
anchorX: 0.5,
anchorY: 0.5
});
moon.x = -100; // Start off-screen left
moon.y = 400; // Upper portion of screen
moon.scaleX = 1.2;
moon.scaleY = 1.2;
moon.alpha = 0.9;
moon.tint = 0xFFFFDD; // Slight cream color
// Moon click counter for easter egg
var moonClickCount = 0;
var moonClickTimeout = null;
// Chaos screen elements
var chaosScreenElements = [];
// Battle screen elements
var battleScreenElements = [];
var battleScreenActive = false;
var enemyDiamonds = [];
var lastEnemyShootTime = 0;
// Turn-based combat system
var isPlayerTurn = true;
var isEnemyTurn = false;
var enemyTurnCounter = 0; // Track which turn number for different attack patterns
// Timing mini-game variables
var timingGameActive = false;
var timingBarElements = [];
var timingLine = null;
var timingLinePosition = 0;
var timingLineDirection = 1;
var timingLineSpeed = 12;
var greenZoneStart = 300;
var greenZoneEnd = 420;
var perfectZoneStart = 0;
var perfectZoneEnd = 0;
var enemyHealth = 100;
var maxEnemyHealth = 100;
// Battle card elements
var battleCardElements = [];
// Character data for DELTARUNE-style cards
var characterData = [{
name: "KRIS",
hp: 150,
attack: 10,
defense: 2,
magic: 1,
portrait: 0x4a4a8a
}, {
name: "SUSIE",
hp: 110,
attack: 14,
defense: 0,
magic: 1,
portrait: 0x8a4a8a
}];
// Add click handler to moon
moon.down = function (x, y, obj) {
LK.getSound('moonClick').play();
// Create and display moon click image
var moonClickImage = LK.getAsset('moonClickImage', {
anchorX: 0.5,
anchorY: 0.5
});
moonClickImage.x = moon.x;
moonClickImage.y = moon.y;
moonClickImage.alpha = 0.8;
game.addChild(moonClickImage);
// Animate image to fade out and remove after 1.5 seconds
tween(moonClickImage, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(moonClickImage);
}
});
// Easter egg: count moon clicks
moonClickCount++;
if (moonClickTimeout) {
LK.clearTimeout(moonClickTimeout);
}
// Reset counter after 3 seconds if no more clicks
moonClickTimeout = LK.setTimeout(function () {
moonClickCount = 0;
}, 3000);
// Check if clicked 3 times in a row
if (moonClickCount >= 3) {
moonClickCount = 0;
if (moonClickTimeout) {
LK.clearTimeout(moonClickTimeout);
moonClickTimeout = null;
}
showChaosScreen();
}
};
game.addChild(moon);
cityElements.push(moon);
// Animate moon movement across screen with arc trajectory
moon.y = 800; // Start much lower
var moonStartY = 800;
var moonMidY = 250; // Higher point at middle
var moonEndY = 800; // End at same height as start
// Function to create complete moon cycle
function startMoonCycle() {
// First half: move right and up to middle
tween(moon, {
x: 1024,
// Middle of screen (2048/2)
y: moonMidY
}, {
duration: 18000,
// 18 seconds to reach middle (slower)
easing: tween.easeOut,
onFinish: function onFinish() {
// Second half: move right and down to end
tween(moon, {
x: 2148,
y: moonEndY
}, {
duration: 18000,
// 18 seconds to reach end (slower)
easing: tween.easeIn,
onFinish: function onFinish() {
// Reset moon and start cycle again
moon.x = -100;
moon.y = moonStartY;
startMoonCycle();
}
});
}
});
}
// Start the moon cycle
startMoonCycle();
// Create start screen elements
var titleText = new Text2('The amazing digital chaos!', {
size: 120,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 2732 / 3;
var playButton = LK.getAsset('furniture', {
anchorX: 0.5,
anchorY: 0.5
});
playButton.x = 2048 / 2;
playButton.y = 2732 / 2 - 100; // Move play button up
playButton.scaleX = 2.5; // Much larger
playButton.scaleY = 1.8; // Taller
// Add border effect with second button behind
var playButtonBorder = LK.getAsset('furniture', {
anchorX: 0.5,
anchorY: 0.5
});
playButtonBorder.x = playButton.x;
playButtonBorder.y = playButton.y;
playButtonBorder.tint = 0x000000; // Black border
playButtonBorder.scaleX = 2.6; // Slightly larger for border
playButtonBorder.scaleY = 1.9;
game.addChild(playButtonBorder);
game.addChild(playButton); // Add main button after border
var playButtonText = new Text2('JUGAR', {
size: 100,
// Larger text
fill: 0x000000 // Black color
});
playButtonText.anchor.set(0.5, 0.5);
playButtonText.x = playButton.x;
playButtonText.y = playButton.y;
// Add start screen elements
game.addChild(titleText);
game.addChild(playButton);
game.addChild(playButtonText);
// Store references for easy removal (including city elements)
var menuElements = [titleText, playButtonBorder, playButton, playButtonText].concat(cityElements).concat(fogElements);
// Create pause button (only visible during gameplay)
var pauseButton = LK.getAsset('furniture', {
anchorX: 0.5,
anchorY: 0.5
});
pauseButton.x = 2048 - 100;
pauseButton.y = 150;
pauseButton.tint = 0x666666;
pauseButton.scaleX = 0.8;
pauseButton.scaleY = 0.8;
var pauseButtonText = new Text2('||', {
size: 60,
fill: 0xFFFFFF
});
pauseButtonText.anchor.set(0.5, 0.5);
pauseButtonText.x = pauseButton.x;
pauseButtonText.y = pauseButton.y;
// Pause menu elements
var pauseMenuElements = [];
var pauseTitle = new Text2('PAUSA', {
size: 120,
fill: 0xFFD700
});
pauseTitle.anchor.set(0.5, 0.5);
pauseTitle.x = 2048 / 2;
pauseTitle.y = 800;
var resumeButton = LK.getAsset('continueButton', {
anchorX: 0.5,
anchorY: 0.5
});
resumeButton.x = 2048 / 2;
resumeButton.y = 1200;
resumeButton.scaleX = 2;
resumeButton.scaleY = 1.2;
var resumeButtonText = new Text2('CONTINUAR', {
size: 80,
fill: 0x000000
});
resumeButtonText.anchor.set(0.5, 0.5);
resumeButtonText.x = resumeButton.x;
resumeButtonText.y = resumeButton.y;
var menuButton = LK.getAsset('mainMenuButton', {
anchorX: 0.5,
anchorY: 0.5
});
menuButton.x = 2048 / 2;
menuButton.y = 1400;
menuButton.scaleX = 2;
menuButton.scaleY = 1.2;
var menuButtonText = new Text2('MENU PRINCIPAL', {
size: 70,
fill: 0x000000
});
menuButtonText.anchor.set(0.5, 0.5);
menuButtonText.x = menuButton.x;
menuButtonText.y = menuButton.y;
var restartButton = LK.getAsset('sensitivityButton', {
anchorX: 0.5,
anchorY: 0.5
});
restartButton.x = 2048 / 2;
restartButton.y = 1600;
restartButton.scaleX = 2;
restartButton.scaleY = 1.2;
var restartButtonText = new Text2('REINICIAR', {
size: 70,
fill: 0x000000
});
restartButtonText.anchor.set(0.5, 0.5);
restartButtonText.x = restartButton.x;
restartButtonText.y = restartButton.y;
var volumeButton = LK.getAsset('sensitivityButton', {
anchorX: 0.5,
anchorY: 0.5
});
volumeButton.x = 2048 / 2;
volumeButton.y = 1800;
volumeButton.scaleX = 2;
volumeButton.scaleY = 1.2;
var volumeButtonText = new Text2('VOLUMEN', {
size: 70,
fill: 0x000000
});
volumeButtonText.anchor.set(0.5, 0.5);
volumeButtonText.x = volumeButton.x;
volumeButtonText.y = volumeButton.y;
pauseMenuElements = [pauseTitle, resumeButton, resumeButtonText, menuButton, menuButtonText, restartButton, restartButtonText, volumeButton, volumeButtonText];
// Settings screen elements
var settingsScreenElements = [];
var settingsTitle = new Text2('AJUSTAR SENSIBILIDAD', {
size: 100,
fill: 0xFFD700
});
settingsTitle.anchor.set(0.5, 0.5);
settingsTitle.x = 2048 / 2;
settingsTitle.y = 800;
var sensitivityText = new Text2('Sensibilidad: ' + Math.round(sensitivity * 100) + '%', {
size: 80,
fill: 0xFFFFFF
});
sensitivityText.anchor.set(0.5, 0.5);
sensitivityText.x = 2048 / 2;
sensitivityText.y = 1200;
var decreaseButton = LK.getAsset('furniture', {
anchorX: 0.5,
anchorY: 0.5
});
decreaseButton.x = 2048 / 2 - 200;
decreaseButton.y = 1400;
decreaseButton.tint = 0xFF4444;
decreaseButton.scaleX = 1.5;
decreaseButton.scaleY = 1.2;
var decreaseButtonText = new Text2('-', {
size: 100,
fill: 0xFFFFFF
});
decreaseButtonText.anchor.set(0.5, 0.5);
decreaseButtonText.x = decreaseButton.x;
decreaseButtonText.y = decreaseButton.y;
var increaseButton = LK.getAsset('furniture', {
anchorX: 0.5,
anchorY: 0.5
});
increaseButton.x = 2048 / 2 + 200;
increaseButton.y = 1400;
increaseButton.tint = 0x44FF44;
increaseButton.scaleX = 1.5;
increaseButton.scaleY = 1.2;
var increaseButtonText = new Text2('+', {
size: 100,
fill: 0xFFFFFF
});
increaseButtonText.anchor.set(0.5, 0.5);
increaseButtonText.x = increaseButton.x;
increaseButtonText.y = increaseButton.y;
var backFromSettingsButton = LK.getAsset('furniture', {
anchorX: 0.5,
anchorY: 0.5
});
backFromSettingsButton.x = 2048 / 2;
backFromSettingsButton.y = 1700;
backFromSettingsButton.tint = 0x888888;
backFromSettingsButton.scaleX = 1.8;
backFromSettingsButton.scaleY = 1.2;
var backFromSettingsButtonText = new Text2('VOLVER', {
size: 70,
fill: 0xFFFFFF
});
backFromSettingsButtonText.anchor.set(0.5, 0.5);
backFromSettingsButtonText.x = backFromSettingsButton.x;
backFromSettingsButtonText.y = backFromSettingsButton.y;
settingsScreenElements = [settingsTitle, sensitivityText, decreaseButton, decreaseButtonText, increaseButton, increaseButtonText, backFromSettingsButton, backFromSettingsButtonText];
// Volume control screen elements
var volumeScreenElements = [];
var volumeTitle = new Text2('AJUSTAR VOLUMEN', {
size: 100,
fill: 0xFFD700
});
volumeTitle.anchor.set(0.5, 0.5);
volumeTitle.x = 2048 / 2;
volumeTitle.y = 800;
var musicVolume = 0.5; // Default volume
var volumeText = new Text2('Volumen: ' + Math.round(musicVolume * 100) + '%', {
size: 80,
fill: 0xFFFFFF
});
volumeText.anchor.set(0.5, 0.5);
volumeText.x = 2048 / 2;
volumeText.y = 1200;
var volumeDecreaseButton = LK.getAsset('furniture', {
anchorX: 0.5,
anchorY: 0.5
});
volumeDecreaseButton.x = 2048 / 2 - 200;
volumeDecreaseButton.y = 1400;
volumeDecreaseButton.tint = 0xFF4444;
volumeDecreaseButton.scaleX = 1.5;
volumeDecreaseButton.scaleY = 1.2;
var volumeDecreaseButtonText = new Text2('-', {
size: 100,
fill: 0xFFFFFF
});
volumeDecreaseButtonText.anchor.set(0.5, 0.5);
volumeDecreaseButtonText.x = volumeDecreaseButton.x;
volumeDecreaseButtonText.y = volumeDecreaseButton.y;
var volumeIncreaseButton = LK.getAsset('furniture', {
anchorX: 0.5,
anchorY: 0.5
});
volumeIncreaseButton.x = 2048 / 2 + 200;
volumeIncreaseButton.y = 1400;
volumeIncreaseButton.tint = 0x44FF44;
volumeIncreaseButton.scaleX = 1.5;
volumeIncreaseButton.scaleY = 1.2;
var volumeIncreaseButtonText = new Text2('+', {
size: 100,
fill: 0xFFFFFF
});
volumeIncreaseButtonText.anchor.set(0.5, 0.5);
volumeIncreaseButtonText.x = volumeIncreaseButton.x;
volumeIncreaseButtonText.y = volumeIncreaseButton.y;
var backFromVolumeButton = LK.getAsset('furniture', {
anchorX: 0.5,
anchorY: 0.5
});
backFromVolumeButton.x = 2048 / 2;
backFromVolumeButton.y = 1700;
backFromVolumeButton.tint = 0x888888;
backFromVolumeButton.scaleX = 1.8;
backFromVolumeButton.scaleY = 1.2;
var backFromVolumeButtonText = new Text2('VOLVER', {
size: 70,
fill: 0xFFFFFF
});
backFromVolumeButtonText.anchor.set(0.5, 0.5);
backFromVolumeButtonText.x = backFromVolumeButton.x;
backFromVolumeButtonText.y = backFromVolumeButton.y;
volumeScreenElements = [volumeTitle, volumeText, volumeDecreaseButton, volumeDecreaseButtonText, volumeIncreaseButton, volumeIncreaseButtonText, backFromVolumeButton, backFromVolumeButtonText];
// Function to show chaos screen (easter egg)
function showChaosScreen() {
gameState = 'chaos';
// Remove menu elements
for (var i = 0; i < menuElements.length; i++) {
game.removeChild(menuElements[i]);
}
// Create chaos screen elements
var chaosTitle = new Text2('EASTER EGG FOUND!', {
size: 100,
fill: 0xFF0000
});
chaosTitle.anchor.set(0.5, 0.5);
chaosTitle.x = 2048 / 2;
chaosTitle.y = 800;
var chaosSubtitle = new Text2('Welcome to the secret screen', {
size: 60,
fill: 0xFFFFFF
});
chaosSubtitle.anchor.set(0.5, 0.5);
chaosSubtitle.x = 2048 / 2;
chaosSubtitle.y = 1000;
var chaosButton = LK.getAsset('furniture', {
anchorX: 0.5,
anchorY: 0.5
});
chaosButton.x = 2048 / 2;
chaosButton.y = 1400;
chaosButton.tint = 0x8B0000; // Dark red
chaosButton.scaleX = 2.5;
chaosButton.scaleY = 1.8;
var chaosButtonText = new Text2('CHAOS', {
size: 100,
fill: 0xFFFFFF
});
chaosButtonText.anchor.set(0.5, 0.5);
chaosButtonText.x = chaosButton.x;
chaosButtonText.y = chaosButton.y;
var backToChaosMenuButton = LK.getAsset('furniture', {
anchorX: 0.5,
anchorY: 0.5
});
backToChaosMenuButton.x = 2048 / 2;
backToChaosMenuButton.y = 1700;
backToChaosMenuButton.tint = 0x888888;
backToChaosMenuButton.scaleX = 1.8;
backToChaosMenuButton.scaleY = 1.2;
var backToChaosMenuButtonText = new Text2('VOLVER', {
size: 70,
fill: 0xFFFFFF
});
backToChaosMenuButtonText.anchor.set(0.5, 0.5);
backToChaosMenuButtonText.x = backToChaosMenuButton.x;
backToChaosMenuButtonText.y = backToChaosMenuButton.y;
chaosScreenElements = [chaosTitle, chaosSubtitle, chaosButton, chaosButtonText, backToChaosMenuButton, backToChaosMenuButtonText];
// Add chaos screen elements
for (var i = 0; i < chaosScreenElements.length; i++) {
game.addChild(chaosScreenElements[i]);
}
}
// Function to return to main menu from chaos screen
function returnToMainMenuFromChaos() {
gameState = 'menu';
// Remove chaos screen elements
for (var i = 0; i < chaosScreenElements.length; i++) {
game.removeChild(chaosScreenElements[i]);
}
// Add menu elements back
for (var i = 0; i < menuElements.length; i++) {
game.addChild(menuElements[i]);
}
}
// Function to create character battle cards
function createBattleCards() {
battleCardElements = [];
// Only create one card - using the first character
var character = characterData[0];
var cardX = 1024; // Center the single card
var cardY = 2550; // Position card further down at bottom of screen
// Make cards much larger to cover entire bottom area
var cardWidth = 2000; // Much wider cards to cover full width
var cardHeight = 500; // Taller cards for better visibility
// Create card border (white background)
var cardBorder = LK.getAsset('characterCardBorder', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: cardWidth / 310,
scaleY: cardHeight / 410
});
cardBorder.x = cardX;
cardBorder.y = cardY;
// Create main card background
var cardBg = LK.getAsset('characterCard', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: cardWidth / 300,
scaleY: cardHeight / 400
});
cardBg.x = cardX;
cardBg.y = cardY;
// Create character portrait (larger and positioned to the left)
var portrait = LK.getAsset('characterPortrait', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
portrait.x = cardX - 600;
portrait.y = cardY - 30;
portrait.tint = character.portrait;
// Create character name text (positioned above portrait, larger)
var nameText = new Text2(character.name, {
size: 70,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0.5);
nameText.x = cardX - 600;
nameText.y = cardY - 150;
// Create HP text (positioned to the right of portrait, larger)
var hpText = new Text2('HP: ' + character.hp, {
size: 50,
fill: 0xFF4444
});
hpText.anchor.set(0.5, 0.5);
hpText.x = cardX - 200;
hpText.y = cardY - 100;
// Create Attack text (larger)
var attackText = new Text2('ATK: ' + character.attack, {
size: 50,
fill: 0xFFAA44
});
attackText.anchor.set(0.5, 0.5);
attackText.x = cardX - 200;
attackText.y = cardY - 30;
// Create Defense text (larger)
var defenseText = new Text2('DEF: ' + character.defense, {
size: 50,
fill: 0x44AAFF
});
defenseText.anchor.set(0.5, 0.5);
defenseText.x = cardX - 200;
defenseText.y = cardY + 40;
// Create action buttons for the character (much larger and better spacing)
var buttonSize = 160;
var buttonSpacing = 180;
var startX = cardX + 200;
var buttonY = cardY;
// ATACAR button
var attackButton = LK.getAsset('characterNameBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: buttonSize / 280,
scaleY: buttonSize / 60
});
attackButton.x = startX;
attackButton.y = buttonY - 80;
attackButton.tint = 0xFF4444;
var attackButtonText = new Text2('ATACAR', {
size: 40,
fill: 0xFFFFFF
});
attackButtonText.anchor.set(0.5, 0.5);
attackButtonText.x = attackButton.x;
attackButtonText.y = attackButton.y;
// ACTUAR button
var actButton = LK.getAsset('characterNameBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: buttonSize / 280,
scaleY: buttonSize / 60
});
actButton.x = startX + buttonSpacing;
actButton.y = buttonY - 80;
actButton.tint = 0x44AA44;
var actButtonText = new Text2('ACTUAR', {
size: 40,
fill: 0xFFFFFF
});
actButtonText.anchor.set(0.5, 0.5);
actButtonText.x = actButton.x;
actButtonText.y = actButton.y;
// COMIDA button
var foodButton = LK.getAsset('characterNameBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: buttonSize / 280,
scaleY: buttonSize / 60
});
foodButton.x = startX;
foodButton.y = buttonY + 80;
foodButton.tint = 0xFFAA44;
var foodButtonText = new Text2('COMIDA', {
size: 40,
fill: 0xFFFFFF
});
foodButtonText.anchor.set(0.5, 0.5);
foodButtonText.x = foodButton.x;
foodButtonText.y = foodButton.y;
// DEFENSA button
var defenseButton = LK.getAsset('characterNameBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: buttonSize / 280,
scaleY: buttonSize / 60
});
defenseButton.x = startX + buttonSpacing;
defenseButton.y = buttonY + 80;
defenseButton.tint = 0x4444FF;
var defenseButtonText = new Text2('DEFENSA', {
size: 40,
fill: 0xFFFFFF
});
defenseButtonText.anchor.set(0.5, 0.5);
defenseButtonText.x = defenseButton.x;
defenseButtonText.y = defenseButton.y;
// Store all card elements including action buttons
battleCardElements.push(cardBorder, cardBg, portrait, nameText, hpText, attackText, defenseText, attackButton, attackButtonText, actButton, actButtonText, foodButton, foodButtonText, defenseButton, defenseButtonText);
}
// Global variables for enemy levitation
var enemyBaseY = 0;
var enemyBaseX = 0;
// Define the enemy levitation function in global scope
function startEnemyLevitation() {
// Get enemy character from battle screen elements
if (battleScreenActive && battleScreenElements.length >= 7) {
var enemyCharacter = battleScreenElements[6];
if (enemyCharacter) {
// Generate continuous left-to-right movement pattern
var movementRange = 180; // Larger horizontal movement range for more visible movement
var currentDirection = enemyCharacter.levitationDirection || 1; // 1 for right, -1 for left
var movementDistance = 60 + Math.random() * 60; // Move 60-120 pixels each time
var randomYOffset = (Math.random() - 0.5) * 30; // Small Y variation
var movementDuration = 1200 + Math.random() * 600; // 1.2-1.8 seconds (minimum 1.2 seconds)
// Calculate next X position based on current direction
var nextX = enemyBaseX + currentDirection * movementDistance;
// Check boundaries and reverse direction if needed
var minX = enemyBaseX - movementRange / 2;
var maxX = enemyBaseX + movementRange / 2;
if (nextX <= minX) {
nextX = minX;
currentDirection = 1; // Start moving right
} else if (nextX >= maxX) {
nextX = maxX;
currentDirection = -1; // Start moving left
}
// Store direction for next iteration
enemyCharacter.levitationDirection = currentDirection;
// Determine direction based on movement and flip enemy accordingly
if (currentDirection > 0) {
// Moving right - show normal image (not flipped)
enemyCharacter.scaleX = Math.abs(enemyCharacter.scaleX);
} else {
// Moving left - flip image horizontally
enemyCharacter.scaleX = -Math.abs(enemyCharacter.scaleX);
}
// Move to next position with slow, smooth movement
tween(enemyCharacter, {
y: enemyBaseY + randomYOffset,
x: nextX
}, {
duration: movementDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Continue the cycle with new movement
startEnemyLevitation();
}
});
}
}
}
// Function to show DELTARUNE-style battle screen
function showBattleScreen() {
gameState = 'battle';
battleScreenActive = true;
// Reset turn system - player starts first
isPlayerTurn = true;
isEnemyTurn = false;
// Reset enemy turn counter
enemyTurnCounter = 0;
// Reset enemy health
enemyHealth = maxEnemyHealth;
// Remove chaos screen elements
for (var i = 0; i < chaosScreenElements.length; i++) {
game.removeChild(chaosScreenElements[i]);
}
// Create battle screen background
var battleBackground = LK.getAsset('battleBackground', {
anchorX: 0,
anchorY: 0
});
battleBackground.x = 0;
battleBackground.y = 0;
// Create battle dialogue box
var battleBox = LK.getAsset('battleBox', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4.2,
scaleY: 8.0
});
battleBox.x = 2048 / 2;
battleBox.y = 2732 / 2;
// Create enemy character above battle box
var enemyCharacter = LK.getAsset('characterPortrait', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
enemyCharacter.x = battleBox.x;
enemyCharacter.y = battleBox.y - 700; // Position higher above battle box (3-4 cm more separation)
// enemyCharacter.tint = 0x8B0080; // Purple alien color - removed to show original image
// Add levitation animation to make enemy look powerful
enemyBaseY = enemyCharacter.y;
enemyBaseX = enemyCharacter.x;
// Start the levitation animation
startEnemyLevitation();
// Create battle text
var battleText = new Text2('* Choose your fighters for battle!', {
size: 50,
fill: 0x000000
});
battleText.anchor.set(0.5, 0.5);
battleText.x = battleBox.x;
battleText.y = battleBox.y;
// Create pause button in top right corner
var battlePauseButton = LK.getAsset('battlePauseButton', {
anchorX: 0.5,
anchorY: 0.5
});
battlePauseButton.x = 2048 - 80;
battlePauseButton.y = 80;
var battlePauseButtonText = new Text2('EXIT', {
size: 30,
fill: 0xFFFFFF
});
battlePauseButtonText.anchor.set(0.5, 0.5);
battlePauseButtonText.x = battlePauseButton.x;
battlePauseButtonText.y = battlePauseButton.y;
// Create heart cursor (player soul)
var heartCursor = LK.getAsset('heartCursor', {
anchorX: 0.5,
anchorY: 0.5
});
heartCursor.x = battleBox.x;
heartCursor.y = battleBox.y;
heartCursor.scaleX = 1.2;
heartCursor.scaleY = 1.2;
// Create enemy health bar
var enemyHealthBarBg = LK.getAsset('timingBar', {
anchorX: 0.5,
anchorY: 0.5
});
enemyHealthBarBg.x = 2048 / 2;
enemyHealthBarBg.y = 300;
enemyHealthBarBg.tint = 0x333333;
enemyHealthBarBg.scaleX = 0.8;
enemyHealthBarBg.scaleY = 0.6;
var enemyHealthBar = LK.getAsset('timingBarGreen', {
anchorX: 0,
anchorY: 0.5
});
enemyHealthBar.x = enemyHealthBarBg.x - enemyHealthBarBg.width * enemyHealthBarBg.scaleX / 2;
enemyHealthBar.y = enemyHealthBarBg.y;
enemyHealthBar.tint = 0xFF0000;
enemyHealthBar.scaleX = enemyHealth / maxEnemyHealth * 5.3;
enemyHealthBar.scaleY = 0.6;
var enemyHealthText = new Text2('ENEMY HP: ' + enemyHealth + '/' + maxEnemyHealth, {
size: 40,
fill: 0xFFFFFF
});
enemyHealthText.anchor.set(0.5, 0.5);
enemyHealthText.x = enemyHealthBarBg.x;
enemyHealthText.y = enemyHealthBarBg.y - 60;
battleScreenElements = [battleBackground, battleBox, battleText, battlePauseButton, battlePauseButtonText, heartCursor, enemyCharacter, enemyHealthBarBg, enemyHealthBar, enemyHealthText];
// Add battle screen elements
for (var i = 0; i < battleScreenElements.length; i++) {
game.addChild(battleScreenElements[i]);
}
// Create and add character cards
createBattleCards();
for (var i = 0; i < battleCardElements.length; i++) {
game.addChild(battleCardElements[i]);
}
}
// Function to create timing mini-game
function createTimingMiniGame() {
timingGameActive = true;
timingBarElements = [];
timingLinePosition = 0;
timingLineDirection = 1;
// Randomize green zone position and size for each round
var minZoneWidth = 80; // Minimum green zone width
var maxZoneWidth = 160; // Maximum green zone width
var zoneWidth = minZoneWidth + Math.random() * (maxZoneWidth - minZoneWidth);
var maxStartPosition = 700 - zoneWidth; // Leave space for the zone width
greenZoneStart = Math.random() * maxStartPosition;
greenZoneEnd = greenZoneStart + zoneWidth;
// Create timing bar background (centered on screen)
var timingBarBg = LK.getAsset('timingBar', {
anchorX: 0.5,
anchorY: 0.5
});
timingBarBg.x = 2048 / 2;
timingBarBg.y = 2732 / 2;
// Create green success zone with randomized size and position
var greenZone = LK.getAsset('timingBarGreen', {
anchorX: 0.5,
anchorY: 0.5
});
// Scale the green zone to match the randomized width (made larger)
greenZone.scaleX = zoneWidth / 120 * 1.5; // 120 is the original width of timingBarGreen, made 1.5x larger
greenZone.x = timingBarBg.x - 400 + greenZoneStart + zoneWidth / 2; // Center the zone at its new position
greenZone.y = timingBarBg.y;
// Create perfect zone (smaller golden zone within green zone)
var perfectZoneWidth = zoneWidth * 0.5; // Perfect zone is half the size of green zone
perfectZoneStart = greenZoneStart + (zoneWidth - perfectZoneWidth) / 2; // Center perfect zone within green zone
perfectZoneEnd = perfectZoneStart + perfectZoneWidth;
var perfectZone = LK.getAsset('timingBarPerfect', {
anchorX: 0.5,
anchorY: 0.5
});
// Scale the perfect zone to match the calculated width
perfectZone.scaleX = perfectZoneWidth / 60; // 60 is the original width of timingBarPerfect
perfectZone.x = timingBarBg.x - 400 + perfectZoneStart + perfectZoneWidth / 2; // Center the zone at its new position
perfectZone.y = timingBarBg.y;
// Create moving timing line
timingLine = LK.getAsset('timingLine', {
anchorX: 0.5,
anchorY: 0.5
});
timingLine.x = timingBarBg.x - 400; // Start at left edge of bar
timingLine.y = timingBarBg.y;
// Create instruction text
var instructionText = new Text2('¡Presiona la pantalla cuando la línea esté en verde!', {
size: 60,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 2048 / 2;
instructionText.y = 2732 / 2 - 150;
// Store elements for cleanup
timingBarElements = [timingBarBg, greenZone, perfectZone, timingLine, instructionText];
// Add elements to game
for (var i = 0; i < timingBarElements.length; i++) {
game.addChild(timingBarElements[i]);
}
}
// Function to clean up timing mini-game
function cleanupTimingMiniGame() {
timingGameActive = false;
for (var i = 0; i < timingBarElements.length; i++) {
game.removeChild(timingBarElements[i]);
}
timingBarElements = [];
timingLine = null;
}
// Function to check timing success
function checkTimingSuccess() {
if (!timingGameActive || !timingLine) return false;
// Check if timing line is within green zone
var linePos = timingLinePosition;
return linePos >= greenZoneStart && linePos <= greenZoneEnd;
}
// Function to calculate damage based on distance from center of green zone
function calculateDamageFromTiming() {
if (!timingGameActive || !timingLine) return 0;
var linePos = timingLinePosition;
// Check if we're in the green zone at all
if (linePos < greenZoneStart || linePos > greenZoneEnd) {
return 0; // No damage if outside green zone
}
// Check if we're in the perfect zone (golden zone)
if (linePos >= perfectZoneStart && linePos <= perfectZoneEnd) {
return 25; // Deal 25 damage when pressing in perfect zone
}
// Deal 15 damage when pressing in green zone but outside perfect zone
return 15;
}
// Action interface elements
var actionInterfaceElements = [];
var actionInterfaceActive = false;
// Function to create action interface
function createActionInterface() {
actionInterfaceActive = true;
actionInterfaceElements = [];
// Create semi-transparent background overlay
var overlay = LK.getAsset('battleBackground', {
anchorX: 0,
anchorY: 0
});
overlay.x = 0;
overlay.y = 0;
overlay.alpha = 0.7;
overlay.tint = 0x000000;
// Create main interface background (larger and centered)
var interfaceBg = LK.getAsset('characterCardBorder', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4.0,
scaleY: 3.0
});
interfaceBg.x = 2048 / 2;
interfaceBg.y = 2732 / 2;
var interfaceContent = LK.getAsset('characterCard', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3.8,
scaleY: 2.8
});
interfaceContent.x = interfaceBg.x;
interfaceContent.y = interfaceBg.y;
// Create title text
var titleText = new Text2('ACCIÓN', {
size: 80,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = interfaceBg.x;
titleText.y = interfaceBg.y - 300;
// Create "Ver estadísticas del enemigo" button
var statsButton = LK.getAsset('characterNameBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6.0,
scaleY: 2.0
});
statsButton.x = interfaceBg.x;
statsButton.y = interfaceBg.y - 100;
statsButton.tint = 0x4444FF;
var statsButtonText = new Text2('Ver estadísticas del enemigo', {
size: 50,
fill: 0xFFFFFF
});
statsButtonText.anchor.set(0.5, 0.5);
statsButtonText.x = statsButton.x;
statsButtonText.y = statsButton.y;
// Create "Hablarle" button
var talkButton = LK.getAsset('characterNameBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6.0,
scaleY: 2.0
});
talkButton.x = interfaceBg.x;
talkButton.y = interfaceBg.y + 100;
talkButton.tint = 0x44AA44;
var talkButtonText = new Text2('Hablarle', {
size: 50,
fill: 0xFFFFFF
});
talkButtonText.anchor.set(0.5, 0.5);
talkButtonText.x = talkButton.x;
talkButtonText.y = talkButton.y;
// Create close button
var closeButton = LK.getAsset('characterNameBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3.0,
scaleY: 1.5
});
closeButton.x = interfaceBg.x;
closeButton.y = interfaceBg.y + 300;
closeButton.tint = 0xFF4444;
var closeButtonText = new Text2('Cerrar', {
size: 45,
fill: 0xFFFFFF
});
closeButtonText.anchor.set(0.5, 0.5);
closeButtonText.x = closeButton.x;
closeButtonText.y = closeButton.y;
// Store all elements
actionInterfaceElements = [overlay, interfaceBg, interfaceContent, titleText, statsButton, statsButtonText, talkButton, talkButtonText, closeButton, closeButtonText];
// Add all elements to game
for (var i = 0; i < actionInterfaceElements.length; i++) {
game.addChild(actionInterfaceElements[i]);
}
}
// Function to close action interface
function closeActionInterface() {
actionInterfaceActive = false;
for (var i = 0; i < actionInterfaceElements.length; i++) {
game.removeChild(actionInterfaceElements[i]);
}
actionInterfaceElements = [];
}
// Food interface elements
var foodInterfaceElements = [];
var foodInterfaceActive = false;
// Track used food items - reset when game restarts/ends
var usedFoodItems = [];
// Function to create food interface
function createFoodInterface() {
foodInterfaceActive = true;
foodInterfaceElements = [];
// Check if all food items are used
var allFoodUsed = true;
for (var i = 0; i < 3; i++) {
if (usedFoodItems.indexOf('galletaPearl_' + i) === -1) {
allFoodUsed = false;
break;
}
}
for (var i = 0; i < 3; i++) {
if (usedFoodItems.indexOf('frutaChaos_' + i) === -1) {
allFoodUsed = false;
break;
}
}
// If all food is used, show error message and allow battle actions
if (allFoodUsed) {
var errorText = new Text2('HAS USADO TODOS TUS ARTICULOS', {
size: 50,
fill: 0xFF0000
});
errorText.anchor.set(0.5, 0.5);
// Position above COMIDA title
var battleBox = battleScreenElements[1];
if (battleBox) {
errorText.x = battleBox.x;
errorText.y = battleBox.y + 600 - 250; // Above title position
}
game.addChild(errorText);
// Store error text in food interface elements for cleanup
foodInterfaceElements = [errorText];
// Auto-remove error message after 2 seconds
LK.setTimeout(function () {
closeFoodInterface();
}, 2000);
return; // Don't create food interface if all items are used
}
// Get battle box position for positioning below it
var battleBox = battleScreenElements[1];
if (!battleBox) return;
// Create main food interface background
var foodInterfaceBg = LK.getAsset('characterCardBorder', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6.0,
scaleY: 2.5
});
foodInterfaceBg.x = battleBox.x;
foodInterfaceBg.y = battleBox.y + 600; // Position below battle box
foodInterfaceBg.tint = 0x8B4513; // Brown color for food background
var foodInterfaceContent = LK.getAsset('characterCard', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 5.8,
scaleY: 2.3
});
foodInterfaceContent.x = foodInterfaceBg.x;
foodInterfaceContent.y = foodInterfaceBg.y;
foodInterfaceContent.tint = 0x4A2C2A; // Dark brown for content
// Create title text
var foodTitleText = new Text2('COMIDA', {
size: 60,
fill: 0xFFD700
});
foodTitleText.anchor.set(0.5, 0.5);
foodTitleText.x = foodInterfaceBg.x;
foodTitleText.y = foodInterfaceBg.y - 180;
// Create 6 food options in 2 rows - much larger and more visible
var buttonWidth = 400; // Increased from 300 to 400
var buttonHeight = 160; // Increased from 120 to 160
var buttonSpacingX = 420; // Increased from 320 to 420
var buttonSpacingY = 180; // Increased from 140 to 180
var startX = foodInterfaceBg.x - 420; // Adjusted start position for much larger buttons
var startY = foodInterfaceBg.y + 50; // Moved down by 100 pixels (was -50, now +50)
// CUSTOMIZE YOUR FOOD OPTIONS HERE:
// You can easily modify these properties to change the appearance
// GalletaPearl button customization
var galletaPearlStyle = {
backgroundColor: 0x00FF88,
// Button background color (bright green)
textColor: 0x000000,
// Text color (black)
textSize: 55,
// Text size
borderColor: 0xFFFFFF,
// Optional border color (white)
glowEffect: true,
// Optional glow effect
pulseAnimation: false // Optional pulse animation
};
// FrutaChaos button customization
var frutaChaosStyle = {
backgroundColor: 0xFF6600,
// Button background color (bright orange)
textColor: 0x000000,
// Text color (black)
textSize: 55,
// Text size
borderColor: 0xFFFFFF,
// Optional border color (white)
glowEffect: true,
// Optional glow effect
pulseAnimation: false // Optional pulse animation
};
// Create 3 GalletaPearl buttons (top row)
var galletaPearlButtons = [];
for (var i = 0; i < 3; i++) {
var foodId = 'galletaPearl_' + i;
var isUsed = usedFoodItems.indexOf(foodId) !== -1;
// Create border/glow effect if enabled
if (galletaPearlStyle.glowEffect) {
var galletaBorder = LK.getAsset('OptionOfCOMIDA', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: (buttonWidth + 10) / 100,
scaleY: (buttonHeight + 10) / 100
});
galletaBorder.x = startX + i * buttonSpacingX;
galletaBorder.y = startY - buttonSpacingY / 2;
galletaBorder.tint = isUsed ? 0x666666 : galletaPearlStyle.borderColor;
galletaPearlButtons.push(galletaBorder);
}
var galletaButton = LK.getAsset('OptionOfCOMIDA', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: buttonWidth / 100,
scaleY: buttonHeight / 100
});
galletaButton.x = startX + i * buttonSpacingX;
galletaButton.y = startY - buttonSpacingY / 2;
galletaButton.tint = isUsed ? 0x444444 : galletaPearlStyle.backgroundColor;
galletaButton.foodType = 'galletaPearl';
galletaButton.foodId = foodId;
galletaButton.healAmount = 20;
galletaButton.isUsed = isUsed;
// Add pulse animation if enabled and not used
if (galletaPearlStyle.pulseAnimation && !isUsed) {
var pulseScale = {
scale: 1
};
tween(pulseScale, {
scale: 1.1
}, {
duration: 1000,
repeat: -1,
yoyo: true,
easing: tween.easeInOut,
onUpdate: function onUpdate() {
galletaButton.scaleX = buttonWidth / 280 * pulseScale.scale;
galletaButton.scaleY = buttonHeight / 60 * pulseScale.scale;
}
});
}
var galletaButtonText = new Text2(isUsed ? 'USADO' : 'GalletaPearl\n+20 HP', {
size: galletaPearlStyle.textSize,
fill: isUsed ? 0x888888 : galletaPearlStyle.textColor
});
galletaButtonText.anchor.set(0.5, 0.5);
galletaButtonText.x = galletaButton.x;
galletaButtonText.y = galletaButton.y;
galletaPearlButtons.push(galletaButton, galletaButtonText);
}
// Create 3 FrutaChaos buttons (bottom row)
var frutaChaosButtons = [];
for (var i = 0; i < 3; i++) {
var foodId = 'frutaChaos_' + i;
var isUsed = usedFoodItems.indexOf(foodId) !== -1;
// Create border/glow effect if enabled
if (frutaChaosStyle.glowEffect) {
var frutaBorder = LK.getAsset('OptionOfCOMIDA', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: (buttonWidth + 10) / 100,
scaleY: (buttonHeight + 10) / 100
});
frutaBorder.x = startX + i * buttonSpacingX;
frutaBorder.y = startY + buttonSpacingY / 2;
frutaBorder.tint = isUsed ? 0x666666 : frutaChaosStyle.borderColor;
frutaChaosButtons.push(frutaBorder);
}
var frutaButton = LK.getAsset('OptionOfCOMIDA', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: buttonWidth / 100,
scaleY: buttonHeight / 100
});
frutaButton.x = startX + i * buttonSpacingX;
frutaButton.y = startY + buttonSpacingY / 2;
frutaButton.tint = isUsed ? 0x444444 : frutaChaosStyle.backgroundColor;
frutaButton.foodType = 'frutaChaos';
frutaButton.foodId = foodId;
frutaButton.healAmount = 15;
frutaButton.isUsed = isUsed;
// Add pulse animation if enabled and not used
if (frutaChaosStyle.pulseAnimation && !isUsed) {
var pulseScale = {
scale: 1
};
tween(pulseScale, {
scale: 1.1
}, {
duration: 1000,
repeat: -1,
yoyo: true,
easing: tween.easeInOut,
onUpdate: function onUpdate() {
frutaButton.scaleX = buttonWidth / 280 * pulseScale.scale;
frutaButton.scaleY = buttonHeight / 60 * pulseScale.scale;
}
});
}
var frutaButtonText = new Text2(isUsed ? 'USADO' : 'FrutaChaos\n+15 HP', {
size: frutaChaosStyle.textSize,
fill: isUsed ? 0x888888 : frutaChaosStyle.textColor
});
frutaButtonText.anchor.set(0.5, 0.5);
frutaButtonText.x = frutaButton.x;
frutaButtonText.y = frutaButton.y;
frutaChaosButtons.push(frutaButton, frutaButtonText);
}
// Store all elements
foodInterfaceElements = [foodInterfaceBg, foodInterfaceContent, foodTitleText].concat(galletaPearlButtons).concat(frutaChaosButtons);
// Add all elements to game
for (var i = 0; i < foodInterfaceElements.length; i++) {
game.addChild(foodInterfaceElements[i]);
}
}
// Function to close food interface
function closeFoodInterface() {
foodInterfaceActive = false;
for (var i = 0; i < foodInterfaceElements.length; i++) {
game.removeChild(foodInterfaceElements[i]);
}
foodInterfaceElements = [];
}
// Function to create defeat screen
function createDefeatScreen() {
defeatScreenActive = true;
defeatScreenElements = [];
// Clear game state to menu to remove all game elements first
gameState = 'menu';
// Remove all game elements if they exist
if (leftWall) game.removeChild(leftWall);
if (rightWall) game.removeChild(rightWall);
if (bottomWall) game.removeChild(bottomWall);
if (topWall) game.removeChild(topWall);
if (scoreText) game.removeChild(scoreText);
if (scoreCounter) game.removeChild(scoreCounter);
if (nextCirclePreview) game.removeChild(nextCirclePreview);
if (nextCircleText) game.removeChild(nextCircleText);
if (currentCircle) {
game.removeChild(currentCircle);
currentCircle = null;
}
if (dropLine) {
game.removeChild(dropLine);
dropLine = null;
}
// Remove all circles
for (var i = 0; i < circles.length; i++) {
game.removeChild(circles[i]);
}
circles = [];
if (pauseButton) game.removeChild(pauseButton);
if (pauseButtonText) game.removeChild(pauseButtonText);
// Remove wooden board and buttons
if (woodenBoard) game.removeChild(woodenBoard);
if (button1) game.removeChild(button1);
if (button1CostText) game.removeChild(button1CostText);
if (button2) game.removeChild(button2);
if (button2CostText) game.removeChild(button2CostText);
if (button3) game.removeChild(button3);
if (button3CostText) game.removeChild(button3CostText);
// Create defeat screen background
var defeatScreenBg = LK.getAsset('characterCard', {
anchorX: 0,
anchorY: 0,
scaleX: 20.5,
scaleY: 27.3
});
defeatScreenBg.x = 0;
defeatScreenBg.y = 0;
defeatScreenBg.tint = 0x330000; // Dark red
// Create title text - very large and prominent
var titleText = new Text2('¡DERROTA!', {
size: 120,
fill: 0xFF0000
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 800;
// Create subtitle
var subtitleText = new Text2('¿QUÉ QUIERES HACER?', {
size: 80,
fill: 0xFFFFFF
});
subtitleText.anchor.set(0.5, 0.5);
subtitleText.x = 2048 / 2;
subtitleText.y = 1000;
// Create Reintentar button
var retryButton = LK.getAsset('OptionOfCOMIDA', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 16.0,
scaleY: 7.0
});
retryButton.x = 2048 / 2;
retryButton.y = 1300;
retryButton.tint = 0x00AA00; // Green
var retryButtonText = new Text2('REINTENTAR', {
size: 100,
fill: 0x000000
});
retryButtonText.anchor.set(0.5, 0.5);
retryButtonText.x = retryButton.x;
retryButtonText.y = retryButton.y;
// Create Rendirse button
var giveUpButton = LK.getAsset('OptionOfCOMIDA', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 16.0,
scaleY: 7.0
});
giveUpButton.x = 2048 / 2;
giveUpButton.y = 1600;
giveUpButton.tint = 0xAA0000; // Red
var giveUpButtonText = new Text2('RENDIRSE', {
size: 100,
fill: 0xFFFFFF
});
giveUpButtonText.anchor.set(0.5, 0.5);
giveUpButtonText.x = giveUpButton.x;
giveUpButtonText.y = giveUpButton.y;
// Store all elements
defeatScreenElements = [defeatScreenBg, titleText, subtitleText, retryButton, retryButtonText, giveUpButton, giveUpButtonText];
// Add all elements to game
for (var i = 0; i < defeatScreenElements.length; i++) {
game.addChild(defeatScreenElements[i]);
}
}
// Function to close defeat screen
function closeDefeatScreen() {
defeatScreenActive = false;
for (var i = 0; i < defeatScreenElements.length; i++) {
game.removeChild(defeatScreenElements[i]);
}
defeatScreenElements = [];
}
// Player defense state
var playerDefenseActive = false;
// Defeat screen interface elements
var defeatScreenElements = [];
var defeatScreenActive = false;
// Function to handle player actions and trigger enemy turn
function handlePlayerAction(actionType) {
if (!isPlayerTurn) return;
if (actionType === 'attack') {
// Start timing mini-game for attack
createTimingMiniGame();
return; // Don't proceed to enemy turn yet
}
if (actionType === 'act') {
// Show action interface
createActionInterface();
return; // Don't proceed to enemy turn yet
}
if (actionType === 'heal') {
// Show food interface
createFoodInterface();
return; // Don't proceed to enemy turn yet
}
if (actionType === 'defend') {
// Show defense message below battle box
var battleBox = battleScreenElements[1];
if (battleBox) {
// Create message box background
var messageBoxBg = LK.getAsset('characterCardBorder', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6.0,
scaleY: 1.5
});
messageBoxBg.x = battleBox.x;
messageBoxBg.y = battleBox.y + 600; // Position below battle box
messageBoxBg.tint = 0x4444FF; // Blue tint for defense
var messageBoxContent = LK.getAsset('characterCard', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 5.8,
scaleY: 1.3
});
messageBoxContent.x = messageBoxBg.x;
messageBoxContent.y = messageBoxBg.y;
messageBoxContent.tint = 0x000044; // Dark blue content
// Create defense message text with typing effect
var fullDefenseMessage = 'Te defendiste, ahora los ataques recibidos serán menos fuertes';
var defenseMessageText = new Text2('', {
size: 45,
fill: 0xFFFFFF
});
defenseMessageText.anchor.set(0.5, 0.5);
defenseMessageText.x = messageBoxBg.x;
defenseMessageText.y = messageBoxBg.y;
// Create typing animation using tween
var defenseTypingProgress = {
charIndex: 0
};
tween(defenseTypingProgress, {
charIndex: fullDefenseMessage.length
}, {
duration: 1500,
// 1.5 seconds for typing animation
easing: tween.linear,
onFinish: function onFinish() {
// Ensure full message is displayed
defenseMessageText.setText(fullDefenseMessage);
}
});
// Update text during typing animation
var defenseTypingInterval = LK.setInterval(function () {
var currentText = fullDefenseMessage.substring(0, Math.floor(defenseTypingProgress.charIndex));
defenseMessageText.setText(currentText);
if (defenseTypingProgress.charIndex >= fullDefenseMessage.length) {
LK.clearInterval(defenseTypingInterval);
}
}, 40); // Update every 40ms for smooth typing effect
// Add message elements to game
game.addChild(messageBoxBg);
game.addChild(messageBoxContent);
game.addChild(defenseMessageText);
// Set defense active for this turn
playerDefenseActive = true;
// Auto-remove message after 2.5 seconds and proceed to enemy turn
LK.setTimeout(function () {
LK.clearInterval(defenseTypingInterval); // Clean up typing interval
game.removeChild(messageBoxBg);
game.removeChild(messageBoxContent);
game.removeChild(defenseMessageText);
// Proceed to enemy turn
isPlayerTurn = false;
isEnemyTurn = true;
LK.setTimeout(function () {
isEnemyTurn = false;
// Reset defense after enemy turn
playerDefenseActive = false;
}, 3000);
}, 2500);
}
return; // Don't proceed to enemy turn yet
}
// For other actions, proceed normally
isPlayerTurn = false;
isEnemyTurn = true;
// Set a timeout to end enemy turn after 3 seconds
LK.setTimeout(function () {
isEnemyTurn = false;
// Don't automatically start player turn - wait for diamonds to exit battle box
}, 3000);
}
// Function to exit battle screen
function exitBattleScreen() {
gameState = 'chaos';
battleScreenActive = false;
// Clean up timing mini-game if active
if (timingGameActive) {
cleanupTimingMiniGame();
}
// Clean up action interface if active
if (actionInterfaceActive) {
closeActionInterface();
}
// Remove battle screen elements
for (var i = 0; i < battleScreenElements.length; i++) {
game.removeChild(battleScreenElements[i]);
}
// Remove battle card elements
for (var i = 0; i < battleCardElements.length; i++) {
game.removeChild(battleCardElements[i]);
}
battleCardElements = [];
// Remove all enemy diamonds
for (var i = 0; i < enemyDiamonds.length; i++) {
game.removeChild(enemyDiamonds[i]);
}
enemyDiamonds = [];
// Reset used food items when exiting battle (keeps them available for next battle)
usedFoodItems = [];
// Return to chaos screen
for (var i = 0; i < chaosScreenElements.length; i++) {
game.addChild(chaosScreenElements[i]);
}
}
// Function to start the game
function startGame() {
gameState = 'playing';
// Reset character HP to 150 when starting new game - ensure full healing
characterData[0].hp = 150;
// Remove menu elements
for (var i = 0; i < menuElements.length; i++) {
game.removeChild(menuElements[i]);
}
// Add game elements
game.addChild(leftWall);
game.addChild(rightWall);
game.addChild(bottomWall);
game.addChild(topWall);
game.addChild(scoreText);
game.addChild(scoreCounter);
game.addChild(nextCirclePreview);
game.addChild(nextCircleText);
// Add pause button
game.addChild(pauseButton);
game.addChild(pauseButtonText);
// Create wooden board below container
woodenBoard = LK.getAsset('woodenBoard', {
anchorX: 0.5,
anchorY: 0
});
woodenBoard.x = containerX + containerWidth / 2;
woodenBoard.y = containerY + containerHeight + 50;
game.addChild(woodenBoard);
// Create 3 buttons on the wooden board
button1 = LK.getAsset('button1', {
anchorX: 0.5,
anchorY: 0.5
});
button1.x = woodenBoard.x - 400;
button1.y = woodenBoard.y + 100;
game.addChild(button1);
button1CostText = new Text2('750 puntos', {
size: 60,
fill: 0xFFD700
});
button1CostText.anchor.set(0.5, 0.5);
button1CostText.x = button1.x;
button1CostText.y = button1.y + 140;
game.addChild(button1CostText);
button2 = LK.getAsset('button2', {
anchorX: 0.5,
anchorY: 0.5
});
button2.x = woodenBoard.x;
button2.y = woodenBoard.y + 100;
game.addChild(button2);
button2CostText = new Text2('650 puntos', {
size: 60,
fill: 0xFFD700
});
button2CostText.anchor.set(0.5, 0.5);
button2CostText.x = button2.x;
button2CostText.y = button2.y + 140;
game.addChild(button2CostText);
button3 = LK.getAsset('button3', {
anchorX: 0.5,
anchorY: 0.5
});
button3.x = woodenBoard.x + 400;
button3.y = woodenBoard.y + 100;
game.addChild(button3);
button3CostText = new Text2('9,999 puntos', {
size: 60,
fill: 0xFFD700
});
button3CostText.anchor.set(0.5, 0.5);
button3CostText.x = button3.x;
button3CostText.y = button3.y + 140;
game.addChild(button3CostText);
// Initialize first circle
generateNextCircle();
gameStarted = true;
// Start playing background music
LK.playMusic('NightChaos');
}
// Function to show pause menu
function showPauseMenu() {
gameState = 'paused';
// Add pause menu elements
for (var i = 0; i < pauseMenuElements.length; i++) {
game.addChild(pauseMenuElements[i]);
}
}
// Function to resume game
function resumeGame() {
gameState = 'playing';
// Remove pause menu elements
for (var i = 0; i < pauseMenuElements.length; i++) {
game.removeChild(pauseMenuElements[i]);
}
}
// Function to show settings screen
function showSettings() {
gameState = 'settings';
// Remove pause menu elements
for (var i = 0; i < pauseMenuElements.length; i++) {
game.removeChild(pauseMenuElements[i]);
}
// Add settings elements
for (var i = 0; i < settingsScreenElements.length; i++) {
game.addChild(settingsScreenElements[i]);
}
}
// Function to go back to pause menu from settings
function backToPauseMenu() {
gameState = 'paused';
// Remove settings elements
for (var i = 0; i < settingsScreenElements.length; i++) {
game.removeChild(settingsScreenElements[i]);
}
// Add pause menu elements
for (var i = 0; i < pauseMenuElements.length; i++) {
game.addChild(pauseMenuElements[i]);
}
}
// Function to show volume control screen
function showVolumeControl() {
gameState = 'volume';
// Remove pause menu elements
for (var i = 0; i < pauseMenuElements.length; i++) {
game.removeChild(pauseMenuElements[i]);
}
// Add volume control elements
for (var i = 0; i < volumeScreenElements.length; i++) {
game.addChild(volumeScreenElements[i]);
}
}
// Function to go back to pause menu from volume control
function backToPauseMenuFromVolume() {
gameState = 'paused';
// Remove volume control elements
for (var i = 0; i < volumeScreenElements.length; i++) {
game.removeChild(volumeScreenElements[i]);
}
// Add pause menu elements
for (var i = 0; i < pauseMenuElements.length; i++) {
game.addChild(pauseMenuElements[i]);
}
}
// Function to restart game
function restartGame() {
// Reset game state
gameState = 'paused';
// Remove pause menu elements
for (var i = 0; i < pauseMenuElements.length; i++) {
game.removeChild(pauseMenuElements[i]);
}
// Show defeat screen when restarting after game over
createDefeatScreen();
return;
}
// Function to return to main menu from pause
function returnToMainMenu() {
gameState = 'menu';
// Remove pause menu elements
for (var i = 0; i < pauseMenuElements.length; i++) {
game.removeChild(pauseMenuElements[i]);
}
// Remove game elements
game.removeChild(leftWall);
game.removeChild(rightWall);
game.removeChild(bottomWall);
game.removeChild(topWall);
game.removeChild(scoreText);
game.removeChild(scoreCounter);
game.removeChild(nextCirclePreview);
game.removeChild(nextCircleText);
if (currentCircle) {
game.removeChild(currentCircle);
currentCircle = null;
}
if (dropLine) {
game.removeChild(dropLine);
dropLine = null;
}
// Remove all circles
for (var i = 0; i < circles.length; i++) {
game.removeChild(circles[i]);
}
circles = [];
game.removeChild(pauseButton);
game.removeChild(pauseButtonText);
// Remove wooden board and buttons
if (woodenBoard) {
game.removeChild(woodenBoard);
}
if (button1) {
game.removeChild(button1);
if (button1CostText) {
game.removeChild(button1CostText);
}
}
if (button2) {
game.removeChild(button2);
if (button2CostText) {
game.removeChild(button2CostText);
}
}
if (button3) {
game.removeChild(button3);
if (button3CostText) {
game.removeChild(button3CostText);
}
}
// Reset game state
score = 0;
nextCircleType = 1;
gameStarted = false;
// Reset used food items
usedFoodItems = [];
// Reset character HP to 150 - ensure full healing when returning to menu
characterData[0].hp = 150;
// Add menu elements back
for (var i = 0; i < menuElements.length; i++) {
game.addChild(menuElements[i]);
}
}
// Movement controls
var keys = {
up: false,
down: false,
left: false,
right: false
};
// Touch/mouse controls
var isDragging = false;
var lastTouchX = 0;
var lastTouchY = 0;
// Wooden board and buttons
var woodenBoard = null;
var button1 = null;
var button1CostText = null;
var button2 = null;
var button2Text = null;
var button2CostText = null;
var button3 = null;
var button3Text = null;
var button3CostText = null;
// Circle selection system
var selectionMode = false;
var selectedCircles = [];
var maxSelectableCircles = 2;
function generateNextCircle() {
nextCircleType = Math.floor(Math.random() * 3) + 1; // Random circle type 1-3 only
// Update preview
game.removeChild(nextCirclePreview);
nextCirclePreview = LK.getAsset('circle' + nextCircleType, {
anchorX: 0.5,
anchorY: 0.5
});
nextCirclePreview.x = containerX + containerWidth + 100;
nextCirclePreview.y = 400;
nextCirclePreview.scaleX = 0.6;
nextCirclePreview.scaleY = 0.6;
game.addChild(nextCirclePreview);
}
game.down = function (x, y, obj) {
// Handle defeat screen first
if (defeatScreenActive) {
// Check retry button click (retry button is at index 3)
if (defeatScreenElements.length >= 7) {
var retryButton = defeatScreenElements[3];
var retryButtonBounds = {
left: retryButton.x - retryButton.width * retryButton.scaleX / 2,
right: retryButton.x + retryButton.width * retryButton.scaleX / 2,
top: retryButton.y - retryButton.height * retryButton.scaleY / 2,
bottom: retryButton.y + retryButton.height * retryButton.scaleY / 2
};
if (x >= retryButtonBounds.left && x <= retryButtonBounds.right && y >= retryButtonBounds.top && y <= retryButtonBounds.bottom) {
// Reset character HP to 150 and restart battle
characterData[0].hp = 150;
// Close defeat screen immediately
closeDefeatScreen();
// Reset used food items for new battle attempt
usedFoodItems = [];
// Reset battle state variables
isPlayerTurn = true;
isEnemyTurn = false;
enemyTurnCounter = 0; // Reset turn counter
enemyHealth = maxEnemyHealth;
playerDefenseActive = false;
// Show restart effect
var restartText = new Text2('¡REINTENTANDO BATALLA!', {
size: 100,
fill: 0x00FF00
});
restartText.anchor.set(0.5, 0.5);
restartText.x = 2048 / 2;
restartText.y = 2732 / 2;
game.addChild(restartText);
// Flash screen green for restart
LK.effects.flashScreen(0x00FF00, 800);
// Animate restart text and show battle screen
tween(restartText, {
y: restartText.y - 100,
alpha: 0
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(restartText);
// Go directly to battle screen to restart the fight
showBattleScreen();
}
});
return;
}
// Check give up button click (give up button is at index 5)
var giveUpButton = defeatScreenElements[5];
var giveUpButtonBounds = {
left: giveUpButton.x - giveUpButton.width * giveUpButton.scaleX / 2,
right: giveUpButton.x + giveUpButton.width * giveUpButton.scaleX / 2,
top: giveUpButton.y - giveUpButton.height * giveUpButton.scaleY / 2,
bottom: giveUpButton.y + giveUpButton.height * giveUpButton.scaleY / 2
};
if (x >= giveUpButtonBounds.left && x <= giveUpButtonBounds.right && y >= giveUpButtonBounds.top && y <= giveUpButtonBounds.bottom) {
// Reset character HP and return to main menu
characterData[0].hp = 150;
closeDefeatScreen();
// Reset game state
score = 0;
nextCircleType = 1;
gameStarted = false;
// Reset used food items
usedFoodItems = [];
// Return to main menu
gameState = 'menu';
// Add menu elements back
for (var i = 0; i < menuElements.length; i++) {
game.addChild(menuElements[i]);
}
return;
}
}
return; // Don't handle other interactions while defeat screen is active
}
if (gameState === 'menu') {
// Check if play button was clicked
var playButtonBounds = {
left: playButton.x - playButton.width * playButton.scaleX / 2,
right: playButton.x + playButton.width * playButton.scaleX / 2,
top: playButton.y - playButton.height * playButton.scaleY / 2,
bottom: playButton.y + playButton.height * playButton.scaleY / 2
};
if (x >= playButtonBounds.left && x <= playButtonBounds.right && y >= playButtonBounds.top && y <= playButtonBounds.bottom) {
startGame();
}
} else if (gameState === 'playing') {
// Check if pause button was clicked
var pauseButtonBounds = {
left: pauseButton.x - pauseButton.width * pauseButton.scaleX / 2,
right: pauseButton.x + pauseButton.width * pauseButton.scaleX / 2,
top: pauseButton.y - pauseButton.height * pauseButton.scaleY / 2,
bottom: pauseButton.y + pauseButton.height * pauseButton.scaleY / 2
};
if (x >= pauseButtonBounds.left && x <= pauseButtonBounds.right && y >= pauseButtonBounds.top && y <= pauseButtonBounds.bottom) {
showPauseMenu();
} else {
// Check if button1 was clicked (only if button1 exists)
if (button1) {
var button1Bounds = {
left: button1.x - button1.width * button1.scaleX / 2,
right: button1.x + button1.width * button1.scaleX / 2,
top: button1.y - button1.height * button1.scaleY / 2,
bottom: button1.y + button1.height * button1.scaleY / 2
};
if (x >= button1Bounds.left && x <= button1Bounds.right && y >= button1Bounds.top && y <= button1Bounds.bottom) {
// Check if player has enough points to use button1
if (score < 750) {
// Show feedback that player doesn't have enough points
// Could add visual/audio feedback here in the future
return;
}
// Play exchange sound when button1 is pressed
LK.getSound('button1Exchange').play();
// Enable selection mode
if (!selectionMode) {
selectionMode = true;
selectedCircles = [];
} else {
// Cancel selection mode
selectionMode = false;
// Reset all selected circles
for (var i = 0; i < selectedCircles.length; i++) {
var circle = selectedCircles[i];
circle.isSelected = false;
var circleGraphics = circle.children[0];
if (circleGraphics) {
circleGraphics.tint = circle.originalTint;
}
}
selectedCircles = [];
}
}
}
// Check if button2 was clicked (only if button2 exists)
if (button2) {
var button2Bounds = {
left: button2.x - button2.width * button2.scaleX / 2,
right: button2.x + button2.width * button2.scaleX / 2,
top: button2.y - button2.height * button2.scaleY / 2,
bottom: button2.y + button2.height * button2.scaleY / 2
};
if (x >= button2Bounds.left && x <= button2Bounds.right && y >= button2Bounds.top && y <= button2Bounds.bottom) {
// Check if player has enough points to use button2
if (score < 650) {
// Show feedback that player doesn't have enough points
return;
}
// Deduct cost for using button2
score -= 650;
scoreText.setText('Score: ' + score);
scoreCounter.setText('Puntos: ' + score);
// Only swap positions if there are at least 2 circles in the container
if (circles.length >= 2) {
// Create array of current positions
var positions = [];
for (var i = 0; i < circles.length; i++) {
positions.push({
x: circles[i].x,
y: circles[i].y
});
}
// Shuffle the positions array
for (var i = positions.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = positions[i];
positions[i] = positions[j];
positions[j] = temp;
}
// Instantly set each circle to its new position
for (var i = 0; i < circles.length; i++) {
var circle = circles[i];
var newPos = positions[i];
// Set position instantly without animation
circle.x = newPos.x;
circle.y = newPos.y;
}
}
}
}
// Check if button3 was clicked (only if button3 exists)
if (button3) {
var button3Bounds = {
left: button3.x - button3.width * button3.scaleX / 2,
right: button3.x + button3.width * button3.scaleX / 2,
top: button3.y - button3.height * button3.scaleY / 2,
bottom: button3.y + button3.height * button3.scaleY / 2
};
if (x >= button3Bounds.left && x <= button3Bounds.right && y >= button3Bounds.top && y <= button3Bounds.bottom) {
// Check if player has enough points to use button3
if (score < 9999) {
// Show feedback that player doesn't have enough points
return;
}
// Deduct cost for using button3
score -= 9999;
scoreText.setText('Score: ' + score);
scoreCounter.setText('Puntos: ' + score);
// Show victory screen
LK.showYouWin();
}
}
// Check if click is inside the container (frasco) boundaries and not in selection mode
if (!selectionMode && x >= containerX + 20 && x <= containerX + containerWidth - 20 && y >= containerY && y <= containerY + containerHeight - 20) {
// Create and drop a circle
var newCircle = new Circle(nextCircleType);
newCircle.x = Math.max(containerX + 50, Math.min(x, containerX + containerWidth - 50));
newCircle.y = containerY - 100; // Spawn above the red line
newCircle.velocityY = 2;
newCircle.velocityX = 0;
newCircle.lastY = newCircle.y;
newCircle.lastIntersecting = false;
// Set individual spawn immunity for this circle
newCircle.spawnImmunity = true;
newCircle.spawnTime = LK.ticks;
game.addChild(newCircle);
circles.push(newCircle);
// Use tween to disable immunity after 3 seconds for this specific circle
var immunityObj = {
immunity: 1
};
tween(immunityObj, {
immunity: 0
}, {
duration: 3000,
onFinish: function onFinish() {
newCircle.spawnImmunity = false;
}
});
generateNextCircle();
}
}
} else if (gameState === 'paused') {
// Handle pause menu interactions
var resumeButtonBounds = {
left: resumeButton.x - resumeButton.width * resumeButton.scaleX / 2,
right: resumeButton.x + resumeButton.width * resumeButton.scaleX / 2,
top: resumeButton.y - resumeButton.height * resumeButton.scaleY / 2,
bottom: resumeButton.y + resumeButton.height * resumeButton.scaleY / 2
};
var menuButtonBounds = {
left: menuButton.x - menuButton.width * menuButton.scaleX / 2,
right: menuButton.x + menuButton.width * menuButton.scaleX / 2,
top: menuButton.y - menuButton.height * menuButton.scaleY / 2,
bottom: menuButton.y + menuButton.height * menuButton.scaleY / 2
};
var restartButtonBounds = {
left: restartButton.x - restartButton.width * restartButton.scaleX / 2,
right: restartButton.x + restartButton.width * restartButton.scaleX / 2,
top: restartButton.y - restartButton.height * restartButton.scaleY / 2,
bottom: restartButton.y + restartButton.height * restartButton.scaleY / 2
};
var volumeButtonBounds = {
left: volumeButton.x - volumeButton.width * volumeButton.scaleX / 2,
right: volumeButton.x + volumeButton.width * volumeButton.scaleX / 2,
top: volumeButton.y - volumeButton.height * volumeButton.scaleY / 2,
bottom: volumeButton.y + volumeButton.height * volumeButton.scaleY / 2
};
if (x >= resumeButtonBounds.left && x <= resumeButtonBounds.right && y >= resumeButtonBounds.top && y <= resumeButtonBounds.bottom) {
resumeGame();
} else if (x >= menuButtonBounds.left && x <= menuButtonBounds.right && y >= menuButtonBounds.top && y <= menuButtonBounds.bottom) {
returnToMainMenu();
} else if (x >= restartButtonBounds.left && x <= restartButtonBounds.right && y >= restartButtonBounds.top && y <= restartButtonBounds.bottom) {
restartGame();
} else if (x >= volumeButtonBounds.left && x <= volumeButtonBounds.right && y >= volumeButtonBounds.top && y <= volumeButtonBounds.bottom) {
showVolumeControl();
}
} else if (gameState === 'settings') {
// Handle settings interactions
var decreaseButtonBounds = {
left: decreaseButton.x - decreaseButton.width * decreaseButton.scaleX / 2,
right: decreaseButton.x + decreaseButton.width * decreaseButton.scaleX / 2,
top: decreaseButton.y - decreaseButton.height * decreaseButton.scaleY / 2,
bottom: decreaseButton.y + decreaseButton.height * decreaseButton.scaleY / 2
};
var increaseButtonBounds = {
left: increaseButton.x - increaseButton.width * increaseButton.scaleX / 2,
right: increaseButton.x + increaseButton.width * increaseButton.scaleX / 2,
top: increaseButton.y - increaseButton.height * increaseButton.scaleY / 2,
bottom: increaseButton.y + increaseButton.height * increaseButton.scaleY / 2
};
var backFromSettingsButtonBounds = {
left: backFromSettingsButton.x - backFromSettingsButton.width * backFromSettingsButton.scaleX / 2,
right: backFromSettingsButton.x + backFromSettingsButton.width * backFromSettingsButton.scaleX / 2,
top: backFromSettingsButton.y - backFromSettingsButton.height * backFromSettingsButton.scaleY / 2,
bottom: backFromSettingsButton.y + backFromSettingsButton.height * backFromSettingsButton.scaleY / 2
};
if (x >= decreaseButtonBounds.left && x <= decreaseButtonBounds.right && y >= decreaseButtonBounds.top && y <= decreaseButtonBounds.bottom) {
sensitivity = Math.max(0.1, sensitivity - 0.1);
storage.sensitivity = sensitivity;
sensitivityText.setText('Sensibilidad: ' + Math.round(sensitivity * 100) + '%');
} else if (x >= increaseButtonBounds.left && x <= increaseButtonBounds.right && y >= increaseButtonBounds.top && y <= increaseButtonBounds.bottom) {
sensitivity = Math.min(1.0, sensitivity + 0.1);
storage.sensitivity = sensitivity;
sensitivityText.setText('Sensibilidad: ' + Math.round(sensitivity * 100) + '%');
} else if (x >= backFromSettingsButtonBounds.left && x <= backFromSettingsButtonBounds.right && y >= backFromSettingsButtonBounds.top && y <= backFromSettingsButtonBounds.bottom) {
backToPauseMenu();
}
} else if (gameState === 'volume') {
// Handle volume control interactions
var volumeDecreaseButtonBounds = {
left: volumeDecreaseButton.x - volumeDecreaseButton.width * volumeDecreaseButton.scaleX / 2,
right: volumeDecreaseButton.x + volumeDecreaseButton.width * volumeDecreaseButton.scaleX / 2,
top: volumeDecreaseButton.y - volumeDecreaseButton.height * volumeDecreaseButton.scaleY / 2,
bottom: volumeDecreaseButton.y + volumeDecreaseButton.height * volumeDecreaseButton.scaleY / 2
};
var volumeIncreaseButtonBounds = {
left: volumeIncreaseButton.x - volumeIncreaseButton.width * volumeIncreaseButton.scaleX / 2,
right: volumeIncreaseButton.x + volumeIncreaseButton.width * volumeIncreaseButton.scaleX / 2,
top: volumeIncreaseButton.y - volumeIncreaseButton.height * volumeIncreaseButton.scaleY / 2,
bottom: volumeIncreaseButton.y + volumeIncreaseButton.height * volumeIncreaseButton.scaleY / 2
};
var backFromVolumeButtonBounds = {
left: backFromVolumeButton.x - backFromVolumeButton.width * backFromVolumeButton.scaleX / 2,
right: backFromVolumeButton.x + backFromVolumeButton.width * backFromVolumeButton.scaleX / 2,
top: backFromVolumeButton.y - backFromVolumeButton.height * backFromVolumeButton.scaleY / 2,
bottom: backFromVolumeButton.y + backFromVolumeButton.height * backFromVolumeButton.scaleY / 2
};
if (x >= volumeDecreaseButtonBounds.left && x <= volumeDecreaseButtonBounds.right && y >= volumeDecreaseButtonBounds.top && y <= volumeDecreaseButtonBounds.bottom) {
musicVolume = Math.max(0.0, musicVolume - 0.1);
volumeText.setText('Volumen: ' + Math.round(musicVolume * 100) + '%');
// Update music volume by restarting it with new volume
LK.stopMusic();
if (musicVolume > 0) {
LK.playMusic('NightChaos', {
fade: {
start: 0,
end: musicVolume,
duration: 500
}
});
}
} else if (x >= volumeIncreaseButtonBounds.left && x <= volumeIncreaseButtonBounds.right && y >= volumeIncreaseButtonBounds.top && y <= volumeIncreaseButtonBounds.bottom) {
musicVolume = Math.min(1.0, musicVolume + 0.1);
volumeText.setText('Volumen: ' + Math.round(musicVolume * 100) + '%');
// Update music volume by restarting it with new volume
LK.stopMusic();
if (musicVolume > 0) {
LK.playMusic('NightChaos', {
fade: {
start: 0,
end: musicVolume,
duration: 500
}
});
}
} else if (x >= backFromVolumeButtonBounds.left && x <= backFromVolumeButtonBounds.right && y >= backFromVolumeButtonBounds.top && y <= backFromVolumeButtonBounds.bottom) {
backToPauseMenuFromVolume();
}
} else if (gameState === 'chaos') {
// Handle chaos screen interactions
var chaosButtonBounds = {
left: chaosScreenElements[2].x - chaosScreenElements[2].width * chaosScreenElements[2].scaleX / 2,
right: chaosScreenElements[2].x + chaosScreenElements[2].width * chaosScreenElements[2].scaleX / 2,
top: chaosScreenElements[2].y - chaosScreenElements[2].height * chaosScreenElements[2].scaleY / 2,
bottom: chaosScreenElements[2].y + chaosScreenElements[2].height * chaosScreenElements[2].scaleY / 2
};
var backToChaosMenuButtonBounds = {
left: chaosScreenElements[4].x - chaosScreenElements[4].width * chaosScreenElements[4].scaleX / 2,
right: chaosScreenElements[4].x + chaosScreenElements[4].width * chaosScreenElements[4].scaleX / 2,
top: chaosScreenElements[4].y - chaosScreenElements[4].height * chaosScreenElements[4].scaleY / 2,
bottom: chaosScreenElements[4].y + chaosScreenElements[4].height * chaosScreenElements[4].scaleY / 2
};
if (x >= chaosButtonBounds.left && x <= chaosButtonBounds.right && y >= chaosButtonBounds.top && y <= chaosButtonBounds.bottom) {
// CHAOS button clicked - open battle screen
showBattleScreen();
} else if (x >= backToChaosMenuButtonBounds.left && x <= backToChaosMenuButtonBounds.right && y >= backToChaosMenuButtonBounds.top && y <= backToChaosMenuButtonBounds.bottom) {
returnToMainMenuFromChaos();
}
} else if (gameState === 'battle') {
// Handle food interface first
if (foodInterfaceActive) {
// Check for food button clicks - iterate through all elements and check if they have foodType property
for (var i = 0; i < foodInterfaceElements.length; i++) {
var foodButton = foodInterfaceElements[i];
if (foodButton.foodType) {
// This is a food button
var foodButtonBounds = {
left: foodButton.x - foodButton.width * foodButton.scaleX / 2,
right: foodButton.x + foodButton.width * foodButton.scaleX / 2,
top: foodButton.y - foodButton.height * foodButton.scaleY / 2,
bottom: foodButton.y + foodButton.height * foodButton.scaleY / 2
};
if (x >= foodButtonBounds.left && x <= foodButtonBounds.right && y >= foodButtonBounds.top && y <= foodButtonBounds.bottom) {
// Check if food item is already used
if (foodButton.isUsed) {
// Show message that item is already used
var usedText = new Text2('Ya usado', {
size: 50,
fill: 0xFF4444
});
usedText.anchor.set(0.5, 0.5);
usedText.x = 2048 / 2;
usedText.y = 2732 / 2 - 300;
game.addChild(usedText);
// Animate used text
tween(usedText, {
y: usedText.y - 50,
alpha: 0
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(usedText);
}
});
return;
}
// Mark food item as used
usedFoodItems.push(foodButton.foodId);
// Heal player
var healAmount = foodButton.healAmount;
var currentHP = characterData[0].hp;
var maxHP = 150; // Character's max HP
var newHP = Math.min(maxHP, currentHP + healAmount);
characterData[0].hp = newHP;
// Update HP display in battle card
if (battleCardElements.length > 4) {
var hpText = battleCardElements[4]; // HP text element
hpText.setText('HP: ' + newHP);
}
// Show heal effect
var healText = new Text2('+' + healAmount + ' HP', {
size: 60,
fill: 0x00FF00
});
healText.anchor.set(0.5, 0.5);
healText.x = 2048 / 2;
healText.y = 2732 / 2 - 300;
game.addChild(healText);
// Animate heal text
tween(healText, {
y: healText.y - 100,
alpha: 0
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(healText);
}
});
// Flash screen green for healing
LK.effects.flashScreen(0x00FF00, 500);
// Close food interface
closeFoodInterface();
// Proceed to enemy turn
isPlayerTurn = false;
isEnemyTurn = true;
LK.setTimeout(function () {
isEnemyTurn = false;
}, 3000);
return;
}
}
}
return; // Don't handle other battle interactions while food interface is active
}
// Handle action interface first
if (actionInterfaceActive) {
// Check for action interface button clicks
if (actionInterfaceElements.length >= 10) {
// Stats button
var statsButton = actionInterfaceElements[4];
var statsButtonBounds = {
left: statsButton.x - statsButton.width * statsButton.scaleX / 2,
right: statsButton.x + statsButton.width * statsButton.scaleX / 2,
top: statsButton.y - statsButton.height * statsButton.scaleY / 2,
bottom: statsButton.y + statsButton.height * statsButton.scaleY / 2
};
if (x >= statsButtonBounds.left && x <= statsButtonBounds.right && y >= statsButtonBounds.top && y <= statsButtonBounds.bottom) {
// Close current action interface
closeActionInterface();
// Create full screen stats display
actionInterfaceActive = true;
actionInterfaceElements = [];
// Create semi-transparent background overlay
var overlay = LK.getAsset('battleBackground', {
anchorX: 0,
anchorY: 0
});
overlay.x = 0;
overlay.y = 0;
overlay.alpha = 0.7;
overlay.tint = 0x000000;
// Create main interface background (larger and centered)
var interfaceBg = LK.getAsset('characterCardBorder', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4.0,
scaleY: 3.0
});
interfaceBg.x = 2048 / 2;
interfaceBg.y = 2732 / 2;
var interfaceContent = LK.getAsset('characterCard', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3.8,
scaleY: 2.8
});
interfaceContent.x = interfaceBg.x;
interfaceContent.y = interfaceBg.y;
// Create large title text
var titleText = new Text2('ESTADÍSTICAS DEL ENEMIGO', {
size: 80,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = interfaceBg.x;
titleText.y = interfaceBg.y - 250;
// Create large stats display
var damageText = new Text2('Daño: 25', {
size: 70,
fill: 0xFF4444
});
damageText.anchor.set(0.5, 0.5);
damageText.x = interfaceBg.x;
damageText.y = interfaceBg.y - 100;
var defenseText = new Text2('Defensa: 15', {
size: 70,
fill: 0x4444FF
});
defenseText.anchor.set(0.5, 0.5);
defenseText.x = interfaceBg.x;
defenseText.y = interfaceBg.y - 20;
var chaosText = new Text2('Chaos: 100', {
size: 70,
fill: 0xFF44FF
});
chaosText.anchor.set(0.5, 0.5);
chaosText.x = interfaceBg.x;
chaosText.y = interfaceBg.y + 60;
// Store all elements (without continue button)
actionInterfaceElements = [overlay, interfaceBg, interfaceContent, titleText, damageText, defenseText, chaosText];
// Add all elements to game
for (var i = 0; i < actionInterfaceElements.length; i++) {
game.addChild(actionInterfaceElements[i]);
}
// Auto-close stats window after 2.5 seconds and trigger enemy turn
LK.setTimeout(function () {
closeActionInterface();
// Proceed directly to enemy turn when continuing from stats
isPlayerTurn = false;
isEnemyTurn = true;
// Set a timeout to end enemy turn after 3 seconds
LK.setTimeout(function () {
isEnemyTurn = false;
// Don't automatically start player turn - wait for diamonds to exit battle box
}, 3000);
}, 2500);
return;
}
// Talk button
var talkButton = actionInterfaceElements[6];
var talkButtonBounds = {
left: talkButton.x - talkButton.width * talkButton.scaleX / 2,
right: talkButton.x + talkButton.width * talkButton.scaleX / 2,
top: talkButton.y - talkButton.height * talkButton.scaleY / 2,
bottom: talkButton.y + talkButton.height * talkButton.scaleY / 2
};
if (x >= talkButtonBounds.left && x <= talkButtonBounds.right && y >= talkButtonBounds.top && y <= talkButtonBounds.bottom) {
// Close action interface first
closeActionInterface();
// Show talk message below battle box
var battleBox = battleScreenElements[1];
if (battleBox) {
// Create message box background
var messageBoxBg = LK.getAsset('characterCardBorder', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6.0,
scaleY: 1.5
});
messageBoxBg.x = battleBox.x;
messageBoxBg.y = battleBox.y + 600; // Position below battle box
messageBoxBg.tint = 0x333333;
var messageBoxContent = LK.getAsset('characterCard', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 5.8,
scaleY: 1.3
});
messageBoxContent.x = messageBoxBg.x;
messageBoxContent.y = messageBoxBg.y;
messageBoxContent.tint = 0x000000;
// Create the talk message text - start with empty text for typing effect
var fullMessage = 'Intentas hablar con Jevil, pero parece no prestar mucha atencion';
var talkMessageText = new Text2('', {
size: 45,
fill: 0xFFFFFF
});
talkMessageText.anchor.set(0.5, 0.5);
talkMessageText.x = messageBoxBg.x;
talkMessageText.y = messageBoxBg.y;
// Add message elements to game
game.addChild(messageBoxBg);
game.addChild(messageBoxContent);
game.addChild(talkMessageText);
// Create typing animation using tween
var typingProgress = {
charIndex: 0
};
tween(typingProgress, {
charIndex: fullMessage.length
}, {
duration: 2000,
// 2 seconds for typing animation
easing: tween.linear,
onFinish: function onFinish() {
// Ensure full message is displayed
talkMessageText.setText(fullMessage);
}
});
// Update text during typing animation
var typingInterval = LK.setInterval(function () {
var currentText = fullMessage.substring(0, Math.floor(typingProgress.charIndex));
talkMessageText.setText(currentText);
if (typingProgress.charIndex >= fullMessage.length) {
LK.clearInterval(typingInterval);
}
}, 50); // Update every 50ms for smooth typing effect
// Auto-remove message after 4.5 seconds and proceed to enemy turn
LK.setTimeout(function () {
LK.clearInterval(typingInterval); // Clean up interval
game.removeChild(messageBoxBg);
game.removeChild(messageBoxContent);
game.removeChild(talkMessageText);
// Proceed to enemy turn
isPlayerTurn = false;
isEnemyTurn = true;
LK.setTimeout(function () {
isEnemyTurn = false;
}, 3000);
}, 4500);
}
return;
}
// No continue button handling needed as stats auto-close after 2.5 seconds
// Close button for normal action interface (if this is the normal interface, not stats)
if (actionInterfaceElements.length === 10) {
var closeButton = actionInterfaceElements[8]; // Close button in normal action interface
var closeButtonBounds = {
left: closeButton.x - closeButton.width * closeButton.scaleX / 2,
right: closeButton.x + closeButton.width * closeButton.scaleX / 2,
top: closeButton.y - closeButton.height * closeButton.scaleY / 2,
bottom: closeButton.y + closeButton.height * closeButton.scaleY / 2
};
if (x >= closeButtonBounds.left && x <= closeButtonBounds.right && y >= closeButtonBounds.top && y <= closeButtonBounds.bottom) {
closeActionInterface();
return;
}
}
}
return; // Don't handle other battle interactions while action interface is active
}
// Handle timing mini-game first
if (timingGameActive) {
var damage = calculateDamageFromTiming();
cleanupTimingMiniGame();
if (damage > 0) {
var isPerfect = damage === 25; // Perfect is maximum damage
// Deal damage to enemy
enemyHealth = Math.max(0, enemyHealth - damage);
// Update enemy health bar and text
if (battleScreenElements.length >= 10) {
var enemyHealthBar = battleScreenElements[8];
var enemyHealthText = battleScreenElements[9];
// Animate health bar reduction
tween(enemyHealthBar, {
scaleX: enemyHealth / maxEnemyHealth * 5.3
}, {
duration: 500,
easing: tween.easeOut
});
enemyHealthText.setText('ENEMY HP: ' + enemyHealth + '/' + maxEnemyHealth);
}
// Flash screen different colors based on timing quality
if (isPerfect) {
// Perfect timing (25 damage) - flash gold
LK.effects.flashScreen(0xFFD700, 500);
} else if (damage >= 20) {
// Great timing (20-24 damage) - flash bright green
LK.effects.flashScreen(0x00FF00, 500);
} else {
// Good timing (10-19 damage) - flash regular green
LK.effects.flashScreen(0x44AA44, 500);
}
// Create damage text with color based on timing quality
var damageColor = 0xFF0000; // Default red
if (isPerfect) {
damageColor = 0xFFD700; // Gold for perfect
} else if (damage >= 20) {
damageColor = 0x00FF00; // Bright green for great
} else if (damage >= 15) {
damageColor = 0x44AA44; // Regular green for good
}
var damageText = new Text2('-' + damage + ' HP', {
size: 80,
fill: damageColor
});
damageText.anchor.set(0.5, 0.5);
damageText.x = 2048 / 2;
damageText.y = 2732 / 2 - 300;
game.addChild(damageText);
// Add quality text based on damage amount
if (isPerfect) {
var qualityText = new Text2('¡PERFECTO!', {
size: 60,
fill: 0xFFD700
});
qualityText.anchor.set(0.5, 0.5);
qualityText.x = 2048 / 2;
qualityText.y = 2732 / 2 - 200;
game.addChild(qualityText);
// Animate quality text
tween(qualityText, {
y: qualityText.y - 50,
alpha: 0
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(qualityText);
}
});
} else if (damage >= 20) {
var qualityText = new Text2('¡EXCELENTE!', {
size: 50,
fill: 0x00FF00
});
qualityText.anchor.set(0.5, 0.5);
qualityText.x = 2048 / 2;
qualityText.y = 2732 / 2 - 200;
game.addChild(qualityText);
// Animate quality text
tween(qualityText, {
y: qualityText.y - 50,
alpha: 0
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(qualityText);
}
});
}
// Animate damage text
tween(damageText, {
y: damageText.y - 100,
alpha: 0
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(damageText);
}
});
// Check if enemy is defeated
if (enemyHealth <= 0) {
// Enemy defeated - show victory
var victoryText = new Text2('¡ENEMIGO DERROTADO!', {
size: 100,
fill: 0x00FF00
});
victoryText.anchor.set(0.5, 0.5);
victoryText.x = 2048 / 2;
victoryText.y = 2732 / 2;
game.addChild(victoryText);
// Exit battle after 2 seconds
LK.setTimeout(function () {
game.removeChild(victoryText);
exitBattleScreen();
}, 2000);
return;
}
} else {
// Failed timing - show miss
LK.effects.flashScreen(0xFF0000, 300);
var missText = new Text2('¡FALLASTE!', {
size: 60,
fill: 0xFF0000
});
missText.anchor.set(0.5, 0.5);
missText.x = 2048 / 2;
missText.y = 2732 / 2;
game.addChild(missText);
// Animate miss text
tween(missText, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
game.removeChild(missText);
}
});
}
// Now trigger enemy turn
isPlayerTurn = false;
isEnemyTurn = true;
LK.setTimeout(function () {
isEnemyTurn = false;
// Don't automatically start player turn - wait for diamonds to exit battle box
}, 3000);
return;
}
// Handle battle screen interactions
if (battleScreenElements.length >= 5) {
var battlePauseButton = battleScreenElements[3];
var battlePauseButtonBounds = {
left: battlePauseButton.x - battlePauseButton.width * battlePauseButton.scaleX / 2,
right: battlePauseButton.x + battlePauseButton.width * battlePauseButton.scaleX / 2,
top: battlePauseButton.y - battlePauseButton.height * battlePauseButton.scaleY / 2,
bottom: battlePauseButton.y + battlePauseButton.height * battlePauseButton.scaleY / 2
};
if (x >= battlePauseButtonBounds.left && x <= battlePauseButtonBounds.right && y >= battlePauseButtonBounds.top && y <= battlePauseButtonBounds.bottom) {
exitBattleScreen();
}
// Check if there are diamonds still in the battle box
var battleBox = battleScreenElements[1];
var diamondsInBattleBox = false;
if (battleBox && enemyDiamonds.length > 0) {
var battleBoxWidth = battleBox.width * battleBox.scaleX;
var battleBoxHeight = battleBox.height * battleBox.scaleY;
var battleBoxLeft = battleBox.x - battleBoxWidth / 2;
var battleBoxRight = battleBox.x + battleBoxWidth / 2;
var battleBoxTop = battleBox.y - battleBoxHeight / 2;
var battleBoxBottom = battleBox.y + battleBoxHeight / 2;
for (var i = 0; i < enemyDiamonds.length; i++) {
var diamond = enemyDiamonds[i];
// Check if diamond is still inside battle box
if (diamond.x >= battleBoxLeft && diamond.x <= battleBoxRight && diamond.y >= battleBoxTop && diamond.y <= battleBoxBottom) {
diamondsInBattleBox = true;
break;
}
}
}
// Check for action button clicks (if battle cards exist and no diamonds in battle box)
if (battleCardElements.length > 0 && isPlayerTurn && !diamondsInBattleBox) {
// Check action buttons for single character card (buttons start at index 7)
var buttonStartIndex = 7;
// ATACAR button
var attackButton = battleCardElements[buttonStartIndex];
if (attackButton) {
var attackButtonBounds = {
left: attackButton.x - attackButton.width * attackButton.scaleX / 2,
right: attackButton.x + attackButton.width * attackButton.scaleX / 2,
top: attackButton.y - attackButton.height * attackButton.scaleY / 2,
bottom: attackButton.y + attackButton.height * attackButton.scaleY / 2
};
if (x >= attackButtonBounds.left && x <= attackButtonBounds.right && y >= attackButtonBounds.top && y <= attackButtonBounds.bottom) {
handlePlayerAction('attack');
}
}
// ACTUAR button
var actButton = battleCardElements[buttonStartIndex + 2];
if (actButton) {
var actButtonBounds = {
left: actButton.x - actButton.width * actButton.scaleX / 2,
right: actButton.x + actButton.width * actButton.scaleX / 2,
top: actButton.y - actButton.height * actButton.scaleY / 2,
bottom: actButton.y + actButton.height * actButton.scaleY / 2
};
if (x >= actButtonBounds.left && x <= actButtonBounds.right && y >= actButtonBounds.top && y <= actButtonBounds.bottom) {
handlePlayerAction('act');
}
}
// COMIDA button
var foodButton = battleCardElements[buttonStartIndex + 4];
if (foodButton) {
var foodButtonBounds = {
left: foodButton.x - foodButton.width * foodButton.scaleX / 2,
right: foodButton.x + foodButton.width * foodButton.scaleX / 2,
top: foodButton.y - foodButton.height * foodButton.scaleY / 2,
bottom: foodButton.y + foodButton.height * foodButton.scaleY / 2
};
if (x >= foodButtonBounds.left && x <= foodButtonBounds.right && y >= foodButtonBounds.top && y <= foodButtonBounds.bottom) {
handlePlayerAction('heal');
}
}
// DEFENSA button
var defenseButton = battleCardElements[buttonStartIndex + 6];
if (defenseButton) {
var defenseButtonBounds = {
left: defenseButton.x - defenseButton.width * defenseButton.scaleX / 2,
right: defenseButton.x + defenseButton.width * defenseButton.scaleX / 2,
top: defenseButton.y - defenseButton.height * defenseButton.scaleY / 2,
bottom: defenseButton.y + defenseButton.height * defenseButton.scaleY / 2
};
if (x >= defenseButtonBounds.left && x <= defenseButtonBounds.right && y >= defenseButtonBounds.top && y <= defenseButtonBounds.bottom) {
handlePlayerAction('defend');
}
}
}
}
}
};
game.move = function (x, y, obj) {
// Handle heart cursor movement in battle screen - allow movement until all diamonds exit battle box
if (gameState === 'battle' && battleScreenElements.length >= 6) {
// Check if there are diamonds still in the battle box
var battleBox = battleScreenElements[1];
var diamondsInBattleBox = false;
if (battleBox && enemyDiamonds.length > 0) {
var battleBoxWidth = battleBox.width * battleBox.scaleX;
var battleBoxHeight = battleBox.height * battleBox.scaleY;
var battleBoxLeft = battleBox.x - battleBoxWidth / 2;
var battleBoxRight = battleBox.x + battleBoxWidth / 2;
var battleBoxTop = battleBox.y - battleBoxHeight / 2;
var battleBoxBottom = battleBox.y + battleBoxHeight / 2;
for (var i = 0; i < enemyDiamonds.length; i++) {
var diamond = enemyDiamonds[i];
// Check if diamond is still inside battle box
if (diamond.x >= battleBoxLeft && diamond.x <= battleBoxRight && diamond.y >= battleBoxTop && diamond.y <= battleBoxBottom) {
diamondsInBattleBox = true;
break;
}
}
}
// Allow heart movement during enemy turn OR when there are diamonds in battle box
if (isEnemyTurn || diamondsInBattleBox) {
var heartCursor = battleScreenElements[5];
if (heartCursor && battleBox) {
// Calculate the green rectangle boundaries within the battleBox
// Make the heart movement area 2.2 times smaller (larger than before)
var battleBoxWidth = battleBox.width * battleBox.scaleX;
var battleBoxHeight = battleBox.height * battleBox.scaleY;
var smallerWidth = battleBoxWidth / 2.2;
var smallerHeight = battleBoxHeight / 1.8; // Make height area larger (1.8 instead of 2.2)
var battleBoxLeft = battleBox.x - smallerWidth / 2;
var battleBoxRight = battleBox.x + smallerWidth / 2;
var battleBoxTop = battleBox.y - smallerHeight / 2;
var battleBoxBottom = battleBox.y + smallerHeight / 2;
// Constrain heart cursor within the adjusted green rectangle boundaries
heartCursor.x = Math.max(battleBoxLeft, Math.min(x, battleBoxRight));
heartCursor.y = Math.max(battleBoxTop, Math.min(y, battleBoxBottom));
}
}
}
};
game.up = function (x, y, obj) {
if (gameState === 'playing') {
isDragging = false;
}
};
// Suika Game helper functions can be added here if needed
// Override LK's game over handling to show defeat screen
var originalShowGameOver = LK.showGameOver;
LK.showGameOver = function () {
// Show our custom defeat screen instead of standard game over
createDefeatScreen();
};
// Override LK's restart handling to ensure defeat screen appears
var originalRestart = LK.restart || function () {};
LK.restart = function () {
// When player clicks restart/CHOS button after game over, show defeat screen
createDefeatScreen();
};
// Main game update
game.update = function () {
// Animate fog elements in menu
if (gameState === 'menu') {
for (var i = 0; i < fogElements.length; i++) {
var fog = fogElements[i];
fog.x += Math.cos(fog.fogDirection) * fog.fogSpeed;
fog.y += Math.sin(fog.fogDirection) * fog.fogSpeed * 0.3;
fog.alpha += Math.sin(LK.ticks * 0.02 + i) * 0.01;
// Keep fog within bounds and wrap around
if (fog.x < -100) fog.x = 2148;
if (fog.x > 2148) fog.x = -100;
if (fog.y < 1000) fog.y = 2200;
if (fog.y > 2200) fog.y = 1000;
}
}
if (gameState === 'playing') {
// Handle circle merging
var mergedCircles = [];
var circlesToRemove = [];
for (var i = circles.length - 1; i >= 0; i--) {
var circle = circles[i];
if (circle.shouldMerge && circle.mergeInto) {
// Only add the merged circle once
if (mergedCircles.indexOf(circle.mergeInto) === -1) {
game.addChild(circle.mergeInto);
mergedCircles.push(circle.mergeInto);
circles.push(circle.mergeInto);
circle.mergeInto.lastY = circle.mergeInto.y;
circle.mergeInto.lastIntersecting = false;
// Set spawn immunity for merged circles
circle.mergeInto.spawnImmunity = true;
circle.mergeInto.spawnTime = LK.ticks;
// Use tween to disable immunity after 3 seconds for merged circle
var mergedImmunityObj = {
immunity: 1
};
var mergedCircle = circle.mergeInto; // Capture reference before tween
tween(mergedImmunityObj, {
immunity: 0
}, {
duration: 3000,
onFinish: function onFinish() {
if (mergedCircle) {
mergedCircle.spawnImmunity = false;
}
}
});
}
// Mark circle for removal
circlesToRemove.push(circle);
}
}
// Remove all circles that merged
for (var j = 0; j < circlesToRemove.length; j++) {
var circleToRemove = circlesToRemove[j];
game.removeChild(circleToRemove);
var index = circles.indexOf(circleToRemove);
if (index > -1) {
circles.splice(index, 1);
}
}
// Check for game over (circle rises and touches the red line)
for (var i = 0; i < circles.length; i++) {
var circle = circles[i];
// Only trigger game over if circle touches the red line and this specific circle's immunity is not active
if (circle.y - circle.radius <= containerY && !circle.spawnImmunity) {
// Game over condition - circle touched the red line
LK.showGameOver();
return;
}
}
}
if (gameState === 'battle' && battleScreenActive) {
// Handle timing mini-game
if (timingGameActive && timingLine) {
// Move timing line back and forth
timingLinePosition += timingLineSpeed * timingLineDirection;
// Bounce at edges
if (timingLinePosition >= 800) {
timingLinePosition = 800;
timingLineDirection = -1;
} else if (timingLinePosition <= 0) {
timingLinePosition = 0;
timingLineDirection = 1;
}
// Update visual position of timing line
timingLine.x = 2048 / 2 - 400 + timingLinePosition;
}
// Enemy shooting logic - only during enemy turn and every 0.5 seconds (30 ticks)
if (isEnemyTurn && LK.ticks - lastEnemyShootTime >= 30) {
lastEnemyShootTime = LK.ticks;
// Get enemy position from battleScreenElements
if (battleScreenElements.length >= 7) {
var enemyCharacter = battleScreenElements[6];
var heartCursor = battleScreenElements[5]; // Get heart cursor reference
var battleBox = battleScreenElements[1]; // Get battle box reference
// Store original position for return later
if (!enemyCharacter.originalX) {
enemyCharacter.originalX = enemyCharacter.x;
enemyCharacter.originalY = enemyCharacter.y;
}
// Calculate battle box boundaries to teleport outside of it
var battleBoxWidth = battleBox.width * battleBox.scaleX;
var battleBoxHeight = battleBox.height * battleBox.scaleY;
var battleBoxLeft = battleBox.x - battleBoxWidth / 2;
var battleBoxRight = battleBox.x + battleBoxWidth / 2;
var battleBoxTop = battleBox.y - battleBoxHeight / 2;
var battleBoxBottom = battleBox.y + battleBoxHeight / 2;
// Define screen areas avoiding battle box for random teleportation
var screenAreas = [
// Top area above battle box
{
minX: 200,
maxX: 1848,
minY: 200,
maxY: Math.max(battleBoxTop - 50, 300)
},
// Bottom area below battle box
{
minX: 200,
maxX: 1848,
minY: Math.min(battleBoxBottom + 50, 2100),
maxY: 2400
},
// Left area beside battle box
{
minX: 200,
maxX: Math.max(battleBoxLeft - 50, 400),
minY: 300,
maxY: 2400
},
// Right area beside battle box
{
minX: Math.min(battleBoxRight + 50, 1400),
maxX: 1848,
minY: 300,
maxY: 2400
}];
// Filter areas to ensure they are valid (minX < maxX, minY < maxY)
var validAreas = [];
for (var z = 0; z < screenAreas.length; z++) {
var area = screenAreas[z];
if (area.minX < area.maxX && area.minY < area.maxY) {
validAreas.push(area);
}
}
// If no valid areas, create a default safe area
if (validAreas.length === 0) {
validAreas = [{
minX: 200,
maxX: 500,
minY: 200,
maxY: 500
}];
}
// Choose random area from valid areas
var randomArea = validAreas[Math.floor(Math.random() * validAreas.length)];
// Calculate random position within chosen area
var newX = randomArea.minX + Math.random() * (randomArea.maxX - randomArea.minX);
var newY = randomArea.minY + Math.random() * (randomArea.maxY - randomArea.minY);
// Instantly teleport enemy to new position
enemyCharacter.x = newX;
enemyCharacter.y = newY;
// Different attack patterns based on turn counter
if (enemyTurnCounter % 2 === 0) {
// First attack pattern: single diamond (original attack)
var newDiamond = new EnemyDiamond();
newDiamond.x = enemyCharacter.x;
newDiamond.y = enemyCharacter.y;
newDiamond.lastX = newDiamond.x;
newDiamond.lastY = newDiamond.y;
// Set launch direction and rotation towards heart cursor
newDiamond.setLaunchDirection(heartCursor.x, heartCursor.y);
game.addChild(newDiamond);
enemyDiamonds.push(newDiamond);
} else {
// Second attack pattern: triple smaller circles with pica design - all launched simultaneously
// Store the three circles to launch them at the same time
var circlesToLaunch = [];
// Create 3 smaller, faster circles using pica asset design
for (var circleIndex = 0; circleIndex < 3; circleIndex++) {
var largeCircle = LK.getAsset('pica', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
// Make them smaller (was 3.0, now 1.8)
scaleY: 1.8
});
largeCircle.x = enemyCharacter.x;
largeCircle.y = enemyCharacter.y;
largeCircle.speed = 8.5; // Faster speed (was 6.0, now 8.5)
largeCircle.velocityX = 0;
largeCircle.velocityY = 0;
largeCircle.lastX = largeCircle.x;
largeCircle.lastY = largeCircle.y;
largeCircle.tint = 0x8B0080; // Purple color for enemy circles
largeCircle.circleIndex = circleIndex; // Store circle index for spreading
largeCircle.spreadForce = 0; // Initial spread force
largeCircle.maxSpread = 150; // Maximum spread distance (15 cm)
largeCircle.currentSpread = 0; // Current spread distance
// Calculate target direction (all toward player initially)
var targetX = heartCursor.x;
var targetY = heartCursor.y;
// Calculate direction towards target
var deltaX = targetX - largeCircle.x;
var deltaY = targetY - largeCircle.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
// Set velocity toward target
if (distance > 0) {
largeCircle.velocityX = deltaX / distance * largeCircle.speed;
largeCircle.velocityY = deltaY / distance * largeCircle.speed;
// Set rotation to point towards target
largeCircle.rotation = Math.atan2(deltaY, deltaX);
} else {
largeCircle.velocityX = 0;
largeCircle.velocityY = largeCircle.speed;
largeCircle.rotation = Math.PI / 2; // Point downward
}
// Add update method for movement with gradual spreading effect
largeCircle.update = function () {
this.x += this.velocityX;
this.y += this.velocityY;
// Gradually increase spread force very slowly, but cap it
if (this.currentSpread < this.maxSpread) {
this.spreadForce += 0.03; // Set spreading speed to 3 (was 0.02, now 0.03)
this.currentSpread += Math.abs(this.spreadForce);
}
// Apply horizontal spreading based on circle index, but only if under max spread
if (this.currentSpread < this.maxSpread) {
if (this.circleIndex === 1) {
// Second circle spreads to the left
this.velocityX -= this.spreadForce;
} else if (this.circleIndex === 2) {
// Third circle spreads to the right
this.velocityX += this.spreadForce;
}
}
// Update rotation to point in direction of movement
this.rotation = Math.atan2(this.velocityY, this.velocityX);
};
// Store circle for simultaneous launch
circlesToLaunch.push(largeCircle);
}
// Launch all 3 circles at the same time
for (var launchIndex = 0; launchIndex < circlesToLaunch.length; launchIndex++) {
var circleToLaunch = circlesToLaunch[launchIndex];
game.addChild(circleToLaunch);
enemyDiamonds.push(circleToLaunch); // Add to same array for collision detection
}
}
}
}
// Update and manage enemy diamonds
for (var i = enemyDiamonds.length - 1; i >= 0; i--) {
var diamond = enemyDiamonds[i];
// Check collision with heart cursor
if (battleScreenElements.length >= 6) {
var heartCursor = battleScreenElements[5];
if (heartCursor) {
var dx = diamond.x - heartCursor.x;
var dy = diamond.y - heartCursor.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var collisionDistance = 40; // Collision radius
if (distance < collisionDistance) {
// Collision detected - deal damage to player
var damageAmount = playerDefenseActive ? 15 : 25; // Reduced damage if defending
var currentHP = characterData[0].hp;
var newHP = Math.max(0, currentHP - damageAmount);
characterData[0].hp = newHP;
// Update HP display in battle card
if (battleCardElements.length > 4) {
var hpText = battleCardElements[4]; // HP text element
hpText.setText('HP: ' + newHP);
}
// Show damage effect
var damageText = new Text2('-' + damageAmount + ' HP', {
size: 60,
fill: 0xFF0000
});
damageText.anchor.set(0.5, 0.5);
damageText.x = heartCursor.x;
damageText.y = heartCursor.y - 50;
game.addChild(damageText);
// Animate damage text
tween(damageText, {
y: damageText.y - 100,
alpha: 0
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(damageText);
}
});
// Flash screen red for damage
LK.effects.flashScreen(0xFF0000, 500);
// Remove diamond after collision
game.removeChild(diamond);
enemyDiamonds.splice(i, 1);
// Check if player is defeated
if (newHP <= 0) {
// Player defeated - trigger defeat screen
var defeatText = new Text2('¡HAS SIDO DERROTADO!', {
size: 100,
fill: 0xFF0000
});
defeatText.anchor.set(0.5, 0.5);
defeatText.x = 2048 / 2;
defeatText.y = 2732 / 2;
game.addChild(defeatText);
// Show defeat screen after 2 seconds
LK.setTimeout(function () {
game.removeChild(defeatText);
// Exit battle first, then show defeat screen
exitBattleScreen();
// Show defeat screen with retry and give up options
createDefeatScreen();
}, 2000);
return;
}
continue; // Skip other checks for this diamond
}
}
}
// Check if diamond is off screen
if (diamond.x < -50 || diamond.x > 2098 || diamond.y < -50 || diamond.y > 2782) {
game.removeChild(diamond);
enemyDiamonds.splice(i, 1);
}
}
// Return enemy to original position immediately when enemy turn ends (not waiting for player turn)
if (isEnemyTurn === false && battleScreenElements.length >= 7) {
var enemyCharacter = battleScreenElements[6];
// Check if enemy is not already at original position
if (enemyCharacter && enemyCharacter.originalX !== undefined) {
var distanceFromOriginal = Math.abs(enemyCharacter.x - enemyCharacter.originalX) + Math.abs(enemyCharacter.y - enemyCharacter.originalY);
if (distanceFromOriginal > 10) {
// Increment enemy turn counter when turn ends
enemyTurnCounter++;
// Instantly teleport enemy back to original position
enemyCharacter.x = enemyCharacter.originalX;
enemyCharacter.y = enemyCharacter.originalY;
// Immediately restart levitation animation at original position
enemyBaseX = enemyCharacter.originalX;
enemyBaseY = enemyCharacter.originalY;
// Stop any existing tweens on the enemy character
tween.stop(enemyCharacter);
// Start levitation immediately
startEnemyLevitation();
}
}
}
// Check if all diamonds have left the battle box area before allowing player turn
if (!isPlayerTurn && !isEnemyTurn) {
var battleBox = battleScreenElements[1];
if (battleBox) {
var battleBoxWidth = battleBox.width * battleBox.scaleX;
var battleBoxHeight = battleBox.height * battleBox.scaleY;
var battleBoxLeft = battleBox.x - battleBoxWidth / 2;
var battleBoxRight = battleBox.x + battleBoxWidth / 2;
var battleBoxTop = battleBox.y - battleBoxHeight / 2;
var battleBoxBottom = battleBox.y + battleBoxHeight / 2;
var allDiamondsOutside = true;
// Check if any diamonds are still inside battle box
for (var i = 0; i < enemyDiamonds.length; i++) {
var diamond = enemyDiamonds[i];
// Check if diamond is still inside battle box
if (diamond.x >= battleBoxLeft && diamond.x <= battleBoxRight && diamond.y >= battleBoxTop && diamond.y <= battleBoxBottom) {
allDiamondsOutside = false;
break;
}
}
// Only start player turn when all diamonds are outside battle box OR no diamonds exist
if (allDiamondsOutside) {
// Start player turn
isPlayerTurn = true;
// Position heart cursor automatically to center of battle box
var heartCursor = battleScreenElements[5];
if (heartCursor && battleBox) {
tween(heartCursor, {
x: battleBox.x,
y: battleBox.y
}, {
duration: 500,
easing: tween.easeOut
});
}
}
}
}
}
}; ===================================================================
--- original.js
+++ change.js
@@ -3305,9 +3305,9 @@
this.x += this.velocityX;
this.y += this.velocityY;
// Gradually increase spread force very slowly, but cap it
if (this.currentSpread < this.maxSpread) {
- this.spreadForce += 0.02; // Much slower spread increase (was 0.05, now 0.02)
+ this.spreadForce += 0.03; // Set spreading speed to 3 (was 0.02, now 0.03)
this.currentSpread += Math.abs(this.spreadForce);
}
// Apply horizontal spreading based on circle index, but only if under max spread
if (this.currentSpread < this.maxSpread) {
Niebla terrorifica. In-Game asset. 2d. High contrast. No shadows
marco de boton de inicio sin palabras en el. In-Game asset. 2d. High contrast. No shadows
una estrella hermosa con cara kawai que en su frente diga Dazai. In-Game asset. 2d. High contrast. No shadows
una luna redondita kawai con lentes de sol, en su frente lleva una sinta que dice STAR. In-Game asset. 2d. High contrast. No shadows
sacale el fondo de color negro, dejando solo al personaje con el redondeado rojo
un oso redondo. In-Game asset. 2d. High contrast. No shadows
un monito en una imagen redonda, el monito lleva gafas de sol, es de plastico y tiene una sonrisa. In-Game asset. 2d. High contrast. No shadows
un oso redondito, con una aureola, cara kawai y con los brazitos juntitos como rezando y cantando. In-Game asset. 2d. High contrast. No shadows
Nube realista de noche. In-Game asset. 2d. High contrast. No shadows
un edificio pixel art por la noche. In-Game asset. 2d. High contrast. No shadows
un boton color rojo, dentro de el hay un dibujo de dos flechas como indicando que se mezcla algo. In-Game asset. 2d. High contrast. No shadows
un boton redondo color amarillo, dentro de el hay un dinujo de una corona brillante. In-Game asset. 2d. High contrast. No shadows
una tabla de madera alargada como si fuese de una cocina. In-Game asset. 2d. High contrast. No shadows
Una luna brillante. In-Game asset. 2d. High contrast. No shadows
un corazon pixeleado al estilo de DELTARUNE u Undertale. In-Game asset. 2d. High contrast. No shadows
Jevil, un jefe del capitulo 1 de deltarune, es pixleado y el fondo detras de este es color blanco. In-Game asset. 2d. High contrast. No shadows
un diamante, es pixeleado, solo mejora su calidad, no cambies su forma
haz que este trebol blanco, sea pixeleado de 16x16
Jevil de deltarune capitulo uno siendo golpeado en el estomago echandose un poco para atras aunque con una risa loca en su rostro (pixeleado con fondo blanco). In-Game asset. 2d. High contrast. No shadows
Una caja sorpresa cerrada en blanco y negro pixeleado en 16x16 pixeles, en la caja hay un dibujo de unos ojos y sonrisa de Jevil de deltarune. el fondo de la imagen es de color rojo
un corazon de color blanco con bordes negros, el mismo que lanza Jevil en deltarune capitulo 1, el corazon es pixeleado 16x16 (el fondo de la imagen sea roja). In-Game asset. 2d. High contrast. No shadows
una bomba redonda, color blanco con bordes de color negro, es pixeleada de 16x16 (la imagen tiene fondo rojo). In-Game asset. 2d. High contrast. No shadows