User prompt
Pon en los botones de selección el ased player5 como el botón 5
User prompt
As que los ased para seleccionar los personajes estén en la izquierda de la pantalla y que sean un poco más grandes
User prompt
El doble salto no funciona
User prompt
As que el jugador tenga un doble salto y que las ias ased caminando1 y caminando2 lo tengan también
User prompt
Elimina la función del ased moneda3
User prompt
Elimina la función del ased moneda1
User prompt
Elimina los ased moneda1 y moneda2
User prompt
En la pantalla inicial añade 5 botones en la parte izquierda que estén numerados y que en 1 este el ased player 2 en el 2 el ased player3 en el 3 el ased player 4 y en el 5 el ased player
User prompt
El ases moneda1 debe seguir asta la distancia 10000 el ases manoeda3 asta la distancia 5000
User prompt
As que el ased moneda3 Siga asta la distancia 5000
User prompt
As que el ased moneda 3 aga lo mismo que el ased moneda1
User prompt
As qeu el ased moneda1 soga asta la distancia 10000
User prompt
As que el ased moneda1 aparezca en el modo infinito y que aga lo mismo que el ased Final1
User prompt
As que el ased moneda1 este en el modo infinito y que tenga las mismas mecánicas que el ased Final1 y que se detenga en la distancia 1000
User prompt
Al iniciar el modo normal se queda el botón para iniciar el modo infinito
User prompt
Please fix the bug: 'TypeError: Cannot read properties of null (reading 'x')' in or related to this line: 'var aiTargetCameraX = aiPlayer.x - 400;' Line Number: 1425
User prompt
As un nuevo botón debajo de elde inicio que eliminé las ias ased caminando1 y caminando2 y el ased Final1 y que sea infinito
User prompt
As que antes de iniciar el juego salga el título pixel race
User prompt
As que las ias ased caminando1 y caminando2 sean más lentas que el jugador
User prompt
As que las ias ased caminando1 y caminando2 sean más lentas que el jugador y la velocidad del salto sea más lenta que la del jugador
User prompt
El ased cielo1 está no está illendo a la velocidad del jugador
User prompt
El ases de cielo no está illendo a la velocidad correcta y se queda atrás
User prompt
El ased cielo1 está illendo al lado contrario del movimiento del jugado
User prompt
As qie el ased cielo1 siga el movimiento del jugador y que las ias ased caminando1 y caminando2 sean más lentos en el movimiento del salto
User prompt
Cambia el fondo predeterminado por el ases cielo1
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var AI = Container.expand(function () {
var self = Container.call(this);
var aiGraphics = self.attachAsset('Caminando1', {
anchorX: 0.5,
anchorY: 1.0,
width: 60,
height: 60
});
self.target = null;
self.lastX = 0;
self.lastY = 0;
self.stuckCounter = 0;
self.jumpCooldown = 0;
self.scanDistance = 800;
self.pathfindingCooldown = 0;
self.velocityY = 0;
self.velocityX = 0;
self.isGrounded = false;
self.jumpPower = -20;
self.gravity = 1.2;
self.speed = 4; // Slower than player
self.maxFallSpeed = 20;
// AI health and regeneration system
self.health = 100;
self.maxHealth = 100;
self.regenerationRate = 2; // Health points per second
self.damageCooldown = 0;
self.isRegenerating = false;
self.regenerationDelay = 60; // Frames to wait before starting regeneration after damage
// AI decision making
self.makeDecision = function () {
if (!aiGoalAsset) return;
// Update cooldowns
if (self.jumpCooldown > 0) self.jumpCooldown--;
if (self.pathfindingCooldown > 0) self.pathfindingCooldown--;
// Check if stuck
var aiMovement = Math.abs(self.x - self.lastX) + Math.abs(self.y - self.lastY);
if (aiMovement < 2) {
self.stuckCounter++;
} else {
self.stuckCounter = 0;
}
self.lastX = self.x;
self.lastY = self.y;
// Decision state system - AI can choose between different actions
var decisionState = self.evaluateSituation();
switch (decisionState) {
case 'JUMP':
if (self.isGrounded && self.jumpCooldown <= 0) {
self.jump();
self.jumpCooldown = 20;
}
break;
case 'MOVE_LEFT':
self.moveLeft();
break;
case 'MOVE_RIGHT':
self.moveRight();
break;
case 'STAY_STILL':
// AI decides to stay still - do nothing
self.velocityX *= 0.5; // Slow down gradually
break;
default:
// Default fallback behavior
self.executeDefaultBehavior();
break;
}
};
// Evaluate current situation and decide what action to take
self.evaluateSituation = function () {
if (!aiGoalAsset) return 'MOVE_RIGHT'; // Default if no goal
var goalDistance = aiGoalAsset.x - self.x;
var goalVerticalDistance = aiGoalAsset.y - self.y;
var obstacleAhead = self.checkForObstaclesAhead();
var distanceToGoal = Math.abs(goalDistance);
var goalReachable = distanceToGoal <= 1000; // Check if goal is within reachable distance
// Priority 1: If stuck for too long, jump
if (self.stuckCounter > 30 && self.isGrounded && self.jumpCooldown <= 0) {
return 'JUMP';
}
// Priority 2: Jump over obstacles when moving
if (obstacleAhead && self.isGrounded && self.jumpCooldown <= 0 && Math.abs(self.velocityX) > 1) {
return 'JUMP';
}
// Priority 3: Jump if goal is significantly above and we're close horizontally
if (Math.abs(goalDistance) < 200 && goalVerticalDistance < -100 && self.isGrounded && self.jumpCooldown <= 0) {
return 'JUMP';
}
// Priority 4: Stay still if very close to goal (within 100 units)
if (Math.abs(goalDistance) < 100 && Math.abs(goalVerticalDistance) < 50) {
return 'STAY_STILL';
}
// Priority 5: Stay still if on unstable ground or dangerous situation
if (!self.isGrounded && self.velocityY > 10) {
return 'STAY_STILL'; // Don't make sudden moves while falling fast
}
// Priority 6: Move towards goal only if it's reachable
if (goalReachable) {
if (goalDistance > 50) {
return 'MOVE_RIGHT';
} else if (goalDistance < -50) {
return 'MOVE_LEFT';
}
} else {
// Goal is not reachable due to distance restriction - move towards it to get closer
if (goalDistance > 0) {
return 'MOVE_RIGHT';
} else {
return 'MOVE_LEFT';
}
}
// Priority 7: Stay still if goal is close horizontally and reachable
if (goalReachable && Math.abs(goalDistance) < 100) {
return 'STAY_STILL';
}
return 'MOVE_RIGHT'; // Default movement
};
// Execute default behavior when no specific decision is made
self.executeDefaultBehavior = function () {
// Find target platform to move towards goal
if (self.pathfindingCooldown <= 0) {
self.target = self.findBestPlatform();
self.pathfindingCooldown = 10;
}
// Navigate towards target
if (self.target) {
self.navigateToTarget();
} else {
// Move towards goal as fallback
if (aiGoalAsset) {
var goalDistance = aiGoalAsset.x - self.x;
var goalVerticalDistance = aiGoalAsset.y - self.y;
// Check for obstacles ahead when moving towards goal
var obstacleAhead = self.checkForObstaclesAhead();
if (obstacleAhead && self.isGrounded && self.jumpCooldown <= 0) {
self.jump();
self.jumpCooldown = 20;
}
if (goalDistance > 50) {
self.moveRight();
} else if (goalDistance < -50) {
self.moveLeft();
}
} else {
// No goal yet, move right by default
// Check for obstacles when moving right
var obstacleAhead = self.checkForObstaclesAhead();
if (obstacleAhead && self.isGrounded && self.jumpCooldown <= 0) {
self.jump();
self.jumpCooldown = 20;
}
self.moveRight();
}
}
};
self.findBestPlatform = function () {
var bestPlatform = null;
var bestScore = -999999;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
// Skip platforms too far away or too close
if (Math.abs(platform.x - self.x) > 400 || Math.abs(platform.x - self.x) < 20) continue;
// Calculate score based on progress towards goal and reachability
var distanceToGoal = Math.abs(platform.x - aiGoalAsset.x);
var progressScore = (platform.x - self.x) * 2; // Favor forward movement
var goalProximityScore = -distanceToGoal * 0.5; // Favor platforms closer to goal
var heightPenalty = Math.abs(platform.y - self.y) * 0.1;
var score = progressScore + goalProximityScore - heightPenalty;
// Check if platform is reachable
if (self.isPlatformReachableByAI(platform)) {
score += 1000; // Bonus for reachable platforms
}
// Check for obstacles on platform
if (self.hasObstacleOnPlatform(platform)) {
score -= 500; // Penalty for obstacles
}
if (score > bestScore) {
bestScore = score;
bestPlatform = platform;
}
}
return bestPlatform;
};
self.isPlatformReachableByAI = function (platform) {
var horizontalDistance = Math.abs(platform.x - self.x);
var verticalDistance = platform.y - self.y;
// Simple reachability check
if (horizontalDistance > 350) return false; // Too far horizontally
if (verticalDistance > 400) return false; // Too high
if (verticalDistance < -600) return false; // Too far below
return true;
};
self.hasObstacleOnPlatform = function (platform) {
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
var distToPlatform = Math.abs(obstacle.x - platform.x);
var heightDiff = Math.abs(obstacle.y - platform.y);
if (distToPlatform < platform.width / 2 + 50 && heightDiff < 100) {
return true;
}
}
return false;
};
self.navigateToTarget = function () {
if (!self.target) return;
var horizontalDistance = self.target.x - self.x;
var verticalDistance = self.target.y - self.y;
// Check if we need to jump over obstacles
var needsJump = self.checkForObstaclesAhead();
// Jump if target is above us or if there's an obstacle (be more aggressive)
if ((verticalDistance < -50 || needsJump) && self.isGrounded && self.jumpCooldown <= 0) {
self.jump();
self.jumpCooldown = 20; // Reduced cooldown for more responsive jumping
}
// Also jump if we're close to the target horizontally but need to reach it vertically
if (Math.abs(horizontalDistance) < 100 && verticalDistance < -50 && self.isGrounded && self.jumpCooldown <= 0) {
self.jump();
self.jumpCooldown = 20;
}
// Move horizontally towards target
if (horizontalDistance > 30) {
self.moveRight();
} else if (horizontalDistance < -30) {
self.moveLeft();
}
// Check if we've reached the target platform
if (Math.abs(horizontalDistance) < 50 && Math.abs(verticalDistance) < 100) {
self.target = null; // Find new target
}
};
self.checkForObstaclesAhead = function () {
// Look ahead based on current movement speed and direction
var lookAheadDistance = Math.abs(self.velocityX) * 15 + 100; // Scale with speed
var direction = self.velocityX >= 0 ? 1 : -1; // Moving right or left
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
var obstacleDistance = (obstacle.x - self.x) * direction;
var heightDiff = Math.abs(obstacle.y - self.y);
// Check if obstacle is ahead in movement direction and at similar height
if (obstacleDistance > 0 && obstacleDistance < lookAheadDistance && heightDiff < 120) {
return true;
}
}
return false;
};
self.moveLeft = function () {
self.velocityX = -self.speed;
};
self.moveRight = function () {
self.velocityX = self.speed;
};
self.jump = function () {
if (self.isGrounded) {
self.velocityY = self.jumpPower;
self.isGrounded = false;
}
};
// AI takes damage and handles regeneration
self.takeDamage = function (amount) {
amount = amount || 20; // Default damage amount
self.health -= amount;
if (self.health < 0) self.health = 0;
self.damageCooldown = self.regenerationDelay;
self.isRegenerating = false;
// Flash AI red when taking damage
LK.effects.flashObject(self, 0xff0000, 500);
// If health reaches 0, reset AI position and health
if (self.health <= 0) {
self.health = self.maxHealth;
// Find platform closest to Final1 asset and respawn there
if (goalAsset && platforms.length > 0) {
var closestPlatform = null;
var shortestDistance = 999999;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var distance = Math.abs(platform.x - goalAsset.x);
if (distance < shortestDistance) {
shortestDistance = distance;
closestPlatform = platform;
}
}
// Position AI on the closest platform to Final1
if (closestPlatform) {
self.x = closestPlatform.x;
self.y = closestPlatform.y - 20; // Position slightly above platform
} else {
// Fallback to player position if no platform found
self.x = player.x;
self.y = player.y;
}
} else {
// Fallback to player position if no Final1 asset exists
self.x = player.x;
self.y = player.y;
}
self.velocityX = 0;
self.velocityY = 0;
LK.effects.flashObject(self, 0x00ff00, 1000); // Green flash for regeneration
}
};
self.update = function () {
// Apply gravity
if (!self.isGrounded) {
self.velocityY += self.gravity;
if (self.velocityY > self.maxFallSpeed) {
self.velocityY = self.maxFallSpeed;
}
}
// Check for obstacles before moving and jump if needed
if (self.isGrounded && self.jumpCooldown <= 0 && Math.abs(self.velocityX) > 2) {
var obstacleAhead = self.checkForObstaclesAhead();
if (obstacleAhead) {
self.jump();
self.jumpCooldown = 25;
}
}
// Apply horizontal movement with friction
self.x += self.velocityX;
self.velocityX *= 0.85;
// Apply vertical movement
self.y += self.velocityY;
// Check if AI needs to jump to avoid falling (gap detection)
if (self.isGrounded && self.jumpCooldown <= 0) {
// Look ahead to see if there's a platform to land on
var foundPlatformAhead = false;
var lookAheadX = self.x + (self.velocityX > 0 ? 150 : -150);
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var platformLeft = platform.x - platform.width / 2;
var platformRight = platform.x + platform.width / 2;
var heightDiff = Math.abs(platform.y - self.y);
// Check if there's a platform ahead at similar height
if (lookAheadX >= platformLeft && lookAheadX <= platformRight && heightDiff < 200) {
foundPlatformAhead = true;
break;
}
}
// If no platform found ahead and we're moving, jump to try to reach something
if (!foundPlatformAhead && Math.abs(self.velocityX) > 2) {
self.jump();
self.jumpCooldown = 40;
}
}
// Handle damage cooldown and regeneration
if (self.damageCooldown > 0) {
self.damageCooldown--;
} else if (self.health < self.maxHealth) {
// Start regenerating when cooldown is over
if (!self.isRegenerating) {
self.isRegenerating = true;
}
// Regenerate health (60 FPS, so divide by 60 for per-second rate)
self.health += self.regenerationRate / 60;
if (self.health > self.maxHealth) {
self.health = self.maxHealth;
self.isRegenerating = false;
}
}
// Make AI decisions
self.makeDecision();
};
return self;
});
var AI2 = Container.expand(function () {
var self = Container.call(this);
var aiGraphics = self.attachAsset('Caminando2', {
anchorX: 0.5,
anchorY: 1.0,
width: 60,
height: 60
});
self.target = null;
self.lastX = 0;
self.lastY = 0;
self.stuckCounter = 0;
self.jumpCooldown = 0;
self.scanDistance = 800;
self.pathfindingCooldown = 0;
self.velocityY = 0;
self.velocityX = 0;
self.isGrounded = false;
self.jumpPower = -18;
self.gravity = 1.2;
self.speed = 6; // Slower than player
self.maxFallSpeed = 20;
// AI health and regeneration system
self.health = 100;
self.maxHealth = 100;
self.regenerationRate = 2; // Health points per second
self.damageCooldown = 0;
self.isRegenerating = false;
self.regenerationDelay = 60; // Frames to wait before starting regeneration after damage
// AI decision making
self.makeDecision = function () {
if (!aiGoalAsset) return;
// Update cooldowns
if (self.jumpCooldown > 0) self.jumpCooldown--;
if (self.pathfindingCooldown > 0) self.pathfindingCooldown--;
// Check if stuck
var aiMovement = Math.abs(self.x - self.lastX) + Math.abs(self.y - self.lastY);
if (aiMovement < 2) {
self.stuckCounter++;
} else {
self.stuckCounter = 0;
}
self.lastX = self.x;
self.lastY = self.y;
// Decision state system - AI can choose between different actions
var decisionState = self.evaluateSituation();
switch (decisionState) {
case 'JUMP':
if (self.isGrounded && self.jumpCooldown <= 0) {
self.jump();
self.jumpCooldown = 20;
}
break;
case 'MOVE_LEFT':
self.moveLeft();
break;
case 'MOVE_RIGHT':
self.moveRight();
break;
case 'STAY_STILL':
// AI decides to stay still - do nothing
self.velocityX *= 0.5; // Slow down gradually
break;
default:
// Default fallback behavior
self.executeDefaultBehavior();
break;
}
};
// Evaluate current situation and decide what action to take
self.evaluateSituation = function () {
if (!aiGoalAsset) return 'MOVE_RIGHT'; // Default if no goal
var goalDistance = aiGoalAsset.x - self.x;
var goalVerticalDistance = aiGoalAsset.y - self.y;
var obstacleAhead = self.checkForObstaclesAhead();
var distanceToGoal = Math.abs(goalDistance);
var goalReachable = distanceToGoal <= 1000; // Check if goal is within reachable distance
// Priority 1: If stuck for too long, jump
if (self.stuckCounter > 30 && self.isGrounded && self.jumpCooldown <= 0) {
return 'JUMP';
}
// Priority 2: Jump over obstacles when moving
if (obstacleAhead && self.isGrounded && self.jumpCooldown <= 0 && Math.abs(self.velocityX) > 1) {
return 'JUMP';
}
// Priority 3: Jump if goal is significantly above and we're close horizontally
if (Math.abs(goalDistance) < 200 && goalVerticalDistance < -100 && self.isGrounded && self.jumpCooldown <= 0) {
return 'JUMP';
}
// Priority 4: Stay still if very close to goal (within 100 units)
if (Math.abs(goalDistance) < 100 && Math.abs(goalVerticalDistance) < 50) {
return 'STAY_STILL';
}
// Priority 5: Stay still if on unstable ground or dangerous situation
if (!self.isGrounded && self.velocityY > 10) {
return 'STAY_STILL'; // Don't make sudden moves while falling fast
}
// Priority 6: Move towards goal only if it's reachable
if (goalReachable) {
if (goalDistance > 50) {
return 'MOVE_RIGHT';
} else if (goalDistance < -50) {
return 'MOVE_LEFT';
}
} else {
// Goal is not reachable due to distance restriction - move towards it to get closer
if (goalDistance > 0) {
return 'MOVE_RIGHT';
} else {
return 'MOVE_LEFT';
}
}
// Priority 7: Stay still if goal is close horizontally and reachable
if (goalReachable && Math.abs(goalDistance) < 100) {
return 'STAY_STILL';
}
return 'MOVE_RIGHT'; // Default movement
};
// Execute default behavior when no specific decision is made
self.executeDefaultBehavior = function () {
// Find target platform to move towards goal
if (self.pathfindingCooldown <= 0) {
self.target = self.findBestPlatform();
self.pathfindingCooldown = 10;
}
// Navigate towards target
if (self.target) {
self.navigateToTarget();
} else {
// Move towards goal as fallback
if (aiGoalAsset) {
var goalDistance = aiGoalAsset.x - self.x;
var goalVerticalDistance = aiGoalAsset.y - self.y;
// Check for obstacles ahead when moving towards goal
var obstacleAhead = self.checkForObstaclesAhead();
if (obstacleAhead && self.isGrounded && self.jumpCooldown <= 0) {
self.jump();
self.jumpCooldown = 20;
}
if (goalDistance > 50) {
self.moveRight();
} else if (goalDistance < -50) {
self.moveLeft();
}
} else {
// No goal yet, move right by default
// Check for obstacles when moving right
var obstacleAhead = self.checkForObstaclesAhead();
if (obstacleAhead && self.isGrounded && self.jumpCooldown <= 0) {
self.jump();
self.jumpCooldown = 20;
}
self.moveRight();
}
}
};
self.findBestPlatform = function () {
var bestPlatform = null;
var bestScore = -999999;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
// Skip platforms too far away or too close
if (Math.abs(platform.x - self.x) > 400 || Math.abs(platform.x - self.x) < 20) continue;
// Calculate score based on progress towards goal and reachability
var distanceToGoal = Math.abs(platform.x - aiGoalAsset.x);
var progressScore = (platform.x - self.x) * 2; // Favor forward movement
var goalProximityScore = -distanceToGoal * 0.5; // Favor platforms closer to goal
var heightPenalty = Math.abs(platform.y - self.y) * 0.1;
var score = progressScore + goalProximityScore - heightPenalty;
// Check if platform is reachable
if (self.isPlatformReachableByAI(platform)) {
score += 1000; // Bonus for reachable platforms
}
// Check for obstacles on platform
if (self.hasObstacleOnPlatform(platform)) {
score -= 500; // Penalty for obstacles
}
if (score > bestScore) {
bestScore = score;
bestPlatform = platform;
}
}
return bestPlatform;
};
self.isPlatformReachableByAI = function (platform) {
var horizontalDistance = Math.abs(platform.x - self.x);
var verticalDistance = platform.y - self.y;
// Simple reachability check
if (horizontalDistance > 350) return false; // Too far horizontally
if (verticalDistance > 400) return false; // Too high
if (verticalDistance < -600) return false; // Too far below
return true;
};
self.hasObstacleOnPlatform = function (platform) {
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
var distToPlatform = Math.abs(obstacle.x - platform.x);
var heightDiff = Math.abs(obstacle.y - platform.y);
if (distToPlatform < platform.width / 2 + 50 && heightDiff < 100) {
return true;
}
}
return false;
};
self.navigateToTarget = function () {
if (!self.target) return;
var horizontalDistance = self.target.x - self.x;
var verticalDistance = self.target.y - self.y;
// Check if we need to jump over obstacles
var needsJump = self.checkForObstaclesAhead();
// Jump if target is above us or if there's an obstacle (be more aggressive)
if ((verticalDistance < -50 || needsJump) && self.isGrounded && self.jumpCooldown <= 0) {
self.jump();
self.jumpCooldown = 20; // Reduced cooldown for more responsive jumping
}
// Also jump if we're close to the target horizontally but need to reach it vertically
if (Math.abs(horizontalDistance) < 100 && verticalDistance < -50 && self.isGrounded && self.jumpCooldown <= 0) {
self.jump();
self.jumpCooldown = 20;
}
// Move horizontally towards target
if (horizontalDistance > 30) {
self.moveRight();
} else if (horizontalDistance < -30) {
self.moveLeft();
}
// Check if we've reached the target platform
if (Math.abs(horizontalDistance) < 50 && Math.abs(verticalDistance) < 100) {
self.target = null; // Find new target
}
};
self.checkForObstaclesAhead = function () {
// Look ahead based on current movement speed and direction
var lookAheadDistance = Math.abs(self.velocityX) * 15 + 100; // Scale with speed
var direction = self.velocityX >= 0 ? 1 : -1; // Moving right or left
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
var obstacleDistance = (obstacle.x - self.x) * direction;
var heightDiff = Math.abs(obstacle.y - self.y);
// Check if obstacle is ahead in movement direction and at similar height
if (obstacleDistance > 0 && obstacleDistance < lookAheadDistance && heightDiff < 120) {
return true;
}
}
return false;
};
self.moveLeft = function () {
self.velocityX = -self.speed;
};
self.moveRight = function () {
self.velocityX = self.speed;
};
self.jump = function () {
if (self.isGrounded) {
self.velocityY = self.jumpPower;
self.isGrounded = false;
}
};
// AI takes damage and handles regeneration
self.takeDamage = function (amount) {
amount = amount || 20; // Default damage amount
self.health -= amount;
if (self.health < 0) self.health = 0;
self.damageCooldown = self.regenerationDelay;
self.isRegenerating = false;
// Flash AI red when taking damage
LK.effects.flashObject(self, 0xff0000, 500);
// If health reaches 0, reset AI position and health
if (self.health <= 0) {
self.health = self.maxHealth;
// Find platform closest to Final1 asset and respawn there
if (goalAsset && platforms.length > 0) {
var closestPlatform = null;
var shortestDistance = 999999;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var distance = Math.abs(platform.x - goalAsset.x);
if (distance < shortestDistance) {
shortestDistance = distance;
closestPlatform = platform;
}
}
// Position AI on the closest platform to Final1
if (closestPlatform) {
self.x = closestPlatform.x;
self.y = closestPlatform.y - 20; // Position slightly above platform
} else {
// Fallback to player position if no platform found
self.x = player.x;
self.y = player.y;
}
} else {
// Fallback to player position if no Final1 asset exists
self.x = player.x;
self.y = player.y;
}
self.velocityX = 0;
self.velocityY = 0;
LK.effects.flashObject(self, 0x00ff00, 1000); // Green flash for regeneration
}
};
self.update = function () {
// Apply gravity
if (!self.isGrounded) {
self.velocityY += self.gravity;
if (self.velocityY > self.maxFallSpeed) {
self.velocityY = self.maxFallSpeed;
}
}
// Check for obstacles before moving and jump if needed
if (self.isGrounded && self.jumpCooldown <= 0 && Math.abs(self.velocityX) > 2) {
var obstacleAhead = self.checkForObstaclesAhead();
if (obstacleAhead) {
self.jump();
self.jumpCooldown = 25;
}
}
// Apply horizontal movement with friction
self.x += self.velocityX;
self.velocityX *= 0.85;
// Apply vertical movement
self.y += self.velocityY;
// Check if AI needs to jump to avoid falling (gap detection)
if (self.isGrounded && self.jumpCooldown <= 0) {
// Look ahead to see if there's a platform to land on
var foundPlatformAhead = false;
var lookAheadX = self.x + (self.velocityX > 0 ? 150 : -150);
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var platformLeft = platform.x - platform.width / 2;
var platformRight = platform.x + platform.width / 2;
var heightDiff = Math.abs(platform.y - self.y);
// Check if there's a platform ahead at similar height
if (lookAheadX >= platformLeft && lookAheadX <= platformRight && heightDiff < 200) {
foundPlatformAhead = true;
break;
}
}
// If no platform found ahead and we're moving, jump to try to reach something
if (!foundPlatformAhead && Math.abs(self.velocityX) > 2) {
self.jump();
self.jumpCooldown = 40;
}
}
// Handle damage cooldown and regeneration
if (self.damageCooldown > 0) {
self.damageCooldown--;
} else if (self.health < self.maxHealth) {
// Start regenerating when cooldown is over
if (!self.isRegenerating) {
self.isRegenerating = true;
}
// Regenerate health (60 FPS, so divide by 60 for per-second rate)
self.health += self.regenerationRate / 60;
if (self.health > self.maxHealth) {
self.health = self.maxHealth;
self.isRegenerating = false;
}
}
// Make AI decisions
self.makeDecision();
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0
});
self.width = 30;
self.height = 60;
return self;
});
var Platform = Container.expand(function (width) {
var self = Container.call(this);
width = width || 300;
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: width / 300
});
self.width = width;
self.height = 40;
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 1.0
});
self.velocityY = 0;
self.velocityX = 0;
self.isGrounded = false;
self.jumpPower = -25;
self.gravity = 1.2;
self.speed = 8;
self.maxFallSpeed = 20;
self.isMoving = false;
self.idleAnimationTime = 0;
self.movementAnimationTime = 0;
self.moveLeft = function () {
self.velocityX = -self.speed;
};
self.moveRight = function () {
self.velocityX = self.speed;
};
self.jump = function () {
if (self.isGrounded) {
self.velocityY = self.jumpPower;
self.isGrounded = false;
LK.getSound('jump').play();
}
};
self.update = function () {
// Apply gravity
if (!self.isGrounded) {
self.velocityY += self.gravity;
if (self.velocityY > self.maxFallSpeed) {
self.velocityY = self.maxFallSpeed;
}
}
// Apply horizontal movement with friction
self.x += self.velocityX;
self.velocityX *= 0.85;
// Apply vertical movement
self.y += self.velocityY;
// Check if player is moving horizontally
self.isMoving = Math.abs(self.velocityX) > 0.5;
// Update animations
if (self.isMoving) {
// Movement animation - slight bouncing effect
self.movementAnimationTime += 0.3;
var bounceOffset = Math.sin(self.movementAnimationTime) * 3;
playerGraphics.y = bounceOffset;
playerGraphics.scaleX = 1 + Math.sin(self.movementAnimationTime * 2) * 0.05;
playerGraphics.scaleY = 1 + Math.cos(self.movementAnimationTime * 2) * 0.05;
// Reset idle animation
self.idleAnimationTime = 0;
} else {
// Idle animation - gentle floating effect
self.idleAnimationTime += 0.1;
var floatOffset = Math.sin(self.idleAnimationTime) * 2;
playerGraphics.y = floatOffset;
playerGraphics.scaleX = 1 + Math.sin(self.idleAnimationTime * 0.5) * 0.02;
playerGraphics.scaleY = 1 + Math.cos(self.idleAnimationTime * 0.5) * 0.02;
// Reset movement animation
self.movementAnimationTime = 0;
}
// No horizontal boundaries - allow infinite movement for side-scrolling
// Check if fallen off screen
if (self.y > 2800) {
LK.showGameOver();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Set background to Cielo1 asset
var backgroundAsset = LK.getAsset('Cielo1', {
width: 2048,
height: 2732,
anchorX: 0,
anchorY: 0
});
backgroundAsset.x = 0;
backgroundAsset.y = 0;
game.addChildAt(backgroundAsset, 0); // Add as first child so it's behind everything
var gameState = 'start'; // 'start', 'playing', 'paused'
var startButton = null;
var player;
var platforms = [];
var obstacles = [];
var cameraOffset = 0;
var distanceScore = 0;
var lastPlatformX = 0;
var leftButtonPressed = false;
var rightButtonPressed = false;
var jumpButtonPressed = false;
var gameAttempts = 0;
var levelSeed = 0;
var goalReached = false;
var goalAsset = null;
var aiPlayer = null;
var aiCameraOffset = 0;
var aiDistanceScore = 0;
var aiGoalAsset = null;
var aiGoalReached = false;
var aiLastPlatformX = 0;
var aiPlayer2 = null;
var playerLives = 5;
var maxLives = 5;
var hearts = [];
var playerInvulnerable = false;
var invulnerabilityDuration = 120; // 2 seconds at 60 FPS
var invulnerabilityTimer = 0;
// Create score display
var scoreText = new Text2('Distance: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
// Create control instruction text
var instructionText = new Text2('Use Buttons to Move and Jump', {
size: 40,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 1);
LK.gui.bottom.addChild(instructionText);
// Create start screen elements
var titleText = new Text2('Platform Adventure', {
size: 120,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(titleText);
var startButtonText = new Text2('START GAME', {
size: 80,
fill: 0xFFFFFF
});
startButtonText.anchor.set(0.5, 0.5);
// Create start button using Star1 asset as background
startButton = LK.getAsset('Star1', {
width: 300,
height: 120,
anchorX: 0.5,
anchorY: 0.5
});
startButton.tint = 0x32cd32;
startButton.alpha = 0.8;
LK.gui.center.addChild(startButton);
startButton.addChild(startButtonText);
startButton.y = 150;
// Hide game UI elements initially
scoreText.visible = false;
instructionText.visible = false;
// Create heart life display
function createHeartDisplay() {
// Clear existing hearts
for (var i = 0; i < hearts.length; i++) {
hearts[i].destroy();
}
hearts = [];
// Create new hearts based on current lives
for (var i = 0; i < maxLives; i++) {
var heart = LK.getAsset('corason1', {
width: 60,
height: 60,
anchorX: 0.5,
anchorY: 0.5
});
heart.x = 150 + i * 70; // Position hearts horizontally
heart.y = 80; // Position at top
heart.alpha = i < playerLives ? 1.0 : 0.3; // Full opacity for active lives, faded for lost lives
hearts.push(heart);
LK.gui.topLeft.addChild(heart);
}
}
// Initialize heart display
createHeartDisplay();
// Function to initialize the game
function initializeGame() {
// Initialize player
player = new Player();
player.x = 300;
player.y = 2000;
game.addChild(player);
// Initialize AI
aiPlayer = new AI();
aiPlayer.x = 200;
aiPlayer.y = 2000;
game.addChild(aiPlayer);
// Initialize AI2
aiPlayer2 = new AI2();
aiPlayer2.x = 150;
aiPlayer2.y = 2000;
game.addChild(aiPlayer2);
}
// Start button event handlers
startButton.down = function () {
startButton.alpha = 1.0;
startButton.scaleX = 0.95;
startButton.scaleY = 0.95;
};
startButton.up = function () {
startButton.alpha = 0.8;
startButton.scaleX = 1.0;
startButton.scaleY = 1.0;
// Start the game
gameState = 'playing';
// Hide start screen elements
titleText.visible = false;
startButton.visible = false;
// Show game UI elements
scoreText.visible = true;
instructionText.visible = true;
// Initialize game objects
initializeGame();
};
// Initialize AI-specific variables
aiCameraOffset = 0;
aiDistanceScore = 0;
aiLastPlatformX = 2200; // Same as initial lastPlatformX
// Create initial platforms
function createPlatform(x, y, width) {
var platform = new Platform(width);
platform.x = x;
platform.y = y;
platforms.push(platform);
game.addChild(platform);
return platform;
}
function createObstacle(x, y) {
var obstacle = new Obstacle();
obstacle.x = x;
obstacle.y = y;
obstacles.push(obstacle);
game.addChild(obstacle);
return obstacle;
}
// Generate initial level
createPlatform(200, 2100, 400); // Starting platform
createPlatform(600, 2000, 300);
createPlatform(1000, 1900, 250);
createPlatform(1400, 1800, 300);
createObstacle(1400, 1800);
createPlatform(1800, 1700, 200);
createPlatform(2200, 1600, 350);
lastPlatformX = 2200;
function generateLevel() {
// Remove platforms that are too far behind
for (var i = platforms.length - 1; i >= 0; i--) {
var platform = platforms[i];
if (platform.x < cameraOffset - 500) {
platform.destroy();
platforms.splice(i, 1);
}
}
// Remove obstacles that are too far behind
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
if (obstacle.x < cameraOffset - 500) {
obstacle.destroy();
obstacles.splice(i, 1);
}
}
// Generate new platforms ahead for player
while (lastPlatformX < cameraOffset + 3000) {
var lastPlatform = findLastPlatform();
var newPlatform = generateVerifiedPlatform(lastPlatform);
lastPlatformX = newPlatform.x;
createPlatform(newPlatform.x, newPlatform.y, newPlatform.width);
// Add obstacles with attempt-based variation
var obstacleChance = 0.2 + gameAttempts * 0.05; // Increase difficulty with attempts
if (obstacleChance > 0.5) obstacleChance = 0.5; // Cap at 50%
if (Math.random() < obstacleChance) {
createObstacle(newPlatform.x, newPlatform.y);
}
}
// Generate new platforms ahead for AI
while (aiLastPlatformX < aiCameraOffset + 3000) {
var aiLastPlatform = findLastPlatform();
var aiNewPlatform = generateVerifiedPlatform(aiLastPlatform);
aiLastPlatformX = aiNewPlatform.x;
createPlatform(aiNewPlatform.x, aiNewPlatform.y, aiNewPlatform.width);
// Add obstacles for AI path
if (Math.random() < 0.3) {
createObstacle(aiNewPlatform.x, aiNewPlatform.y);
}
}
}
function findLastPlatform() {
var lastPlatform = null;
var maxX = -999999;
for (var i = 0; i < platforms.length; i++) {
if (platforms[i].x > maxX) {
maxX = platforms[i].x;
lastPlatform = platforms[i];
}
}
return lastPlatform;
}
function generateVerifiedPlatform(lastPlatform) {
var maxJumpDistance = 320; // Maximum horizontal jump distance
var maxJumpHeight = 350; // Maximum jump height (going up)
var maxFallHeight = 600; // Maximum fall height (going down)
// Attempt-based level variation
var difficultyMultiplier = 1 + gameAttempts * 0.1;
if (difficultyMultiplier > 2) difficultyMultiplier = 2; // Cap difficulty
var attemptSeed = gameAttempts * 12345 % 100000;
var pseudoRandom = (attemptSeed + lastPlatformX * 7) % 1000 / 1000;
var gapDistance = 150 + pseudoRandom * 200 * difficultyMultiplier;
var platformWidth = 150 + pseudoRandom * 150;
var heightVariation = -150 + pseudoRandom * 300;
// Ensure gap is not too large
if (gapDistance > maxJumpDistance) {
gapDistance = maxJumpDistance - 20;
}
var newX = lastPlatform.x + gapDistance;
var newY = lastPlatform.y + heightVariation;
// Verify vertical reachability
var heightDifference = newY - lastPlatform.y;
if (heightDifference > maxFallHeight) {
newY = lastPlatform.y + maxFallHeight;
} else if (heightDifference < -maxJumpHeight) {
newY = lastPlatform.y - maxJumpHeight;
}
// Keep platforms within screen bounds - terrain cannot go above middle of screen
if (newY > 2200) newY = 2200;
if (newY < 1366) newY = 1366; // Middle of screen (2732/2 = 1366) - platforms cannot generate above this
// Verify horizontal reachability with physics simulation
if (!isPlatformReachable(lastPlatform, {
x: newX,
y: newY,
width: platformWidth
})) {
// Adjust platform to make it reachable
gapDistance = maxJumpDistance - 50;
newX = lastPlatform.x + gapDistance;
// Also adjust height to be more forgiving
if (heightDifference > 0) {
newY = lastPlatform.y + Math.min(heightDifference, 200);
} else {
newY = lastPlatform.y + Math.max(heightDifference, -250);
}
}
return {
x: newX,
y: newY,
width: platformWidth
};
}
function isPlatformReachable(fromPlatform, toPlatform) {
// Simulate a jump from the edge of fromPlatform to toPlatform
var startX = fromPlatform.x + fromPlatform.width / 2;
var startY = fromPlatform.y;
var targetX = toPlatform.x;
var targetY = toPlatform.y;
var targetLeft = targetX - toPlatform.width / 2;
var targetRight = targetX + toPlatform.width / 2;
// Simulate jump physics
var jumpPower = -25;
var gravity = 1.2;
var speed = 8;
var maxSimulationTime = 100; // Prevent infinite loops
var simX = startX;
var simY = startY;
var velocityY = jumpPower;
var velocityX = speed;
for (var t = 0; t < maxSimulationTime; t++) {
simX += velocityX;
simY += velocityY;
velocityY += gravity;
// Check if we've reached the target platform level
if (simY >= targetY && simX >= targetLeft && simX <= targetRight) {
return true;
}
// If we've fallen too far below the target, we can't reach it
if (simY > targetY + 100) {
break;
}
}
return false;
}
function checkCollisions() {
player.isGrounded = false;
// Check platform collisions
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var playerBounds = {
left: player.x - 30,
right: player.x + 30,
top: player.y - 60,
bottom: player.y
};
var platformBounds = {
left: platform.x - platform.width / 2,
right: platform.x + platform.width / 2,
top: platform.y - 20,
bottom: platform.y + 20
};
// Check if player overlaps with platform
if (playerBounds.right > platformBounds.left && playerBounds.left < platformBounds.right && playerBounds.bottom > platformBounds.top && playerBounds.top < platformBounds.bottom) {
// Landing on top of platform
if (player.velocityY >= 0 && playerBounds.bottom - platformBounds.top < 20) {
player.y = platformBounds.top;
player.velocityY = 0;
player.isGrounded = true;
}
}
}
// Check obstacle collisions - only if player is not invulnerable
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
if (player.intersects(obstacle) && !playerInvulnerable) {
// Player loses one life
playerLives--;
// Start invulnerability period
playerInvulnerable = true;
invulnerabilityTimer = invulnerabilityDuration;
// Flash player red when taking damage
LK.effects.flashObject(player, 0xff0000, 500);
LK.effects.flashScreen(0xff0000, 500);
// Create blinking effect during invulnerability using tween
tween(player, {
alpha: 0.3
}, {
duration: 200,
onFinish: function onFinish() {
tween(player, {
alpha: 1.0
}, {
duration: 200
});
}
});
// Update heart display
createHeartDisplay();
// Check if player is out of lives
if (playerLives <= 0) {
LK.showGameOver();
return;
} else {
// Push player away from obstacle to prevent multiple hits
if (obstacle.x > player.x) {
player.x -= 50; // Push left
} else {
player.x += 50; // Push right
}
player.velocityX = 0; // Stop horizontal movement
}
}
}
// Final1 asset is unreachable - no collision detection needed
}
function updateCamera() {
// Camera follows player with some offset
var targetCameraX = player.x - 400;
cameraOffset += (targetCameraX - cameraOffset) * 0.1;
// Move all game objects relative to camera
game.x = -cameraOffset;
// Make background follow player movement in opposite direction for proper parallax effect
if (backgroundAsset) {
backgroundAsset.x = cameraOffset; // Match exact player movement speed
}
// Update distance score
distanceScore = Math.floor(cameraOffset / 10);
scoreText.setText('Distance: ' + distanceScore);
LK.setScore(distanceScore);
// Create Final1 asset that moves dynamically
if (!goalAsset) {
goalAsset = LK.getAsset('Final1', {
width: 100,
height: 100,
anchorX: 0.5,
anchorY: 1.0
});
goalAsset.moveSpeed = 8; // Much faster movement speed for Final1
goalAsset.moveDirection = 1; // 1 for right, -1 for left
goalAsset.baseY = 800; // Base Y position
goalAsset.floatTime = 0; // For floating animation
game.addChild(goalAsset);
}
// Move Final1 asset with floating motion
goalAsset.moveSpeed = goalAsset.moveSpeed || 8;
goalAsset.moveDirection = goalAsset.moveDirection || 1;
goalAsset.baseY = goalAsset.baseY || 800;
goalAsset.floatTime = goalAsset.floatTime || 0;
// Move horizontally only to the right, but stop when goal is reached
if (!goalReached) {
goalAsset.x += goalAsset.moveSpeed;
// Stop at right boundary but don't reverse direction
var screenRight = cameraOffset + 1800;
if (goalAsset.x >= screenRight) {
goalAsset.x = screenRight; // Keep at right boundary
}
}
// Floating vertical motion - only if animation is not deactivated
if (!goalAsset.animationDeactivated) {
goalAsset.floatTime += 0.02;
goalAsset.y = goalAsset.baseY + Math.sin(goalAsset.floatTime) * 50;
} else {
// Keep Final1 fixed at base Y position when animation is deactivated
goalAsset.y = goalAsset.baseY;
}
// Distance-based reachability system
var playerDistance = Math.abs(goalAsset.x - player.x);
var aiDistance = Math.abs(goalAsset.x - (aiPlayer ? aiPlayer.x : 9999));
// Check if Final1 has reached distance 15000 from start
var finalAssetDistance = goalAsset.x - 300; // Subtract initial player position
if (finalAssetDistance >= 15000 && !goalReached) {
goalReached = true;
// Find nearest platform and position Final1 on it
var nearestPlatform = null;
var shortestDistance = 999999;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var distance = Math.abs(platform.x - goalAsset.x);
if (distance < shortestDistance) {
shortestDistance = distance;
nearestPlatform = platform;
}
}
// Position Final1 on the nearest platform
if (nearestPlatform) {
goalAsset.x = nearestPlatform.x;
goalAsset.y = nearestPlatform.y - 20; // Position slightly above platform
goalAsset.baseY = nearestPlatform.y - 20; // Update base Y for floating
// Deactivate floating animation by setting a flag
goalAsset.animationDeactivated = true;
}
LK.effects.flashScreen(0xFFD700, 2000); // Flash gold when Final1 becomes reachable
}
// Check if player touches Final1 asset when it's reachable
if (goalReached && playerDistance < 100) {
LK.effects.flashScreen(0x00FF00, 1500); // Green flash for player success
LK.showYouWin();
}
}
function updateAICamera() {
// AI camera follows AI player
var aiTargetCameraX = aiPlayer.x - 400;
aiCameraOffset += (aiTargetCameraX - aiCameraOffset) * 0.1;
// Update AI distance score
aiDistanceScore = Math.floor(aiCameraOffset / 10);
// AI uses the same moving Final1 asset as the player's goal
if (!aiGoalAsset && goalAsset) {
aiGoalAsset = goalAsset; // Share the same moving Final1 asset
}
}
// Create control buttons
var leftButton = LK.getAsset('Izquierda1', {
width: 150,
height: 100,
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
leftButton.alpha = 0.7;
var rightButton = LK.getAsset('Derecha2', {
width: 150,
height: 100,
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
rightButton.alpha = 0.7;
var jumpButton = LK.getAsset('Salto1', {
width: 120,
height: 120,
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.2,
scaleY: 2.2
});
jumpButton.tint = 0x32cd32;
jumpButton.alpha = 0.8;
// Position buttons in GUI - left and right buttons together in bottom left
LK.gui.bottomLeft.addChild(leftButton);
leftButton.x = 80;
leftButton.y = -100;
LK.gui.bottomLeft.addChild(rightButton);
rightButton.x = 300;
rightButton.y = -100;
LK.gui.bottomRight.addChild(jumpButton);
jumpButton.x = -130;
jumpButton.y = -100;
// Button event handlers
leftButton.down = function () {
leftButton.alpha = 1.0;
leftButtonPressed = true;
};
leftButton.up = function () {
leftButton.alpha = 0.7;
leftButtonPressed = false;
};
rightButton.down = function () {
rightButton.alpha = 1.0;
rightButtonPressed = true;
};
rightButton.up = function () {
rightButton.alpha = 0.7;
rightButtonPressed = false;
};
jumpButton.down = function () {
jumpButton.alpha = 1.0;
jumpButton.scaleX = 1.3;
jumpButton.scaleY = 1.3;
jumpButtonPressed = true;
if (player && gameState === 'playing') {
player.jump();
}
};
jumpButton.up = function () {
jumpButton.alpha = 0.8;
jumpButton.scaleX = 1.5;
jumpButton.scaleY = 1.5;
jumpButtonPressed = false;
};
// Track when game starts/resets
var originalShowGameOver = LK.showGameOver;
LK.showGameOver = function () {
gameAttempts++;
levelSeed = gameAttempts * 54321; // Change seed each attempt
// Reset player lives when game restarts
playerLives = maxLives;
// Reset invulnerability state
playerInvulnerable = false;
invulnerabilityTimer = 0;
createHeartDisplay();
// Reset game state to start screen
gameState = 'start';
// Show start screen elements
titleText.visible = true;
startButton.visible = true;
// Hide game UI elements
scoreText.visible = false;
instructionText.visible = false;
// Clear game objects
if (player) {
player.destroy();
player = null;
}
if (aiPlayer) {
aiPlayer.destroy();
aiPlayer = null;
}
if (aiPlayer2) {
aiPlayer2.destroy();
aiPlayer2 = null;
}
if (goalAsset) {
goalAsset.destroy();
goalAsset = null;
}
// Clear platforms and obstacles
for (var i = 0; i < platforms.length; i++) {
platforms[i].destroy();
}
platforms = [];
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].destroy();
}
obstacles = [];
// Reset game variables
cameraOffset = 0;
distanceScore = 0;
lastPlatformX = 0;
goalReached = false;
aiCameraOffset = 0;
aiDistanceScore = 0;
aiGoalAsset = null;
aiGoalReached = false;
aiLastPlatformX = 0;
originalShowGameOver();
};
game.update = function () {
// Only update game when in playing state
if (gameState !== 'playing') {
return;
}
// Handle invulnerability timer
if (playerInvulnerable) {
invulnerabilityTimer--;
if (invulnerabilityTimer <= 0) {
playerInvulnerable = false;
// Ensure player is fully visible when invulnerability ends
tween.stop(player, {
alpha: true
});
player.alpha = 1.0;
}
}
// Handle continuous movement based on button states
if (leftButtonPressed) {
player.moveLeft();
}
if (rightButtonPressed) {
player.moveRight();
}
// Handle continuous jump (allows jump when held down and landing)
if (jumpButtonPressed) {
player.jump();
}
// Update AI if it exists
if (aiPlayer) {
aiPlayer.update();
// Check AI collisions with platforms
aiPlayer.isGrounded = false;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var aiBounds = {
left: aiPlayer.x - 50,
right: aiPlayer.x + 50,
top: aiPlayer.y - 100,
bottom: aiPlayer.y
};
var platformBounds = {
left: platform.x - platform.width / 2,
right: platform.x + platform.width / 2,
top: platform.y - 20,
bottom: platform.y + 20
};
// Check if AI overlaps with platform
if (aiBounds.right > platformBounds.left && aiBounds.left < platformBounds.right && aiBounds.bottom > platformBounds.top && aiBounds.top < platformBounds.bottom) {
// Landing on top of platform
if (aiPlayer.velocityY >= 0 && aiBounds.bottom - platformBounds.top < 40) {
aiPlayer.y = platformBounds.top;
aiPlayer.velocityY = 0;
aiPlayer.isGrounded = true;
}
}
}
// Check AI obstacle collisions
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
if (aiPlayer.intersects(obstacle)) {
// AI takes damage from obstacle and handles it independently
aiPlayer.takeDamage(25); // AI takes damage instead of affecting player
}
}
}
// Update AI2 if it exists
if (aiPlayer2) {
aiPlayer2.update();
// Check AI2 collisions with platforms
aiPlayer2.isGrounded = false;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var ai2Bounds = {
left: aiPlayer2.x - 50,
right: aiPlayer2.x + 50,
top: aiPlayer2.y - 100,
bottom: aiPlayer2.y
};
var platformBounds = {
left: platform.x - platform.width / 2,
right: platform.x + platform.width / 2,
top: platform.y - 20,
bottom: platform.y + 20
};
// Check if AI2 overlaps with platform
if (ai2Bounds.right > platformBounds.left && ai2Bounds.left < platformBounds.right && ai2Bounds.bottom > platformBounds.top && ai2Bounds.top < platformBounds.bottom) {
// Landing on top of platform
if (aiPlayer2.velocityY >= 0 && ai2Bounds.bottom - platformBounds.top < 40) {
aiPlayer2.y = platformBounds.top;
aiPlayer2.velocityY = 0;
aiPlayer2.isGrounded = true;
}
}
}
// Check AI2 obstacle collisions
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
if (aiPlayer2.intersects(obstacle)) {
// AI2 takes damage from obstacle and handles it independently
aiPlayer2.takeDamage(25); // AI2 takes damage instead of affecting player
}
}
// Check if player is falling into void (no platform below for a significant distance)
if (player.y > 2400 && !player.isGrounded) {
// Start checking earlier than complete fall off
var foundPlatformBelow = false;
// Look for any platform below the player within a reasonable distance
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var horizontalDistance = Math.abs(platform.x - player.x);
// Check if there's a platform below within reasonable horizontal distance
if (platform.y > player.y && platform.y < player.y + 400 && horizontalDistance < 200) {
foundPlatformBelow = true;
break;
}
}
// If no platform found below and player is falling fast, respawn with 2 life loss
if (!foundPlatformBelow || player.velocityY > 15) {
// Player loses 2 lives when falling into void
playerLives -= 2;
if (playerLives < 0) playerLives = 0;
// Flash effects for void fall
LK.effects.flashObject(player, 0xff0000, 800);
LK.effects.flashScreen(0xff0000, 800);
// Update heart display
createHeartDisplay();
// Check if player is out of lives
if (playerLives <= 0) {
LK.showGameOver();
return;
}
// Find platform closest to Final1 asset and respawn there
if (goalAsset && platforms.length > 0) {
var closestPlatform = null;
var shortestDistance = 999999;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var distance = Math.abs(platform.x - goalAsset.x);
if (distance < shortestDistance) {
shortestDistance = distance;
closestPlatform = platform;
}
}
// Position player on the closest platform to Final1
if (closestPlatform) {
player.x = closestPlatform.x;
player.y = closestPlatform.y - 20; // Position slightly above platform
} else {
// Fallback to starting position if no platform found
player.x = 300;
player.y = 2000;
}
} else {
// Fallback to starting position if no Final1 asset exists
player.x = 300;
player.y = 2000;
}
player.velocityX = 0;
player.velocityY = 0;
player.isGrounded = false;
// Start invulnerability period after respawn
playerInvulnerable = true;
invulnerabilityTimer = invulnerabilityDuration;
// Create blinking effect during invulnerability using tween
tween(player, {
alpha: 0.3
}, {
duration: 200,
onFinish: function onFinish() {
tween(player, {
alpha: 1.0
}, {
duration: 200
});
}
});
}
}
// Check if AI is falling into void (no platform below for a significant distance)
if (aiPlayer.y > 2400 && !aiPlayer.isGrounded) {
// Start checking earlier than complete fall off
var foundPlatformBelow = false;
// Look for any platform below the AI within a reasonable distance
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var platformLeft = platform.x - platform.width / 2;
var platformRight = platform.x + platform.width / 2;
var horizontalDistance = Math.abs(platform.x - aiPlayer.x);
// Check if there's a platform below within reasonable horizontal distance
if (platform.y > aiPlayer.y && platform.y < aiPlayer.y + 400 && horizontalDistance < 200) {
foundPlatformBelow = true;
break;
}
}
// If no platform found below and AI is falling fast, respawn
if (!foundPlatformBelow || aiPlayer.velocityY > 15) {
// Find platform closest to Final1 asset and respawn there
if (goalAsset && platforms.length > 0) {
var closestPlatform = null;
var shortestDistance = 999999;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var distance = Math.abs(platform.x - goalAsset.x);
if (distance < shortestDistance) {
shortestDistance = distance;
closestPlatform = platform;
}
}
// Position AI on the closest platform to Final1
if (closestPlatform) {
aiPlayer.x = closestPlatform.x;
aiPlayer.y = closestPlatform.y - 20; // Position slightly above platform
} else {
// Fallback to player position if no platform found
aiPlayer.x = player.x;
aiPlayer.y = player.y;
}
} else {
// Fallback to player position if no Final1 asset exists
aiPlayer.x = player.x;
aiPlayer.y = player.y;
}
aiPlayer.velocityX = 0;
aiPlayer.velocityY = 0;
aiPlayer.isGrounded = false;
LK.effects.flashObject(aiPlayer, 0x00ff00, 1000); // Green flash for regeneration
}
}
// Check if AI2 is falling into void (no platform below for a significant distance)
if (aiPlayer2.y > 2400 && !aiPlayer2.isGrounded) {
// Start checking earlier than complete fall off
var foundPlatformBelow = false;
// Look for any platform below the AI2 within a reasonable distance
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var platformLeft = platform.x - platform.width / 2;
var platformRight = platform.x + platform.width / 2;
var horizontalDistance = Math.abs(platform.x - aiPlayer2.x);
// Check if there's a platform below within reasonable horizontal distance
if (platform.y > aiPlayer2.y && platform.y < aiPlayer2.y + 400 && horizontalDistance < 200) {
foundPlatformBelow = true;
break;
}
}
// If no platform found below and AI2 is falling fast, respawn
if (!foundPlatformBelow || aiPlayer2.velocityY > 15) {
// Find platform closest to Final1 asset and respawn there
if (goalAsset && platforms.length > 0) {
var closestPlatform = null;
var shortestDistance = 999999;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var distance = Math.abs(platform.x - goalAsset.x);
if (distance < shortestDistance) {
shortestDistance = distance;
closestPlatform = platform;
}
}
// Position AI2 on the closest platform to Final1
if (closestPlatform) {
aiPlayer2.x = closestPlatform.x;
aiPlayer2.y = closestPlatform.y - 20; // Position slightly above platform
} else {
// Fallback to player position if no platform found
aiPlayer2.x = player.x;
aiPlayer2.y = player.y;
}
} else {
// Fallback to player position if no Final1 asset exists
aiPlayer2.x = player.x;
aiPlayer2.y = player.y;
}
aiPlayer2.velocityX = 0;
aiPlayer2.velocityY = 0;
aiPlayer2.isGrounded = false;
LK.effects.flashObject(aiPlayer2, 0x00ff00, 1000); // Green flash for regeneration
}
}
// Prevent AI from falling off screen (backup safety check)
if (aiPlayer.y > 2800) {
aiPlayer.y = 2000;
aiPlayer.x = 200; // Reset to independent starting position
aiPlayer.velocityY = 0;
aiPlayer.velocityX = 0;
}
// Prevent AI2 from falling off screen (backup safety check)
if (aiPlayer2.y > 2800) {
aiPlayer2.y = 2000;
aiPlayer2.x = 150; // Reset to independent starting position
aiPlayer2.velocityY = 0;
aiPlayer2.velocityX = 0;
}
// AI goal stays fixed at right center of screen - no movement needed
}
checkCollisions();
updateCamera();
updateAICamera();
generateLevel();
}; ===================================================================
--- original.js
+++ change.js
@@ -1224,9 +1224,9 @@
// Move all game objects relative to camera
game.x = -cameraOffset;
// Make background follow player movement in opposite direction for proper parallax effect
if (backgroundAsset) {
- backgroundAsset.x = cameraOffset * 0.8; // Increase speed to keep up with player movement
+ backgroundAsset.x = cameraOffset; // Match exact player movement speed
}
// Update distance score
distanceScore = Math.floor(cameraOffset / 10);
scoreText.setText('Distance: ' + distanceScore);
Puedes Aser una persona palito de color negra que este pixelada. In-Game asset
Plataforma flotante con pasto ensima y tierra debajo pixelada. In-Game asset. 2d. High contrast. No shadows
Cuadro gris con bordes negros que dentro tenga una flecha apuntando a la derecha pixelada. In-Game asset. No shadows
Personaje que sea un alpinista pixelado con una gran mochila que este en movimiento caminando In-Game asset. 2d. High contrast. No shadows
Bandera de meta en un gran poste Pixelado. In-Game asset. 2d. High contrast. No shadows
As un corazón pixelado. In-Game asset. High contrast. No shadows
Rectángulo gris con bordes negros que en el sentro tenga la palabra Star pixelada. In-Game asset. High contrast. No shadows
Cielo de fondo pixelado con un sol y nubes. No shadows
As un alpinista caminando que sea una persona real. In-Game asset. 2d. High contrast. No shadows