Code edit (6 edits merged)
Please save this source code
User prompt
al presionar el boton de saltar debera ejecutarse el jumpPower
Code edit (3 edits merged)
Please save this source code
User prompt
agrega un boton para saltar
Code edit (1 edits merged)
Please save this source code
User prompt
que el valor del salto sea mayor a la gravedad
User prompt
restale un poco el valor a la gravedad
User prompt
el boton de saltar no funciona, mejor crea una funcion que permita que al deslizar en la pantalla hacia arriba el jugador salte
User prompt
remplaza la textura del boton saltar por un triangulo apuntando hacia arriba
User prompt
al dar click sobre el boton saltar el jugador debe aumentar su valor vertical el 500
User prompt
al dar click sobre el boton saltar el jugador debe subir y luego volver a caer
User prompt
el boton de saltar no funciona, solucionalo
User prompt
coloca el boton de saltar en la parte inferior central
User prompt
permite que si el jugador esta tocando el suelo pueda saltar utilizando el boton de saltar
User prompt
agrega un boton de saltar, que al presionarlo debe elevar al jugador desafiando la gravedad
User prompt
elimina el boton de saltar
User prompt
el boton de saltar sigue sin funcionar, solucionalo, al presionarlo el jugador debe poder elevarse un poco
User prompt
bien, elimina la función de caminar tocando los laterales de la pantalla y que solo se pueda caminar utilizando los botones de izquierda y derecha, y permite que el jugador pueda saltar utilizando el botón de saltar
User prompt
aumenta el zoom de la pantalla de forma que el suelo quede rosando la parte inferior de la pantalla, tambien agrega botones para moverse a izquierda y derecha, el boton izquierda al lateral izquierdo de la pantalla y el boton derecha al lateral derecho, y agrega un boton para saltar encima del boton derecha
Code edit (1 edits merged)
Please save this source code
User prompt
Super Jump Adventure
Initial prompt
quiero un juego de plataformas al estilo del super mario wolrd
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.rotationSpeed = 0.1;
self.baseY = 0; // Store original Y position for floating effect
self.floatOffset = 0; // Current floating offset
self.floatSpeed = 0.02; // Speed of floating animation
self.update = function () {
if (!self.collected) {
// Floating animation
self.floatOffset += self.floatSpeed;
var floatAmount = Math.sin(self.floatOffset) * 15; // 15 pixels up and down
self.y = self.baseY + floatAmount;
}
};
self.collect = function () {
if (!self.collected) {
self.collected = true;
LK.getSound('coin').play();
LK.setScore(LK.getScore() + 50);
coinsCollected++;
updateScoreDisplay();
tween(self, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 1.0
});
self.velocityX = 2;
self.speed = 2;
self.alive = true;
self.direction = 1;
self.stretchScale = 0.8;
self.stretchDirection = 1;
self.stretchSpeed = 0.017;
self.maxStretchScale = 1.0;
self.minStretchScale = 0.7;
self.update = function () {
if (!self.alive) {
return;
}
// Check for platform edges before moving
var nextX = self.x + self.velocityX * self.direction;
var onPlatform = false;
var shouldReverse = false;
// Check floating platforms
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
// Check if enemy is vertically aligned with this platform
if (self.y >= platform.y - 10 && self.y <= platform.y + 10) {
// Check if enemy is currently on this platform
if (self.x >= platform.x && self.x <= platform.x + platform.platformWidth) {
onPlatform = true;
// Check if next position would be off the platform
if (nextX < platform.x || nextX > platform.x + platform.platformWidth) {
shouldReverse = true;
break;
}
}
}
}
// Check ground if not on a platform
if (!onPlatform) {
if (self.y >= ground.y - 10 && self.y <= ground.y + 10) {
// Check if enemy is currently on ground
if (self.x >= ground.x && self.x <= ground.x + ground.platformWidth) {
onPlatform = true;
// Check if next position would be off the ground
if (nextX < ground.x || nextX > ground.x + ground.platformWidth) {
shouldReverse = true;
}
}
}
}
// Reverse direction if we would fall off
if (shouldReverse) {
self.direction *= -1;
}
// Stretch/squeeze animation - constantly growing and shrinking
self.stretchScale += self.stretchSpeed * self.stretchDirection;
if (self.stretchScale >= self.maxStretchScale) {
self.stretchScale = self.maxStretchScale;
self.stretchDirection = -1;
} else if (self.stretchScale <= self.minStretchScale) {
self.stretchScale = self.minStretchScale;
self.stretchDirection = 1;
}
// Apply stretch effect - stretch vertically, compress horizontally when stretching
var horizontalCompression = self.stretchScale > 1.0 ? 1.0 / self.stretchScale * 0.8 : 1.0;
enemyGraphics.scaleY = self.stretchScale;
// Flip enemy sprite based on direction and apply horizontal compression
enemyGraphics.scaleX = (self.direction > 0 ? 1 : -1) * horizontalCompression;
// Add forward lean when walking
var leanAmount = 0.15; // Lean angle in radians
enemyGraphics.rotation = self.direction > 0 ? leanAmount : -leanAmount;
// Move the enemy
self.x += self.velocityX * self.direction;
};
self.defeat = function () {
self.alive = false;
LK.getSound('enemyHit').play();
LK.setScore(LK.getScore() + 100);
updateScoreDisplay();
tween(self, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var Goal = Container.expand(function () {
var self = Container.call(this);
var goalGraphics = self.attachAsset('goal', {
anchorX: 0.5,
anchorY: 1.0
});
self.reached = false;
self.reachGoal = function () {
if (!self.reached) {
self.reached = true;
LK.setScore(LK.getScore() + 1000);
updateScoreDisplay();
LK.showYouWin();
}
};
return self;
});
var Ground = Container.expand(function (width, height) {
var self = Container.call(this);
var groundGraphics = self.attachAsset('ground', {
anchorX: 0,
anchorY: 0,
width: width || 300,
height: height || 40
});
self.platformWidth = width || 300;
self.platformHeight = height || 40;
return self;
});
var Hero = Container.expand(function () {
var self = Container.call(this);
var heroGraphics = self.attachAsset('hero', {
anchorX: 0.5,
anchorY: 1.0
});
self.velocityX = 0;
self.velocityY = 0;
self.canJump = true;
self.speed = 8;
self.jumpPower = -25;
self.gravity = 0.8;
self.maxFallSpeed = 50;
self.lives = 5;
self.invulnerable = false;
self.invulnerableTime = 0;
self.angerScale = 1.0;
self.angerDirection = 1;
self.angerSpeed = 0.02;
self.maxAngerScale = 1.3;
self.minAngerScale = 1.0;
self.walkingSplashTimer = 0;
self.walkingSplashFrequency = 8; // Create splash every 8 frames when walking
self.update = function () {
// Apply gravity
if (self.onGround === false) {
self.velocityY += self.gravity;
if (self.velocityY > self.maxFallSpeed) {
self.velocityY = self.maxFallSpeed;
}
}
// Apply velocities
self.x += self.velocityX;
self.y += self.velocityY;
// Handle invulnerability
if (self.invulnerable) {
self.invulnerableTime--;
heroGraphics.alpha = Math.sin(self.invulnerableTime * 0.3) * 0.5 + 0.5;
if (self.invulnerableTime <= 0) {
self.invulnerable = false;
heroGraphics.alpha = 1;
}
}
// Reset canJump when landing on ground
if (self.onGround === true && !self.wasOnGround) {
self.canJump = true;
}
// Update wasOnGround for next frame
self.wasOnGround = self.onGround;
// Friction
self.velocityX *= 0.85;
// Anger animation - constantly growing and shrinking
self.angerScale += self.angerSpeed * self.angerDirection;
if (self.angerScale >= self.maxAngerScale) {
self.angerScale = self.maxAngerScale;
self.angerDirection = -1;
} else if (self.angerScale <= self.minAngerScale) {
self.angerScale = self.minAngerScale;
self.angerDirection = 1;
}
// When shrinking (angerScale < 1), also stretch horizontally
var horizontalScale = self.angerScale < 1.0 ? 1.0 + (1.0 - self.angerScale) * 0.3 : 1.0;
heroGraphics.scaleY = Math.abs(heroGraphics.scaleX) * self.angerScale;
heroGraphics.scaleX = (heroGraphics.scaleX < 0 ? -1 : 1) * horizontalScale;
// Create walking splash effect when moving and on ground
if (self.onGround && Math.abs(self.velocityX) > 2) {
self.walkingSplashTimer++;
if (self.walkingSplashTimer >= self.walkingSplashFrequency) {
self.createWalkingSplashEffect();
self.walkingSplashTimer = 0;
}
}
};
self.jump = function () {
if (self.onGround && self.canJump) {
// Normal ground jump
self.velocityY = self.jumpPower;
self.canJump = false;
// Create splash effect when jumping
self.createSplashEffect();
// Stretch hero upward when jumping
tween(heroGraphics, {
scaleY: 1.4,
scaleX: 0.8
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
// Return to original form
tween(heroGraphics, {
scaleY: 1.0,
scaleX: 1.0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
}
};
self.moveLeft = function () {
self.velocityX = -self.speed;
heroGraphics.scaleX = -1; // Flip image horizontally when moving left
};
self.moveRight = function () {
self.velocityX = self.speed;
heroGraphics.scaleX = 1; // Reset image to normal orientation when moving right
};
self.createSplashEffect = function () {
// Create multiple splash particles
for (var i = 0; i < 6; i++) {
var splashParticle = LK.getAsset('splash', {
anchorX: 0.5,
anchorY: 0.5
});
// Position at hero's feet
splashParticle.x = self.x + (Math.random() - 0.5) * 60;
splashParticle.y = self.y - 5;
// Add to game
game.addChild(splashParticle);
// Animate splash particle
var randomVelX = (Math.random() - 0.5) * 8;
var randomVelY = -Math.random() * 4 - 2;
tween(splashParticle, {
x: splashParticle.x + randomVelX * 20,
y: splashParticle.y + randomVelY * 10,
scaleX: 0.3,
scaleY: 0.3,
alpha: 0
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
splashParticle.destroy();
}
});
}
};
self.createWalkingSplashEffect = function () {
// Create walking splash particles behind the hero
for (var i = 0; i < 3; i++) {
var splashParticle = LK.getAsset('splash', {
anchorX: 0.5,
anchorY: 0.5
});
// Position behind hero based on movement direction
var behindOffset = self.velocityX > 0 ? -30 : 30; // Behind the hero
splashParticle.x = self.x + behindOffset + (Math.random() - 0.5) * 20;
splashParticle.y = self.y - 5 + (Math.random() - 0.5) * 10;
// Add to game
game.addChild(splashParticle);
// Animate splash particle backwards
var splashVelX = self.velocityX > 0 ? -Math.random() * 6 - 2 : Math.random() * 6 + 2;
var splashVelY = -Math.random() * 8 - 4; // Increased upward velocity for more elevation
tween(splashParticle, {
x: splashParticle.x + splashVelX * 15,
y: splashParticle.y + splashVelY * 15,
// Increased multiplier for more elevation
scaleX: 0.2,
scaleY: 0.2,
alpha: 0
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
splashParticle.destroy();
}
});
}
};
self.takeDamage = function () {
if (!self.invulnerable) {
self.lives--;
self.invulnerable = true;
self.invulnerableTime = 120;
LK.effects.flashScreen(0xff0000, 500);
updateLivesDisplay();
// Determine knockback direction based on hero facing direction
var knockbackDirection = heroGraphics.scaleX > 0 ? -1 : 1; // If facing right, knock left; if facing left, knock right
var knockbackVelocity = knockbackDirection * 15; // Knockback speed
// Apply knockback jump
self.velocityY = -12; // Reduced upward velocity
self.velocityX = knockbackVelocity * 1.5; // Increased horizontal knockback distance
// Lean backward animation - tilt in knockback direction
tween(heroGraphics, {
rotation: knockbackDirection * 0.4
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Return to upright position
tween(heroGraphics, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
if (self.lives <= 0) {
LK.showGameOver();
}
}
};
return self;
});
var Platform = Container.expand(function (width, height) {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0,
anchorY: 0,
width: width || 300,
height: height || 40
});
self.platformWidth = width || 300;
self.platformHeight = height || 40;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb
});
/****
* Game Code
****/
// Set background using cielocaricatura image
game.setBackgroundColor(0x87ceeb);
var background = game.addChild(LK.getAsset('cielocaricatura', {
anchorX: 0,
anchorY: 0.2,
scaleX: 40.96,
// Scale to cover full level width (4000/100)
scaleY: 27.32 // Scale to fit screen height (2732/100)
}));
background.x = 0;
background.y = 0;
var hero;
var platforms = [];
var ground;
var enemies = [];
var coins = [];
var goal;
var camera = {
x: 0,
y: 0
};
//ALARGAR NIVEL
var levelWidth = 7000;
var coinsCollected = 0;
var totalCoins = 0;
var trail = [];
var trailTimer = 0;
var trailFrequency = 8; // Create trail every 8 frames when moving
// Button controls only
var leftPressed = false;
var rightPressed = false;
var jumpPressed = false;
// UI Elements
var coinIcon = LK.getAsset('coin', {
anchorX: 0,
anchorY: 0,
scaleX: 1.3,
scaleY: 1.3
});
LK.gui.topLeft.addChild(coinIcon);
coinIcon.x = 105;
coinIcon.y = 50;
var scoreText = new Text2('0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
LK.gui.topLeft.addChild(scoreText);
scoreText.x = 200;
scoreText.y = 47;
// Lives display with player icon
var livesIcon = LK.getAsset('hero', {
anchorX: 0,
anchorY: 0,
scaleX: 1,
scaleY: 1
});
LK.gui.topLeft.addChild(livesIcon);
livesIcon.x = 100;
livesIcon.y = 150;
var livesText = new Text2('5', {
size: 60,
fill: 0xFFFFFF
});
livesText.anchor.set(0, 0);
LK.gui.topLeft.addChild(livesText);
livesText.x = 200;
livesText.y = 150;
// Position display in top-right corner
var positionText = new Text2('X: 0 Y: 0', {
size: 50,
fill: 0xFFFFFF
});
positionText.anchor.set(1, 0);
LK.gui.topRight.addChild(positionText);
positionText.x = -50;
positionText.y = 50;
// FPS display removed for optimization
// Control buttons
var leftButton = LK.getAsset('DIRECCION', {
size: 300,
scaleX: -1,
fill: 0xFFFFFF
});
leftButton.anchor.set(0.5, 0.5);
LK.gui.bottomLeft.addChild(leftButton);
leftButton.x = 250;
leftButton.y = -220;
var rightButton = LK.getAsset('DIRECCION', {
size: 300,
fill: 0xFFFFFF
});
rightButton.anchor.set(0.5, 0.5);
LK.gui.bottomRight.addChild(rightButton);
rightButton.x = -250;
rightButton.y = -220;
var jumpButton = LK.getAsset('jumpButtonAsset', {
scaleX: 2.5,
scaleY: 2.5
});
jumpButton.anchor.set(0.5, 0.5);
jumpButton.alpha = 0.8; // Make slightly transparent for better visual feedback
LK.gui.bottom.addChild(jumpButton);
jumpButton.x = 0;
jumpButton.y = -250;
// Jump button event handlers
jumpButton.down = function (x, y, obj) {
// Set jump pressed state
jumpPressed = true;
// Immediate visual feedback - scale up from original size (2.5)
jumpButton.scaleX = 3.0;
jumpButton.scaleY = 3.0;
jumpButton.alpha = 1.0;
tween(jumpButton, {
scaleX: 2.7,
scaleY: 2.7
}, {
duration: 50,
easing: tween.easeOut
});
};
jumpButton.up = function (x, y, obj) {
// Clear jump pressed state
jumpPressed = false;
tween(jumpButton, {
scaleX: 2.5,
scaleY: 2.5,
alpha: 0.8
}, {
duration: 150,
easing: tween.easeOut
});
};
// Swipe detection variables
var swipeStartY = 0;
var swipeStartTime = 0;
var isSwipeActive = false;
var swipeThreshold = 100; // Minimum distance for swipe
var swipeTimeLimit = 500; // Maximum time for swipe in milliseconds
function updateScoreDisplay() {
scoreText.setText(coinsCollected.toString());
}
function updateLivesDisplay() {
livesText.setText(hero.lives.toString());
}
function createLevel() {
// Create hero
hero = game.addChild(new Hero());
hero.x = 200;
hero.y = 600;
hero.wasOnGround = false;
// Create floating platforms
var platformData = [{
x: 600,
y: 550,
width: 300,
height: 150
}, {
x: 1100,
y: 450,
width: 250,
height: 250
}, {
x: 1500,
y: 350,
width: 200,
height: 350
}, {
x: 1900,
y: 450,
width: 300,
height: 250
}, {
x: 2400,
y: 550,
width: 250,
height: 150
}, {
x: 2900,
y: 350,
width: 200,
height: 350
}, {
x: 3300,
y: 250,
width: 300,
height: 450
}, {
x: 3800,
y: 350,
width: 200,
height: 350
}, {
x: -200,
y: -300,
width: 300,
height: 1000
}];
for (var i = 0; i < platformData.length; i++) {
var data = platformData[i];
var platform = game.addChild(new Platform(data.width, data.height));
platform.x = data.x;
platform.y = data.y;
platforms.push(platform);
}
// Create ground separately
ground = game.addChild(new Ground(levelWidth, 2000));
ground.x = 0;
ground.y = 700;
// Create enemies
var enemyPositions = [{
x: 700,
y: 550
}, {
x: 1200,
y: 450
}, {
x: 2000,
y: 450
}, {
x: 2500,
y: 550
}, {
x: 3400,
y: 250
}];
for (var j = 0; j < enemyPositions.length; j++) {
var enemyPos = enemyPositions[j];
var enemy = game.addChild(new Enemy());
enemy.x = enemyPos.x;
enemy.y = enemyPos.y;
enemies.push(enemy);
}
// Create coins
var coinPositions = [
//CAJA 01
{
x: 750,
y: 500
}, {
x: 850,
y: 500
}, {
x: 650,
y: 500
},
//CAJA 02
{
x: 1275,
y: 400
}, {
x: 1175,
y: 400
},
//CAJA 03
{
x: 1600,
y: 300
},
//CAJA 04
{
x: 2050,
y: 400
}, {
x: 2150,
y: 400
}, {
x: 1950,
y: 400
},
//CAJA 05
{
x: 2575,
y: 500
}, {
x: 2475,
y: 500
},
//CAJA 06
{
x: 3000,
y: 300
}, {
x: 3000,
y: 150
}, {
x: 3000,
y: 0
},
// CAJA 07
{
x: 3450,
y: 200
}, {
x: 3550,
y: 200
}, {
x: 3350,
y: 200
}, {
x: 3900,
y: 300
}];
totalCoins = coinPositions.length;
for (var k = 0; k < coinPositions.length; k++) {
var coinPos = coinPositions[k];
var coin = game.addChild(new Coin());
coin.x = coinPos.x;
coin.y = coinPos.y;
coin.baseY = coinPos.y; // Store original Y position for floating
coin.floatOffset = Math.random() * Math.PI * 2; // Random starting phase for variety
coins.push(coin);
}
// Create goal
goal = game.addChild(new Goal());
goal.x = 6500;
goal.y = 735;
}
function checkPlatformCollisions() {
// Reset ground state - hero is only on ground if touching a platform
hero.onGround = false;
// Check collisions with floating platforms
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
checkSinglePlatformCollision(platform);
}
// Check collision with ground
checkSinglePlatformCollision(ground);
}
function checkSinglePlatformCollision(platform) {
// Define hero boundaries
var heroLeft = hero.x - 40;
var heroRight = hero.x + 40;
var heroTop = hero.y - 80;
var heroBottom = hero.y;
var heroCenterX = hero.x;
var heroCenterY = hero.y - 40;
// Define platform boundaries
var platformLeft = platform.x;
var platformRight = platform.x + platform.platformWidth;
var platformTop = platform.y;
var platformBottom = platform.y + platform.platformHeight;
// Check if hero is overlapping with platform
var horizontalOverlap = heroRight > platformLeft && heroLeft < platformRight;
var verticalOverlap = heroBottom > platformTop && heroTop < platformBottom;
if (horizontalOverlap && verticalOverlap) {
// Calculate overlap distances
var overlapLeft = heroRight - platformLeft;
var overlapRight = platformRight - heroLeft;
var overlapTop = heroBottom - platformTop;
var overlapBottom = platformBottom - heroTop;
// Find minimum overlap to determine collision direction
var minOverlap = Math.min(overlapLeft, overlapRight, overlapTop, overlapBottom);
// Resolve collision based on minimum overlap
if (minOverlap === overlapTop && hero.velocityY >= 0) {
// Landing on top of platform
hero.y = platformTop;
hero.velocityY = 0;
hero.onGround = true;
hero.canJump = true;
} else if (minOverlap === overlapBottom && hero.velocityY < 0) {
// Hitting platform from below
hero.y = platformBottom + 80;
hero.velocityY = 0;
} else if (minOverlap === overlapLeft && hero.velocityX > 0) {
// Hitting platform from left side
hero.x = platformLeft - 40;
hero.velocityX = 0;
} else if (minOverlap === overlapRight && hero.velocityX < 0) {
// Hitting platform from right side
hero.x = platformRight + 40;
hero.velocityX = 0;
}
}
}
function checkEnemyCollisions() {
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (!enemy.alive) {
continue;
}
if (hero.intersects(enemy)) {
// Check if hero is jumping on enemy
if (hero.velocityY > 0 && hero.y < enemy.y - 30) {
enemy.defeat();
enemies.splice(i, 1);
hero.velocityY = -15; // Bounce
} else {
hero.takeDamage();
}
}
}
}
function checkCoinCollisions() {
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
if (!coin.collected && hero.intersects(coin)) {
coin.collect();
coins.splice(i, 1);
}
}
}
function checkGoalCollision() {
if (!goal.reached && hero.intersects(goal)) {
goal.reachGoal();
}
}
function updateCamera() {
// Camera follows hero smoothly - adjusted view area for larger screen
var targetX = hero.x - 450; // Center horizontally (2048/2 = 1024)
var targetY = hero.y - 1000; // Center vertically (2732/2 = 1366) - raised camera
// Smooth camera movement with good responsiveness
camera.x += (targetX - camera.x) * 0.1;
camera.y += (targetY - camera.y) * 0.1;
// Keep camera within level bounds - adjusted for larger view and scale factor
if (camera.x < 0) {
camera.x = 0;
}
if (camera.x > levelWidth - 1024) {
// Adjusted for 2.0 scale (2048/2 = 1024)
camera.x = levelWidth - 1024;
}
if (camera.y < -600) {
camera.y = -600;
}
if (camera.y > 350) {
camera.y = 350;
}
// Apply camera position to game world with scale factor
game.x = -camera.x * 2.0;
game.y = -camera.y * 1.0;
}
function checkBounds() {
// Check if hero fell off the world
if (hero.y > 1000) {
hero.takeDamage();
hero.x = 200;
hero.y = 600;
hero.velocityX = 0;
hero.velocityY = 0;
}
}
// Button event handlers
leftButton.down = function (x, y, obj) {
leftPressed = true;
tween(leftButton, {
scaleX: -1.2,
scaleY: 1.2
}, {
duration: 100,
easing: tween.easeOut
});
// Tilt hero to the left
tween(hero, {
rotation: -0.3
}, {
duration: 200,
easing: tween.easeOut
});
};
leftButton.up = function (x, y, obj) {
leftPressed = false;
tween(leftButton, {
scaleX: -1,
scaleY: 1
}, {
duration: 100,
easing: tween.easeOut
});
// Reset hero tilt to upright
tween(hero, {
rotation: 0
}, {
duration: 200,
easing: tween.easeOut
});
};
rightButton.down = function (x, y, obj) {
rightPressed = true;
tween(rightButton, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100,
easing: tween.easeOut
});
// Tilt hero to the right
tween(hero, {
rotation: 0.3
}, {
duration: 200,
easing: tween.easeOut
});
};
rightButton.up = function (x, y, obj) {
rightPressed = false;
tween(rightButton, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.easeOut
});
// Reset hero tilt to upright
tween(hero, {
rotation: 0
}, {
duration: 200,
easing: tween.easeOut
});
};
// Touch controls with swipe detection
game.down = function (x, y, obj) {
// Start swipe detection
swipeStartY = y;
swipeStartTime = Date.now();
isSwipeActive = true;
};
game.move = function (x, y, obj) {
// Track swipe movement but don't perform action yet
};
game.up = function (x, y, obj) {
isSwipeActive = false;
};
game.update = function () {
// FPS calculation removed for optimization
// Handle continuous button presses
if (leftPressed) {
hero.moveLeft();
}
if (rightPressed) {
hero.moveRight();
}
// Handle continuous jump - jump again when landing if button is still held
if (jumpPressed && hero.onGround && hero.canJump) {
hero.jump();
}
// Create trail when hero is moving on ground
var isActuallyOnGround = false;
// Cache hero bounds for optimization
var heroLeft = hero.x - 40;
var heroRight = hero.x + 40;
var heroBottom = hero.y;
// Check if hero is actually touching any platform or ground
for (var p = 0; p < platforms.length; p++) {
var platform = platforms[p];
if (heroRight > platform.x && heroLeft < platform.x + platform.platformWidth) {
if (Math.abs(heroBottom - platform.y) < 5) {
isActuallyOnGround = true;
break;
}
}
}
// Check ground collision
if (!isActuallyOnGround) {
if (heroRight > ground.x && heroLeft < ground.x + ground.platformWidth) {
if (Math.abs(heroBottom - ground.y) < 5) {
isActuallyOnGround = true;
}
}
}
if (isActuallyOnGround && (leftPressed || rightPressed)) {
trailTimer++;
if (trailTimer >= trailFrequency) {
var trailPiece = game.addChild(LK.getAsset('trail', {
anchorX: 0.5,
anchorY: 0.5
}));
trailPiece.x = hero.x;
trailPiece.y = hero.y - 1 + (Math.random() - 0.5) * 10; // Slightly above ground with height variation
trailPiece.fadeTimer = 500; // 0.5 seconds in milliseconds
trail.push(trailPiece);
trailTimer = 10;
}
}
// Check for floating trail pieces and remove them, also handle fade timer
for (var t = trail.length - 1; t >= 0; t--) {
var trailPiece = trail[t];
// Decrease fade timer
trailPiece.fadeTimer -= 16.67; // Approximately 1 frame at 60fps (1000ms/60fps)
// Check if fade timer expired
if (trailPiece.fadeTimer <= 0) {
// Start fade out effect
tween(trailPiece, {
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
trailPiece.destroy();
}
});
trail.splice(t, 1);
continue;
}
// Cache trail piece bounds for optimization
var trailLeft = trailPiece.x - 17.5;
var trailRight = trailPiece.x + 17.5;
var trailBottom = trailPiece.y + 7.5;
var trailOnGround = false;
// Check if trail piece is on any platform
for (var p = 0; p < platforms.length; p++) {
var platform = platforms[p];
if (trailRight > platform.x && trailLeft < platform.x + platform.platformWidth) {
if (Math.abs(trailBottom - platform.y) < 10) {
trailOnGround = true;
break;
}
}
}
// Check if trail piece is on ground
if (!trailOnGround) {
if (trailRight > ground.x && trailLeft < ground.x + ground.platformWidth) {
if (Math.abs(trailBottom - ground.y) < 10) {
trailOnGround = true;
}
}
}
// Remove trail piece if it's floating
if (!trailOnGround) {
trailPiece.destroy();
trail.splice(t, 1);
}
}
checkPlatformCollisions();
checkEnemyCollisions();
checkCoinCollisions();
checkGoalCollision();
checkBounds();
updateCamera();
// Update position display
positionText.setText('X: ' + Math.round(hero.x) + ' Y: ' + Math.round(hero.y));
};
// Initialize level
createLevel();
// Scale game up to increase screen size
tween(game, {
scaleX: 2.0,
scaleY: 2.0
}, {
duration: 1000,
easing: tween.easeInOut
}); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.rotationSpeed = 0.1;
self.baseY = 0; // Store original Y position for floating effect
self.floatOffset = 0; // Current floating offset
self.floatSpeed = 0.02; // Speed of floating animation
self.update = function () {
if (!self.collected) {
// Floating animation
self.floatOffset += self.floatSpeed;
var floatAmount = Math.sin(self.floatOffset) * 15; // 15 pixels up and down
self.y = self.baseY + floatAmount;
}
};
self.collect = function () {
if (!self.collected) {
self.collected = true;
LK.getSound('coin').play();
LK.setScore(LK.getScore() + 50);
coinsCollected++;
updateScoreDisplay();
tween(self, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 1.0
});
self.velocityX = 2;
self.speed = 2;
self.alive = true;
self.direction = 1;
self.stretchScale = 0.8;
self.stretchDirection = 1;
self.stretchSpeed = 0.017;
self.maxStretchScale = 1.0;
self.minStretchScale = 0.7;
self.update = function () {
if (!self.alive) {
return;
}
// Check for platform edges before moving
var nextX = self.x + self.velocityX * self.direction;
var onPlatform = false;
var shouldReverse = false;
// Check floating platforms
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
// Check if enemy is vertically aligned with this platform
if (self.y >= platform.y - 10 && self.y <= platform.y + 10) {
// Check if enemy is currently on this platform
if (self.x >= platform.x && self.x <= platform.x + platform.platformWidth) {
onPlatform = true;
// Check if next position would be off the platform
if (nextX < platform.x || nextX > platform.x + platform.platformWidth) {
shouldReverse = true;
break;
}
}
}
}
// Check ground if not on a platform
if (!onPlatform) {
if (self.y >= ground.y - 10 && self.y <= ground.y + 10) {
// Check if enemy is currently on ground
if (self.x >= ground.x && self.x <= ground.x + ground.platformWidth) {
onPlatform = true;
// Check if next position would be off the ground
if (nextX < ground.x || nextX > ground.x + ground.platformWidth) {
shouldReverse = true;
}
}
}
}
// Reverse direction if we would fall off
if (shouldReverse) {
self.direction *= -1;
}
// Stretch/squeeze animation - constantly growing and shrinking
self.stretchScale += self.stretchSpeed * self.stretchDirection;
if (self.stretchScale >= self.maxStretchScale) {
self.stretchScale = self.maxStretchScale;
self.stretchDirection = -1;
} else if (self.stretchScale <= self.minStretchScale) {
self.stretchScale = self.minStretchScale;
self.stretchDirection = 1;
}
// Apply stretch effect - stretch vertically, compress horizontally when stretching
var horizontalCompression = self.stretchScale > 1.0 ? 1.0 / self.stretchScale * 0.8 : 1.0;
enemyGraphics.scaleY = self.stretchScale;
// Flip enemy sprite based on direction and apply horizontal compression
enemyGraphics.scaleX = (self.direction > 0 ? 1 : -1) * horizontalCompression;
// Add forward lean when walking
var leanAmount = 0.15; // Lean angle in radians
enemyGraphics.rotation = self.direction > 0 ? leanAmount : -leanAmount;
// Move the enemy
self.x += self.velocityX * self.direction;
};
self.defeat = function () {
self.alive = false;
LK.getSound('enemyHit').play();
LK.setScore(LK.getScore() + 100);
updateScoreDisplay();
tween(self, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var Goal = Container.expand(function () {
var self = Container.call(this);
var goalGraphics = self.attachAsset('goal', {
anchorX: 0.5,
anchorY: 1.0
});
self.reached = false;
self.reachGoal = function () {
if (!self.reached) {
self.reached = true;
LK.setScore(LK.getScore() + 1000);
updateScoreDisplay();
LK.showYouWin();
}
};
return self;
});
var Ground = Container.expand(function (width, height) {
var self = Container.call(this);
var groundGraphics = self.attachAsset('ground', {
anchorX: 0,
anchorY: 0,
width: width || 300,
height: height || 40
});
self.platformWidth = width || 300;
self.platformHeight = height || 40;
return self;
});
var Hero = Container.expand(function () {
var self = Container.call(this);
var heroGraphics = self.attachAsset('hero', {
anchorX: 0.5,
anchorY: 1.0
});
self.velocityX = 0;
self.velocityY = 0;
self.canJump = true;
self.speed = 8;
self.jumpPower = -25;
self.gravity = 0.8;
self.maxFallSpeed = 50;
self.lives = 5;
self.invulnerable = false;
self.invulnerableTime = 0;
self.angerScale = 1.0;
self.angerDirection = 1;
self.angerSpeed = 0.02;
self.maxAngerScale = 1.3;
self.minAngerScale = 1.0;
self.walkingSplashTimer = 0;
self.walkingSplashFrequency = 8; // Create splash every 8 frames when walking
self.update = function () {
// Apply gravity
if (self.onGround === false) {
self.velocityY += self.gravity;
if (self.velocityY > self.maxFallSpeed) {
self.velocityY = self.maxFallSpeed;
}
}
// Apply velocities
self.x += self.velocityX;
self.y += self.velocityY;
// Handle invulnerability
if (self.invulnerable) {
self.invulnerableTime--;
heroGraphics.alpha = Math.sin(self.invulnerableTime * 0.3) * 0.5 + 0.5;
if (self.invulnerableTime <= 0) {
self.invulnerable = false;
heroGraphics.alpha = 1;
}
}
// Reset canJump when landing on ground
if (self.onGround === true && !self.wasOnGround) {
self.canJump = true;
}
// Update wasOnGround for next frame
self.wasOnGround = self.onGround;
// Friction
self.velocityX *= 0.85;
// Anger animation - constantly growing and shrinking
self.angerScale += self.angerSpeed * self.angerDirection;
if (self.angerScale >= self.maxAngerScale) {
self.angerScale = self.maxAngerScale;
self.angerDirection = -1;
} else if (self.angerScale <= self.minAngerScale) {
self.angerScale = self.minAngerScale;
self.angerDirection = 1;
}
// When shrinking (angerScale < 1), also stretch horizontally
var horizontalScale = self.angerScale < 1.0 ? 1.0 + (1.0 - self.angerScale) * 0.3 : 1.0;
heroGraphics.scaleY = Math.abs(heroGraphics.scaleX) * self.angerScale;
heroGraphics.scaleX = (heroGraphics.scaleX < 0 ? -1 : 1) * horizontalScale;
// Create walking splash effect when moving and on ground
if (self.onGround && Math.abs(self.velocityX) > 2) {
self.walkingSplashTimer++;
if (self.walkingSplashTimer >= self.walkingSplashFrequency) {
self.createWalkingSplashEffect();
self.walkingSplashTimer = 0;
}
}
};
self.jump = function () {
if (self.onGround && self.canJump) {
// Normal ground jump
self.velocityY = self.jumpPower;
self.canJump = false;
// Create splash effect when jumping
self.createSplashEffect();
// Stretch hero upward when jumping
tween(heroGraphics, {
scaleY: 1.4,
scaleX: 0.8
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
// Return to original form
tween(heroGraphics, {
scaleY: 1.0,
scaleX: 1.0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
}
};
self.moveLeft = function () {
self.velocityX = -self.speed;
heroGraphics.scaleX = -1; // Flip image horizontally when moving left
};
self.moveRight = function () {
self.velocityX = self.speed;
heroGraphics.scaleX = 1; // Reset image to normal orientation when moving right
};
self.createSplashEffect = function () {
// Create multiple splash particles
for (var i = 0; i < 6; i++) {
var splashParticle = LK.getAsset('splash', {
anchorX: 0.5,
anchorY: 0.5
});
// Position at hero's feet
splashParticle.x = self.x + (Math.random() - 0.5) * 60;
splashParticle.y = self.y - 5;
// Add to game
game.addChild(splashParticle);
// Animate splash particle
var randomVelX = (Math.random() - 0.5) * 8;
var randomVelY = -Math.random() * 4 - 2;
tween(splashParticle, {
x: splashParticle.x + randomVelX * 20,
y: splashParticle.y + randomVelY * 10,
scaleX: 0.3,
scaleY: 0.3,
alpha: 0
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
splashParticle.destroy();
}
});
}
};
self.createWalkingSplashEffect = function () {
// Create walking splash particles behind the hero
for (var i = 0; i < 3; i++) {
var splashParticle = LK.getAsset('splash', {
anchorX: 0.5,
anchorY: 0.5
});
// Position behind hero based on movement direction
var behindOffset = self.velocityX > 0 ? -30 : 30; // Behind the hero
splashParticle.x = self.x + behindOffset + (Math.random() - 0.5) * 20;
splashParticle.y = self.y - 5 + (Math.random() - 0.5) * 10;
// Add to game
game.addChild(splashParticle);
// Animate splash particle backwards
var splashVelX = self.velocityX > 0 ? -Math.random() * 6 - 2 : Math.random() * 6 + 2;
var splashVelY = -Math.random() * 8 - 4; // Increased upward velocity for more elevation
tween(splashParticle, {
x: splashParticle.x + splashVelX * 15,
y: splashParticle.y + splashVelY * 15,
// Increased multiplier for more elevation
scaleX: 0.2,
scaleY: 0.2,
alpha: 0
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
splashParticle.destroy();
}
});
}
};
self.takeDamage = function () {
if (!self.invulnerable) {
self.lives--;
self.invulnerable = true;
self.invulnerableTime = 120;
LK.effects.flashScreen(0xff0000, 500);
updateLivesDisplay();
// Determine knockback direction based on hero facing direction
var knockbackDirection = heroGraphics.scaleX > 0 ? -1 : 1; // If facing right, knock left; if facing left, knock right
var knockbackVelocity = knockbackDirection * 15; // Knockback speed
// Apply knockback jump
self.velocityY = -12; // Reduced upward velocity
self.velocityX = knockbackVelocity * 1.5; // Increased horizontal knockback distance
// Lean backward animation - tilt in knockback direction
tween(heroGraphics, {
rotation: knockbackDirection * 0.4
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Return to upright position
tween(heroGraphics, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
if (self.lives <= 0) {
LK.showGameOver();
}
}
};
return self;
});
var Platform = Container.expand(function (width, height) {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0,
anchorY: 0,
width: width || 300,
height: height || 40
});
self.platformWidth = width || 300;
self.platformHeight = height || 40;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb
});
/****
* Game Code
****/
// Set background using cielocaricatura image
game.setBackgroundColor(0x87ceeb);
var background = game.addChild(LK.getAsset('cielocaricatura', {
anchorX: 0,
anchorY: 0.2,
scaleX: 40.96,
// Scale to cover full level width (4000/100)
scaleY: 27.32 // Scale to fit screen height (2732/100)
}));
background.x = 0;
background.y = 0;
var hero;
var platforms = [];
var ground;
var enemies = [];
var coins = [];
var goal;
var camera = {
x: 0,
y: 0
};
//ALARGAR NIVEL
var levelWidth = 7000;
var coinsCollected = 0;
var totalCoins = 0;
var trail = [];
var trailTimer = 0;
var trailFrequency = 8; // Create trail every 8 frames when moving
// Button controls only
var leftPressed = false;
var rightPressed = false;
var jumpPressed = false;
// UI Elements
var coinIcon = LK.getAsset('coin', {
anchorX: 0,
anchorY: 0,
scaleX: 1.3,
scaleY: 1.3
});
LK.gui.topLeft.addChild(coinIcon);
coinIcon.x = 105;
coinIcon.y = 50;
var scoreText = new Text2('0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
LK.gui.topLeft.addChild(scoreText);
scoreText.x = 200;
scoreText.y = 47;
// Lives display with player icon
var livesIcon = LK.getAsset('hero', {
anchorX: 0,
anchorY: 0,
scaleX: 1,
scaleY: 1
});
LK.gui.topLeft.addChild(livesIcon);
livesIcon.x = 100;
livesIcon.y = 150;
var livesText = new Text2('5', {
size: 60,
fill: 0xFFFFFF
});
livesText.anchor.set(0, 0);
LK.gui.topLeft.addChild(livesText);
livesText.x = 200;
livesText.y = 150;
// Position display in top-right corner
var positionText = new Text2('X: 0 Y: 0', {
size: 50,
fill: 0xFFFFFF
});
positionText.anchor.set(1, 0);
LK.gui.topRight.addChild(positionText);
positionText.x = -50;
positionText.y = 50;
// FPS display removed for optimization
// Control buttons
var leftButton = LK.getAsset('DIRECCION', {
size: 300,
scaleX: -1,
fill: 0xFFFFFF
});
leftButton.anchor.set(0.5, 0.5);
LK.gui.bottomLeft.addChild(leftButton);
leftButton.x = 250;
leftButton.y = -220;
var rightButton = LK.getAsset('DIRECCION', {
size: 300,
fill: 0xFFFFFF
});
rightButton.anchor.set(0.5, 0.5);
LK.gui.bottomRight.addChild(rightButton);
rightButton.x = -250;
rightButton.y = -220;
var jumpButton = LK.getAsset('jumpButtonAsset', {
scaleX: 2.5,
scaleY: 2.5
});
jumpButton.anchor.set(0.5, 0.5);
jumpButton.alpha = 0.8; // Make slightly transparent for better visual feedback
LK.gui.bottom.addChild(jumpButton);
jumpButton.x = 0;
jumpButton.y = -250;
// Jump button event handlers
jumpButton.down = function (x, y, obj) {
// Set jump pressed state
jumpPressed = true;
// Immediate visual feedback - scale up from original size (2.5)
jumpButton.scaleX = 3.0;
jumpButton.scaleY = 3.0;
jumpButton.alpha = 1.0;
tween(jumpButton, {
scaleX: 2.7,
scaleY: 2.7
}, {
duration: 50,
easing: tween.easeOut
});
};
jumpButton.up = function (x, y, obj) {
// Clear jump pressed state
jumpPressed = false;
tween(jumpButton, {
scaleX: 2.5,
scaleY: 2.5,
alpha: 0.8
}, {
duration: 150,
easing: tween.easeOut
});
};
// Swipe detection variables
var swipeStartY = 0;
var swipeStartTime = 0;
var isSwipeActive = false;
var swipeThreshold = 100; // Minimum distance for swipe
var swipeTimeLimit = 500; // Maximum time for swipe in milliseconds
function updateScoreDisplay() {
scoreText.setText(coinsCollected.toString());
}
function updateLivesDisplay() {
livesText.setText(hero.lives.toString());
}
function createLevel() {
// Create hero
hero = game.addChild(new Hero());
hero.x = 200;
hero.y = 600;
hero.wasOnGround = false;
// Create floating platforms
var platformData = [{
x: 600,
y: 550,
width: 300,
height: 150
}, {
x: 1100,
y: 450,
width: 250,
height: 250
}, {
x: 1500,
y: 350,
width: 200,
height: 350
}, {
x: 1900,
y: 450,
width: 300,
height: 250
}, {
x: 2400,
y: 550,
width: 250,
height: 150
}, {
x: 2900,
y: 350,
width: 200,
height: 350
}, {
x: 3300,
y: 250,
width: 300,
height: 450
}, {
x: 3800,
y: 350,
width: 200,
height: 350
}, {
x: -200,
y: -300,
width: 300,
height: 1000
}];
for (var i = 0; i < platformData.length; i++) {
var data = platformData[i];
var platform = game.addChild(new Platform(data.width, data.height));
platform.x = data.x;
platform.y = data.y;
platforms.push(platform);
}
// Create ground separately
ground = game.addChild(new Ground(levelWidth, 2000));
ground.x = 0;
ground.y = 700;
// Create enemies
var enemyPositions = [{
x: 700,
y: 550
}, {
x: 1200,
y: 450
}, {
x: 2000,
y: 450
}, {
x: 2500,
y: 550
}, {
x: 3400,
y: 250
}];
for (var j = 0; j < enemyPositions.length; j++) {
var enemyPos = enemyPositions[j];
var enemy = game.addChild(new Enemy());
enemy.x = enemyPos.x;
enemy.y = enemyPos.y;
enemies.push(enemy);
}
// Create coins
var coinPositions = [
//CAJA 01
{
x: 750,
y: 500
}, {
x: 850,
y: 500
}, {
x: 650,
y: 500
},
//CAJA 02
{
x: 1275,
y: 400
}, {
x: 1175,
y: 400
},
//CAJA 03
{
x: 1600,
y: 300
},
//CAJA 04
{
x: 2050,
y: 400
}, {
x: 2150,
y: 400
}, {
x: 1950,
y: 400
},
//CAJA 05
{
x: 2575,
y: 500
}, {
x: 2475,
y: 500
},
//CAJA 06
{
x: 3000,
y: 300
}, {
x: 3000,
y: 150
}, {
x: 3000,
y: 0
},
// CAJA 07
{
x: 3450,
y: 200
}, {
x: 3550,
y: 200
}, {
x: 3350,
y: 200
}, {
x: 3900,
y: 300
}];
totalCoins = coinPositions.length;
for (var k = 0; k < coinPositions.length; k++) {
var coinPos = coinPositions[k];
var coin = game.addChild(new Coin());
coin.x = coinPos.x;
coin.y = coinPos.y;
coin.baseY = coinPos.y; // Store original Y position for floating
coin.floatOffset = Math.random() * Math.PI * 2; // Random starting phase for variety
coins.push(coin);
}
// Create goal
goal = game.addChild(new Goal());
goal.x = 6500;
goal.y = 735;
}
function checkPlatformCollisions() {
// Reset ground state - hero is only on ground if touching a platform
hero.onGround = false;
// Check collisions with floating platforms
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
checkSinglePlatformCollision(platform);
}
// Check collision with ground
checkSinglePlatformCollision(ground);
}
function checkSinglePlatformCollision(platform) {
// Define hero boundaries
var heroLeft = hero.x - 40;
var heroRight = hero.x + 40;
var heroTop = hero.y - 80;
var heroBottom = hero.y;
var heroCenterX = hero.x;
var heroCenterY = hero.y - 40;
// Define platform boundaries
var platformLeft = platform.x;
var platformRight = platform.x + platform.platformWidth;
var platformTop = platform.y;
var platformBottom = platform.y + platform.platformHeight;
// Check if hero is overlapping with platform
var horizontalOverlap = heroRight > platformLeft && heroLeft < platformRight;
var verticalOverlap = heroBottom > platformTop && heroTop < platformBottom;
if (horizontalOverlap && verticalOverlap) {
// Calculate overlap distances
var overlapLeft = heroRight - platformLeft;
var overlapRight = platformRight - heroLeft;
var overlapTop = heroBottom - platformTop;
var overlapBottom = platformBottom - heroTop;
// Find minimum overlap to determine collision direction
var minOverlap = Math.min(overlapLeft, overlapRight, overlapTop, overlapBottom);
// Resolve collision based on minimum overlap
if (minOverlap === overlapTop && hero.velocityY >= 0) {
// Landing on top of platform
hero.y = platformTop;
hero.velocityY = 0;
hero.onGround = true;
hero.canJump = true;
} else if (minOverlap === overlapBottom && hero.velocityY < 0) {
// Hitting platform from below
hero.y = platformBottom + 80;
hero.velocityY = 0;
} else if (minOverlap === overlapLeft && hero.velocityX > 0) {
// Hitting platform from left side
hero.x = platformLeft - 40;
hero.velocityX = 0;
} else if (minOverlap === overlapRight && hero.velocityX < 0) {
// Hitting platform from right side
hero.x = platformRight + 40;
hero.velocityX = 0;
}
}
}
function checkEnemyCollisions() {
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (!enemy.alive) {
continue;
}
if (hero.intersects(enemy)) {
// Check if hero is jumping on enemy
if (hero.velocityY > 0 && hero.y < enemy.y - 30) {
enemy.defeat();
enemies.splice(i, 1);
hero.velocityY = -15; // Bounce
} else {
hero.takeDamage();
}
}
}
}
function checkCoinCollisions() {
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
if (!coin.collected && hero.intersects(coin)) {
coin.collect();
coins.splice(i, 1);
}
}
}
function checkGoalCollision() {
if (!goal.reached && hero.intersects(goal)) {
goal.reachGoal();
}
}
function updateCamera() {
// Camera follows hero smoothly - adjusted view area for larger screen
var targetX = hero.x - 450; // Center horizontally (2048/2 = 1024)
var targetY = hero.y - 1000; // Center vertically (2732/2 = 1366) - raised camera
// Smooth camera movement with good responsiveness
camera.x += (targetX - camera.x) * 0.1;
camera.y += (targetY - camera.y) * 0.1;
// Keep camera within level bounds - adjusted for larger view and scale factor
if (camera.x < 0) {
camera.x = 0;
}
if (camera.x > levelWidth - 1024) {
// Adjusted for 2.0 scale (2048/2 = 1024)
camera.x = levelWidth - 1024;
}
if (camera.y < -600) {
camera.y = -600;
}
if (camera.y > 350) {
camera.y = 350;
}
// Apply camera position to game world with scale factor
game.x = -camera.x * 2.0;
game.y = -camera.y * 1.0;
}
function checkBounds() {
// Check if hero fell off the world
if (hero.y > 1000) {
hero.takeDamage();
hero.x = 200;
hero.y = 600;
hero.velocityX = 0;
hero.velocityY = 0;
}
}
// Button event handlers
leftButton.down = function (x, y, obj) {
leftPressed = true;
tween(leftButton, {
scaleX: -1.2,
scaleY: 1.2
}, {
duration: 100,
easing: tween.easeOut
});
// Tilt hero to the left
tween(hero, {
rotation: -0.3
}, {
duration: 200,
easing: tween.easeOut
});
};
leftButton.up = function (x, y, obj) {
leftPressed = false;
tween(leftButton, {
scaleX: -1,
scaleY: 1
}, {
duration: 100,
easing: tween.easeOut
});
// Reset hero tilt to upright
tween(hero, {
rotation: 0
}, {
duration: 200,
easing: tween.easeOut
});
};
rightButton.down = function (x, y, obj) {
rightPressed = true;
tween(rightButton, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100,
easing: tween.easeOut
});
// Tilt hero to the right
tween(hero, {
rotation: 0.3
}, {
duration: 200,
easing: tween.easeOut
});
};
rightButton.up = function (x, y, obj) {
rightPressed = false;
tween(rightButton, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.easeOut
});
// Reset hero tilt to upright
tween(hero, {
rotation: 0
}, {
duration: 200,
easing: tween.easeOut
});
};
// Touch controls with swipe detection
game.down = function (x, y, obj) {
// Start swipe detection
swipeStartY = y;
swipeStartTime = Date.now();
isSwipeActive = true;
};
game.move = function (x, y, obj) {
// Track swipe movement but don't perform action yet
};
game.up = function (x, y, obj) {
isSwipeActive = false;
};
game.update = function () {
// FPS calculation removed for optimization
// Handle continuous button presses
if (leftPressed) {
hero.moveLeft();
}
if (rightPressed) {
hero.moveRight();
}
// Handle continuous jump - jump again when landing if button is still held
if (jumpPressed && hero.onGround && hero.canJump) {
hero.jump();
}
// Create trail when hero is moving on ground
var isActuallyOnGround = false;
// Cache hero bounds for optimization
var heroLeft = hero.x - 40;
var heroRight = hero.x + 40;
var heroBottom = hero.y;
// Check if hero is actually touching any platform or ground
for (var p = 0; p < platforms.length; p++) {
var platform = platforms[p];
if (heroRight > platform.x && heroLeft < platform.x + platform.platformWidth) {
if (Math.abs(heroBottom - platform.y) < 5) {
isActuallyOnGround = true;
break;
}
}
}
// Check ground collision
if (!isActuallyOnGround) {
if (heroRight > ground.x && heroLeft < ground.x + ground.platformWidth) {
if (Math.abs(heroBottom - ground.y) < 5) {
isActuallyOnGround = true;
}
}
}
if (isActuallyOnGround && (leftPressed || rightPressed)) {
trailTimer++;
if (trailTimer >= trailFrequency) {
var trailPiece = game.addChild(LK.getAsset('trail', {
anchorX: 0.5,
anchorY: 0.5
}));
trailPiece.x = hero.x;
trailPiece.y = hero.y - 1 + (Math.random() - 0.5) * 10; // Slightly above ground with height variation
trailPiece.fadeTimer = 500; // 0.5 seconds in milliseconds
trail.push(trailPiece);
trailTimer = 10;
}
}
// Check for floating trail pieces and remove them, also handle fade timer
for (var t = trail.length - 1; t >= 0; t--) {
var trailPiece = trail[t];
// Decrease fade timer
trailPiece.fadeTimer -= 16.67; // Approximately 1 frame at 60fps (1000ms/60fps)
// Check if fade timer expired
if (trailPiece.fadeTimer <= 0) {
// Start fade out effect
tween(trailPiece, {
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
trailPiece.destroy();
}
});
trail.splice(t, 1);
continue;
}
// Cache trail piece bounds for optimization
var trailLeft = trailPiece.x - 17.5;
var trailRight = trailPiece.x + 17.5;
var trailBottom = trailPiece.y + 7.5;
var trailOnGround = false;
// Check if trail piece is on any platform
for (var p = 0; p < platforms.length; p++) {
var platform = platforms[p];
if (trailRight > platform.x && trailLeft < platform.x + platform.platformWidth) {
if (Math.abs(trailBottom - platform.y) < 10) {
trailOnGround = true;
break;
}
}
}
// Check if trail piece is on ground
if (!trailOnGround) {
if (trailRight > ground.x && trailLeft < ground.x + ground.platformWidth) {
if (Math.abs(trailBottom - ground.y) < 10) {
trailOnGround = true;
}
}
}
// Remove trail piece if it's floating
if (!trailOnGround) {
trailPiece.destroy();
trail.splice(t, 1);
}
}
checkPlatformCollisions();
checkEnemyCollisions();
checkCoinCollisions();
checkGoalCollision();
checkBounds();
updateCamera();
// Update position display
positionText.setText('X: ' + Math.round(hero.x) + ' Y: ' + Math.round(hero.y));
};
// Initialize level
createLevel();
// Scale game up to increase screen size
tween(game, {
scaleX: 2.0,
scaleY: 2.0
}, {
duration: 1000,
easing: tween.easeInOut
});
colocale la boca sonriendo, mostrando los dientes blancos
SUELO 2D DE METAL ESTILO CARTOON. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
HAZLO COMPLETAMENTE CUADRADO, ESQUINAZ RECTAS
dale un toque moderno, con sombras y reflejos, y reduce un poco el tamaño
COFRE DEL TESORO ESTILO CARTOON. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Quita la figura del centro y remplazala por un circulo con un borde no muy grueso
Dale un estilo cartoon y quítale el símbolo del centro
dibuja bien la cola, colocale los bigotes en zigzag
RATA MUTANTE MUSCULOZA, ESTILO CARTOON, JEFE FINAL. In-Game asset. 2d. High contrast. No shadows