User prompt
Intercambia el botón de estar por el ased star1
User prompt
As que las ias ased caminando1 y camindo2 sean más lentos que el jugador
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'jump')' in or related to this line: 'player.jump();' Line Number: 1426
User prompt
As un botón que inicie el juego
User prompt
As que las plataformas no puedan generarse por ensima de la mitad de la pantalla
User prompt
As un menú principal donde tocas un botón para que inicie el juego
User prompt
As que la IA ased caminando1 sea un poco más lenta que la IA ased caminando2 y que tengan el mismo tamaño del jugador
User prompt
Implementa otra IA que aga lo mismo que la IA ased caminando1 pero que use el ased caminando2
User prompt
As que el ased Final1 siga asta la distancia 15000 y aga lo que tiene que Aser
User prompt
As que cuando el jugador caiga al vacío pierda 2 vidas y se regenere a la plataforma más cercana del ases Final1
User prompt
As que cuando el jugador resiba daño tenga un ligero delay antes de revivir denuebo daño ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
As que la IA ased caminando1 se regenere en la plataforma más cercana a al ases Final1
User prompt
Es que el ased Final1 siga asta la distancia 10000 y aga lo que tiene que Aser
User prompt
As que el ased Final1 Balla a la distancia 1000 y que en la distancia 1000 busque la plataforma más cercana para quedarse hay y que desactive su animación
User prompt
As que el ased Final1 al llegar a la distancia 1000 busque la plataforma más cercana y se ponga en ella y que cuando toques el ased Final1 puedas ganar
User prompt
As que el ased de obstáculo sea un poco más pequeño y que el terreno no pueda ir más arriba de la mitad de la pantalla
User prompt
Implementa un sistema de vida usando el ased corason1 que tenga 5 vidas asiendo que pierda 1 si toca un obstáculo y si pierde las 5 vidas piedar
User prompt
As que el ased Final1 no pueda ir a la izquierda
User prompt
Cuando la IA ased caminando1 cae de las plataformas al vacío no regenera
User prompt
As que el ased Final1 balla más rápido y que la IA ased caminando1 respaune en la misma posición del jugador
User prompt
As que la IA ased caminando1 cuando muera se regenere un poco de tras del jugador ensima de el jugador
User prompt
Cuando la IA ased caminando1 revive daño me cuenta el daño a mi debería Aser que el ased caminando1 se regenere y resiba el daño para el
User prompt
La IA ased caminando1 no detecta el daño de los obstáculos y as que el ased Final1 Balla a una velocidad un poco más rápida
User prompt
As que el ased de Final1 se mueva y que según la distancia del jugador y la IA ased caminando1 que aga que si no está en la distancia 1000 no puedan llegar a ella
User prompt
La IA ased caminando1 ya no detecta las colisiones del suelo
/****
* 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
});
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 = -25;
self.gravity = 1.2;
self.speed = 8; // Match player speed exactly
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;
// Respawn AI at same position as player
self.x = player.x; // Position at same X as player
self.y = player.y; // Position at same Y as player
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
****/
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 playerLives = 5;
var maxLives = 5;
var hearts = [];
// 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 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();
// 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 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)
// 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
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
if (player.intersects(obstacle)) {
// Player loses one life
playerLives--;
// Flash player red when taking damage
LK.effects.flashObject(player, 0xff0000, 500);
LK.effects.flashScreen(0xff0000, 500);
// 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;
// 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 1000 from start
var finalAssetDistance = goalAsset.x - 300; // Subtract initial player position
if (finalAssetDistance >= 1000 && !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;
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;
createHeartDisplay();
originalShowGameOver();
};
game.update = function () {
// 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
}
}
// 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) {
// Respawn AI at same position as player
aiPlayer.x = player.x; // Position at same X as player
aiPlayer.y = player.y; // Position at same Y as player
aiPlayer.velocityX = 0;
aiPlayer.velocityY = 0;
aiPlayer.isGrounded = false;
LK.effects.flashObject(aiPlayer, 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;
}
// AI goal stays fixed at right center of screen - no movement needed
}
checkCollisions();
updateCamera();
updateAICamera();
generateLevel();
}; ===================================================================
--- original.js
+++ change.js
@@ -777,11 +777,16 @@
if (goalAsset.x >= screenRight) {
goalAsset.x = screenRight; // Keep at right boundary
}
}
- // Floating vertical motion
- goalAsset.floatTime += 0.02;
- goalAsset.y = goalAsset.baseY + Math.sin(goalAsset.floatTime) * 50;
+ // 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 1000 from start
@@ -803,8 +808,10 @@
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
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