/****
* 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 = 5000;
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: 3850,
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 = 4500;
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
}); ===================================================================
--- original.js
+++ change.js
@@ -696,8 +696,11 @@
y: 200
}, {
x: 3350,
y: 200
+ }, {
+ x: 3850,
+ y: 300
}];
totalCoins = coinPositions.length;
for (var k = 0; k < coinPositions.length; k++) {
var coinPos = coinPositions[k];
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