User prompt
When you jump on the platform we were born on, let it stay on it
User prompt
When she jumps she can stand on the platform
User prompt
Let the character jump on his own
User prompt
May we stand on the platform on which we were born in the first place
User prompt
Dies 2 seconds after falling
User prompt
The character should be able to stand on platforms and not fall down.
User prompt
to stand on the platform and not fall down
Code edit (1 edits merged)
Please save this source code
User prompt
Sky Hopper
Initial prompt
Make me a game like doodle jump
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.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.update = function () {
// Simple rotation animation
coinGraphics.rotation += 0.1;
// Bob up and down slightly
self.y += Math.sin(LK.ticks * 0.1) * 0.5;
};
self.collect = function () {
if (!self.collected) {
self.collected = true;
// Add coins to storage
var currentCoins = storage.coins || 0;
storage.coins = currentCoins + 1;
// Play sound
LK.getSound('coin').play();
// Animate collection
tween(self, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
}
};
return self;
});
var Platform = Container.expand(function (type) {
var self = Container.call(this);
self.platformType = type || 'normal';
var assetName = 'platform';
if (self.platformType === 'moving') {
assetName = 'movingPlatform';
} else if (self.platformType === 'bounce') {
assetName = 'bouncePlatform';
} else if (self.platformType === 'trap') {
assetName = 'trapPlatform';
}
var platformGraphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.moveDirection = 1;
self.moveSpeed = 2;
self.isTrapped = false;
self.trapTimer = 0;
self.update = function () {
if (self.platformType === 'moving') {
self.x += self.moveDirection * self.moveSpeed;
if (self.x <= 100 || self.x >= 1948) {
self.moveDirection *= -1;
}
} else if (self.platformType === 'trap' && self.isTrapped) {
self.trapTimer++;
if (self.trapTimer >= 60) {
// 1 second at 60 FPS
self.destroy();
// Remove from platforms array
for (var i = platforms.length - 1; i >= 0; i--) {
if (platforms[i] === self) {
platforms.splice(i, 1);
break;
}
}
}
}
};
self.getBounceForce = function () {
if (self.platformType === 'bounce') {
return -25;
}
return -18;
};
self.activateTrap = function () {
if (self.platformType === 'trap' && !self.isTrapped) {
self.isTrapped = true;
self.trapTimer = 0;
// Make platform semi-transparent to show it's breaking
tween(self, {
alpha: 0.3
}, {
duration: 1000
});
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.isOnPlatform = false;
self.lastY = 0;
self.jumpsUsed = 0; // Track number of jumps used while airborne
self.maxJumps = 2; // Maximum jumps allowed while in air
self.isFallingToDeath = false; // Track if player is falling to death
self.update = function () {
// Store last position for collision detection
self.lastY = self.y;
// Store current platform if on one
var currentPlatform = null;
if (self.isOnPlatform) {
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var playerLeft = self.x - 40;
var playerRight = self.x + 40;
var platformLeft = platform.x - 100;
var platformRight = platform.x + 100;
var playerBottom = self.y + 40;
var platformTop = platform.y - 10;
if (Math.abs(playerBottom - platformTop) <= 5 && playerRight > platformLeft && playerLeft < platformRight) {
currentPlatform = platform;
break;
}
}
}
// Apply horizontal movement
self.x += self.velocityX;
// If on a moving platform, move with it
if (currentPlatform && currentPlatform.platformType === 'moving') {
self.x += currentPlatform.moveDirection * currentPlatform.moveSpeed;
}
// Apply gravity when not on platform
if (!self.isOnPlatform) {
self.velocityY += 0.6; // Reduced gravity for higher jumps
} else {
// When on platform, gradually reduce velocities
self.velocityY = Math.max(0, self.velocityY);
}
self.y += self.velocityY;
// Apply friction to horizontal movement
self.velocityX *= 0.95;
// Wrap player horizontally from right to left
if (self.x < 40) {
self.x = 2008; // Wrap to right side
}
if (self.x > 2008) {
self.x = 40; // Wrap to left side
}
};
self.bounce = function (bounceForce) {
self.velocityY = bounceForce || -18;
self.isOnPlatform = true; // Set to true initially, will be updated in next frame
self.jumpsUsed = 0; // Reset jump counter when landing
self.isFallingToDeath = false; // Reset falling to death state when bouncing
LK.getSound('bounce').play();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
var player;
var platforms = [];
var coins = [];
var cameraY = 0;
var nextPlatformY = 2500;
var highestY = 2732;
var gameStarted = false;
var fallStartTime = null;
var isFalling = false;
// Initialize height display
var heightTxt = new Text2('Height: 0m', {
size: 60,
fill: 0xFFD700
});
heightTxt.anchor.set(0, 0);
heightTxt.x = 120; // Position away from platform menu icon
heightTxt.y = 20;
LK.gui.topLeft.addChild(heightTxt);
// Initialize coins display
var pointsTxt = new Text2('Coins: 0', {
size: 60,
fill: 0xFFD700
});
pointsTxt.anchor.set(1, 0);
pointsTxt.y = 20;
LK.gui.topRight.addChild(pointsTxt);
// Initialize score display
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFD700
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.y = 20;
LK.gui.top.addChild(scoreTxt);
// Create player
player = game.addChild(new Player());
player.x = 1024;
player.y = 2560; // Position player on top of the starting platform (2600 - 40 = 2560)
player.isOnPlatform = true; // Start on platform
// Create coin function
function createCoin(x, y) {
var coin = new Coin();
coin.x = x;
coin.y = y;
coins.push(coin);
game.addChild(coin);
return coin;
}
// Create initial platforms
function createPlatform(x, y, type) {
var platform = new Platform(type);
platform.x = x;
platform.y = y;
platforms.push(platform);
game.addChild(platform);
// 30% chance to add a coin on normal platforms (not on trap platforms)
if (type !== 'trap' && Math.random() < 0.3) {
createCoin(x, y - 40); // Position coin above platform
}
return platform;
}
// Generate initial platforms
var startingPlatform = createPlatform(1024, 2600, 'normal');
startingPlatform.isStartingPlatform = true;
for (var i = 0; i < 15; i++) {
var x = Math.random() * 1600 + 200;
var y = nextPlatformY - Math.random() * 200 - 150; // Increased vertical spacing between platforms
var platformType = 'normal';
if (Math.random() < 0.2) {
platformType = 'moving';
} else if (Math.random() < 0.1) {
platformType = 'bounce';
} else if (Math.random() < 0.15) {
platformType = 'trap';
}
createPlatform(x, y, platformType);
nextPlatformY = y;
}
function generateNewPlatforms() {
while (nextPlatformY > cameraY - 1000) {
var x = Math.random() * 1600 + 200;
var y = nextPlatformY - Math.random() * 250 - 180; // Increased spacing for more challenging platform jumping
var platformType = 'normal';
var random = Math.random();
if (random < 0.25) {
platformType = 'moving';
} else if (random < 0.15) {
platformType = 'bounce';
} else if (random < 0.2) {
platformType = 'trap';
}
createPlatform(x, y, platformType);
nextPlatformY = y;
}
}
function updateCamera() {
var targetCameraY = player.y - 1800;
if (targetCameraY < cameraY) {
cameraY = targetCameraY;
}
game.y = -cameraY;
}
function updateScore() {
if (player.y < highestY) {
highestY = player.y;
var score = Math.floor((2732 - highestY) / 10);
LK.setScore(score);
scoreTxt.setText('Score: ' + score);
var height = Math.floor(score / 10);
heightTxt.setText('Height: ' + height + 'm');
}
}
function checkPlatformCollisions() {
// Don't check collisions if player is falling to death
if (player.isFallingToDeath) {
return;
}
// Check for platform collision when falling
if (player.velocityY > 0) {
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var playerBottom = player.y + 40;
var platformTop = platform.y - 10;
var playerLeft = player.x - 40;
var playerRight = player.x + 40;
var platformLeft = platform.x - 100;
var platformRight = platform.x + 100;
// Check if player is landing on platform from above
if (playerBottom >= platformTop && playerBottom <= platformTop + 25 && playerRight > platformLeft && playerLeft < platformRight && player.lastY + 40 <= platformTop) {
// Check if this is a trap platform
if (platform.platformType === 'trap' && !platform.isTrapped) {
platform.activateTrap();
// Player falls through trap platform - don't land on it
player.isFallingToDeath = true; // Start falling to death
return;
}
// Don't land on already trapped platforms
if (platform.platformType === 'trap' && platform.isTrapped) {
player.isFallingToDeath = true; // Start falling to death
return;
}
player.y = platformTop - 40;
player.isOnPlatform = true;
player.velocityY = 0; // Stop falling, prepare for immediate auto-jump
player.jumpsUsed = 0; // Reset jump counter when landing
player.isFallingToDeath = false; // Reset falling to death state
// Only bounce on bounce platforms
if (platform.platformType === 'bounce') {
player.bounce(platform.getBounceForce());
}
return;
}
}
}
// Check if player is still on a platform (for standing)
if (player.velocityY >= 0 && !player.isFallingToDeath) {
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var playerBottom = player.y + 40;
var platformTop = platform.y - 10;
var playerLeft = player.x - 40;
var playerRight = player.x + 40;
var platformLeft = platform.x - 100;
var platformRight = platform.x + 100;
// Check if player is standing on platform
if (Math.abs(playerBottom - platformTop) <= 5 && playerRight > platformLeft && playerLeft < platformRight) {
// Don't stand on trapped platforms
if (platform.platformType === 'trap' && platform.isTrapped) {
player.isFallingToDeath = true; // Start falling to death
return;
}
player.y = platformTop - 40;
player.isOnPlatform = true;
player.jumpsUsed = 0; // Reset jump counter when on platform
player.isFallingToDeath = false; // Reset falling to death state
// For starting platform, ensure player can stay indefinitely
if (platform.isStartingPlatform) {
player.velocityY = 0; // Completely stop vertical movement on starting platform
} else {
player.velocityY = Math.max(0, player.velocityY); // Prevent falling through
}
return;
}
}
}
// If no platform found, player is not on platform
player.isOnPlatform = false;
}
function checkCoinCollisions() {
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
if (coin.collected) continue;
var playerLeft = player.x - 40;
var playerRight = player.x + 40;
var playerTop = player.y - 40;
var playerBottom = player.y + 40;
var coinLeft = coin.x - 20;
var coinRight = coin.x + 20;
var coinTop = coin.y - 20;
var coinBottom = coin.y + 20;
// Check collision
if (playerRight > coinLeft && playerLeft < coinRight && playerBottom > coinTop && playerTop < coinBottom) {
coin.collect();
coins.splice(i, 1);
}
}
}
function updatePointsDisplay() {
var currentCoins = storage.coins || 0;
pointsTxt.setText('Coins: ' + currentCoins);
}
function cleanupCoins() {
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
if (coin.y > cameraY + 3000) {
coin.destroy();
coins.splice(i, 1);
}
}
}
function cleanupPlatforms() {
for (var i = platforms.length - 1; i >= 0; i--) {
var platform = platforms[i];
if (platform.y > cameraY + 3000) {
platform.destroy();
platforms.splice(i, 1);
}
}
}
function handleInput() {
// Input handling now done through click events
}
// Game controls - jump toward clicked position
game.down = function (x, y, obj) {
gameStarted = true;
// Check if player has jumps remaining
if (player.jumpsUsed >= player.maxJumps) {
return; // Cannot jump anymore
}
// Calculate direction toward clicked position
var deltaX = x - player.x;
var deltaY = y - player.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
// Normalize direction and apply jump force
if (distance > 0) {
var jumpForce = 22; // Increased jump force for higher jumps
var horizontalForce = deltaX / distance * jumpForce * 0.8; // Reduced horizontal component
var verticalForce = Math.min(-18, deltaY / distance * jumpForce); // Increased vertical force for higher jumps
player.velocityX = horizontalForce;
player.velocityY = verticalForce;
player.isOnPlatform = false;
player.jumpsUsed++; // Increment jump counter
LK.getSound('bounce').play();
// Removed scaling animation during jumps
}
};
game.up = function (x, y, obj) {
// No longer needed for directional movement
};
// Main game loop
game.update = function () {
if (!gameStarted) return;
handleInput();
checkPlatformCollisions();
checkCoinCollisions();
updateCamera();
updateScore();
updatePointsDisplay();
generateNewPlatforms();
cleanupPlatforms();
cleanupCoins();
// Track falling state
var wasOnPlatform = player.isOnPlatform;
var currentlyFalling = player.velocityY > 0 && !player.isOnPlatform;
// Start fall timer when player starts falling
if (!isFalling && currentlyFalling) {
isFalling = true;
fallStartTime = LK.ticks;
}
// Reset fall timer when player lands or bounces up
if (isFalling && (!currentlyFalling || player.velocityY < 0)) {
isFalling = false;
fallStartTime = null;
}
// Check for 2-second fall timer (120 ticks = 2 seconds at 60 FPS)
if (isFalling && fallStartTime !== null && LK.ticks - fallStartTime >= 120) {
LK.getSound('fall').play();
LK.showGameOver();
}
// Check for game over (player falls too far below camera)
if (player.y > cameraY + 2900) {
LK.getSound('fall').play();
LK.showGameOver();
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.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.update = function () {
// Simple rotation animation
coinGraphics.rotation += 0.1;
// Bob up and down slightly
self.y += Math.sin(LK.ticks * 0.1) * 0.5;
};
self.collect = function () {
if (!self.collected) {
self.collected = true;
// Add coins to storage
var currentCoins = storage.coins || 0;
storage.coins = currentCoins + 1;
// Play sound
LK.getSound('coin').play();
// Animate collection
tween(self, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
}
};
return self;
});
var Platform = Container.expand(function (type) {
var self = Container.call(this);
self.platformType = type || 'normal';
var assetName = 'platform';
if (self.platformType === 'moving') {
assetName = 'movingPlatform';
} else if (self.platformType === 'bounce') {
assetName = 'bouncePlatform';
} else if (self.platformType === 'trap') {
assetName = 'trapPlatform';
}
var platformGraphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.moveDirection = 1;
self.moveSpeed = 2;
self.isTrapped = false;
self.trapTimer = 0;
self.update = function () {
if (self.platformType === 'moving') {
self.x += self.moveDirection * self.moveSpeed;
if (self.x <= 100 || self.x >= 1948) {
self.moveDirection *= -1;
}
} else if (self.platformType === 'trap' && self.isTrapped) {
self.trapTimer++;
if (self.trapTimer >= 60) {
// 1 second at 60 FPS
self.destroy();
// Remove from platforms array
for (var i = platforms.length - 1; i >= 0; i--) {
if (platforms[i] === self) {
platforms.splice(i, 1);
break;
}
}
}
}
};
self.getBounceForce = function () {
if (self.platformType === 'bounce') {
return -25;
}
return -18;
};
self.activateTrap = function () {
if (self.platformType === 'trap' && !self.isTrapped) {
self.isTrapped = true;
self.trapTimer = 0;
// Make platform semi-transparent to show it's breaking
tween(self, {
alpha: 0.3
}, {
duration: 1000
});
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.isOnPlatform = false;
self.lastY = 0;
self.jumpsUsed = 0; // Track number of jumps used while airborne
self.maxJumps = 2; // Maximum jumps allowed while in air
self.isFallingToDeath = false; // Track if player is falling to death
self.update = function () {
// Store last position for collision detection
self.lastY = self.y;
// Store current platform if on one
var currentPlatform = null;
if (self.isOnPlatform) {
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var playerLeft = self.x - 40;
var playerRight = self.x + 40;
var platformLeft = platform.x - 100;
var platformRight = platform.x + 100;
var playerBottom = self.y + 40;
var platformTop = platform.y - 10;
if (Math.abs(playerBottom - platformTop) <= 5 && playerRight > platformLeft && playerLeft < platformRight) {
currentPlatform = platform;
break;
}
}
}
// Apply horizontal movement
self.x += self.velocityX;
// If on a moving platform, move with it
if (currentPlatform && currentPlatform.platformType === 'moving') {
self.x += currentPlatform.moveDirection * currentPlatform.moveSpeed;
}
// Apply gravity when not on platform
if (!self.isOnPlatform) {
self.velocityY += 0.6; // Reduced gravity for higher jumps
} else {
// When on platform, gradually reduce velocities
self.velocityY = Math.max(0, self.velocityY);
}
self.y += self.velocityY;
// Apply friction to horizontal movement
self.velocityX *= 0.95;
// Wrap player horizontally from right to left
if (self.x < 40) {
self.x = 2008; // Wrap to right side
}
if (self.x > 2008) {
self.x = 40; // Wrap to left side
}
};
self.bounce = function (bounceForce) {
self.velocityY = bounceForce || -18;
self.isOnPlatform = true; // Set to true initially, will be updated in next frame
self.jumpsUsed = 0; // Reset jump counter when landing
self.isFallingToDeath = false; // Reset falling to death state when bouncing
LK.getSound('bounce').play();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
var player;
var platforms = [];
var coins = [];
var cameraY = 0;
var nextPlatformY = 2500;
var highestY = 2732;
var gameStarted = false;
var fallStartTime = null;
var isFalling = false;
// Initialize height display
var heightTxt = new Text2('Height: 0m', {
size: 60,
fill: 0xFFD700
});
heightTxt.anchor.set(0, 0);
heightTxt.x = 120; // Position away from platform menu icon
heightTxt.y = 20;
LK.gui.topLeft.addChild(heightTxt);
// Initialize coins display
var pointsTxt = new Text2('Coins: 0', {
size: 60,
fill: 0xFFD700
});
pointsTxt.anchor.set(1, 0);
pointsTxt.y = 20;
LK.gui.topRight.addChild(pointsTxt);
// Initialize score display
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFD700
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.y = 20;
LK.gui.top.addChild(scoreTxt);
// Create player
player = game.addChild(new Player());
player.x = 1024;
player.y = 2560; // Position player on top of the starting platform (2600 - 40 = 2560)
player.isOnPlatform = true; // Start on platform
// Create coin function
function createCoin(x, y) {
var coin = new Coin();
coin.x = x;
coin.y = y;
coins.push(coin);
game.addChild(coin);
return coin;
}
// Create initial platforms
function createPlatform(x, y, type) {
var platform = new Platform(type);
platform.x = x;
platform.y = y;
platforms.push(platform);
game.addChild(platform);
// 30% chance to add a coin on normal platforms (not on trap platforms)
if (type !== 'trap' && Math.random() < 0.3) {
createCoin(x, y - 40); // Position coin above platform
}
return platform;
}
// Generate initial platforms
var startingPlatform = createPlatform(1024, 2600, 'normal');
startingPlatform.isStartingPlatform = true;
for (var i = 0; i < 15; i++) {
var x = Math.random() * 1600 + 200;
var y = nextPlatformY - Math.random() * 200 - 150; // Increased vertical spacing between platforms
var platformType = 'normal';
if (Math.random() < 0.2) {
platformType = 'moving';
} else if (Math.random() < 0.1) {
platformType = 'bounce';
} else if (Math.random() < 0.15) {
platformType = 'trap';
}
createPlatform(x, y, platformType);
nextPlatformY = y;
}
function generateNewPlatforms() {
while (nextPlatformY > cameraY - 1000) {
var x = Math.random() * 1600 + 200;
var y = nextPlatformY - Math.random() * 250 - 180; // Increased spacing for more challenging platform jumping
var platformType = 'normal';
var random = Math.random();
if (random < 0.25) {
platformType = 'moving';
} else if (random < 0.15) {
platformType = 'bounce';
} else if (random < 0.2) {
platformType = 'trap';
}
createPlatform(x, y, platformType);
nextPlatformY = y;
}
}
function updateCamera() {
var targetCameraY = player.y - 1800;
if (targetCameraY < cameraY) {
cameraY = targetCameraY;
}
game.y = -cameraY;
}
function updateScore() {
if (player.y < highestY) {
highestY = player.y;
var score = Math.floor((2732 - highestY) / 10);
LK.setScore(score);
scoreTxt.setText('Score: ' + score);
var height = Math.floor(score / 10);
heightTxt.setText('Height: ' + height + 'm');
}
}
function checkPlatformCollisions() {
// Don't check collisions if player is falling to death
if (player.isFallingToDeath) {
return;
}
// Check for platform collision when falling
if (player.velocityY > 0) {
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var playerBottom = player.y + 40;
var platformTop = platform.y - 10;
var playerLeft = player.x - 40;
var playerRight = player.x + 40;
var platformLeft = platform.x - 100;
var platformRight = platform.x + 100;
// Check if player is landing on platform from above
if (playerBottom >= platformTop && playerBottom <= platformTop + 25 && playerRight > platformLeft && playerLeft < platformRight && player.lastY + 40 <= platformTop) {
// Check if this is a trap platform
if (platform.platformType === 'trap' && !platform.isTrapped) {
platform.activateTrap();
// Player falls through trap platform - don't land on it
player.isFallingToDeath = true; // Start falling to death
return;
}
// Don't land on already trapped platforms
if (platform.platformType === 'trap' && platform.isTrapped) {
player.isFallingToDeath = true; // Start falling to death
return;
}
player.y = platformTop - 40;
player.isOnPlatform = true;
player.velocityY = 0; // Stop falling, prepare for immediate auto-jump
player.jumpsUsed = 0; // Reset jump counter when landing
player.isFallingToDeath = false; // Reset falling to death state
// Only bounce on bounce platforms
if (platform.platformType === 'bounce') {
player.bounce(platform.getBounceForce());
}
return;
}
}
}
// Check if player is still on a platform (for standing)
if (player.velocityY >= 0 && !player.isFallingToDeath) {
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var playerBottom = player.y + 40;
var platformTop = platform.y - 10;
var playerLeft = player.x - 40;
var playerRight = player.x + 40;
var platformLeft = platform.x - 100;
var platformRight = platform.x + 100;
// Check if player is standing on platform
if (Math.abs(playerBottom - platformTop) <= 5 && playerRight > platformLeft && playerLeft < platformRight) {
// Don't stand on trapped platforms
if (platform.platformType === 'trap' && platform.isTrapped) {
player.isFallingToDeath = true; // Start falling to death
return;
}
player.y = platformTop - 40;
player.isOnPlatform = true;
player.jumpsUsed = 0; // Reset jump counter when on platform
player.isFallingToDeath = false; // Reset falling to death state
// For starting platform, ensure player can stay indefinitely
if (platform.isStartingPlatform) {
player.velocityY = 0; // Completely stop vertical movement on starting platform
} else {
player.velocityY = Math.max(0, player.velocityY); // Prevent falling through
}
return;
}
}
}
// If no platform found, player is not on platform
player.isOnPlatform = false;
}
function checkCoinCollisions() {
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
if (coin.collected) continue;
var playerLeft = player.x - 40;
var playerRight = player.x + 40;
var playerTop = player.y - 40;
var playerBottom = player.y + 40;
var coinLeft = coin.x - 20;
var coinRight = coin.x + 20;
var coinTop = coin.y - 20;
var coinBottom = coin.y + 20;
// Check collision
if (playerRight > coinLeft && playerLeft < coinRight && playerBottom > coinTop && playerTop < coinBottom) {
coin.collect();
coins.splice(i, 1);
}
}
}
function updatePointsDisplay() {
var currentCoins = storage.coins || 0;
pointsTxt.setText('Coins: ' + currentCoins);
}
function cleanupCoins() {
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
if (coin.y > cameraY + 3000) {
coin.destroy();
coins.splice(i, 1);
}
}
}
function cleanupPlatforms() {
for (var i = platforms.length - 1; i >= 0; i--) {
var platform = platforms[i];
if (platform.y > cameraY + 3000) {
platform.destroy();
platforms.splice(i, 1);
}
}
}
function handleInput() {
// Input handling now done through click events
}
// Game controls - jump toward clicked position
game.down = function (x, y, obj) {
gameStarted = true;
// Check if player has jumps remaining
if (player.jumpsUsed >= player.maxJumps) {
return; // Cannot jump anymore
}
// Calculate direction toward clicked position
var deltaX = x - player.x;
var deltaY = y - player.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
// Normalize direction and apply jump force
if (distance > 0) {
var jumpForce = 22; // Increased jump force for higher jumps
var horizontalForce = deltaX / distance * jumpForce * 0.8; // Reduced horizontal component
var verticalForce = Math.min(-18, deltaY / distance * jumpForce); // Increased vertical force for higher jumps
player.velocityX = horizontalForce;
player.velocityY = verticalForce;
player.isOnPlatform = false;
player.jumpsUsed++; // Increment jump counter
LK.getSound('bounce').play();
// Removed scaling animation during jumps
}
};
game.up = function (x, y, obj) {
// No longer needed for directional movement
};
// Main game loop
game.update = function () {
if (!gameStarted) return;
handleInput();
checkPlatformCollisions();
checkCoinCollisions();
updateCamera();
updateScore();
updatePointsDisplay();
generateNewPlatforms();
cleanupPlatforms();
cleanupCoins();
// Track falling state
var wasOnPlatform = player.isOnPlatform;
var currentlyFalling = player.velocityY > 0 && !player.isOnPlatform;
// Start fall timer when player starts falling
if (!isFalling && currentlyFalling) {
isFalling = true;
fallStartTime = LK.ticks;
}
// Reset fall timer when player lands or bounces up
if (isFalling && (!currentlyFalling || player.velocityY < 0)) {
isFalling = false;
fallStartTime = null;
}
// Check for 2-second fall timer (120 ticks = 2 seconds at 60 FPS)
if (isFalling && fallStartTime !== null && LK.ticks - fallStartTime >= 120) {
LK.getSound('fall').play();
LK.showGameOver();
}
// Check for game over (player falls too far below camera)
if (player.y > cameraY + 2900) {
LK.getSound('fall').play();
LK.showGameOver();
}
};