/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Obstacle class: static obstacle (box or ellipse)
var Obstacle = Container.expand(function () {
var self = Container.call(this);
// Attach obstacle asset (ellipse shape)
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Platform class: static or moving platform
var Platform = Container.expand(function () {
var self = Container.call(this);
// Attach platform asset (box shape)
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
// Platform movement properties
self.isMoving = false;
self.moveDir = 1; // 1: right, -1: left
self.moveRange = 0; // in px
self.moveSpeed = 0; // px per frame
self.startX = 0;
// Called every tick
self.update = function () {
if (self.isMoving) {
self.x += self.moveDir * self.moveSpeed;
if (Math.abs(self.x - self.startX) > self.moveRange) {
self.moveDir *= -1;
}
}
};
return self;
});
// Player class
var Player = Container.expand(function () {
var self = Container.call(this);
// Attach player asset (box shape)
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// Physics properties
self.vx = 0;
self.vy = 0;
self.isOnGround = false;
self.width = playerGraphics.width;
self.height = playerGraphics.height;
// Jump method
self.jump = function () {
if (self.isOnGround) {
self.vy = -jumpStrength;
self.isOnGround = false;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222244
});
/****
* Game Code
****/
// --- Asset Initialization ---
// --- Game Constants ---
var GRAVITY = 2.2;
var MOVE_SPEED = 22;
var jumpStrength = 48;
var PLATFORM_MIN_WIDTH = 220;
var PLATFORM_MAX_WIDTH = 420;
var PLATFORM_HEIGHT = 40;
var PLATFORM_GAP_MIN = 220;
var PLATFORM_GAP_MAX = 420;
var PLATFORM_MOVE_CHANCE = 0.25;
var PLATFORM_MOVE_RANGE = 320;
var PLATFORM_MOVE_SPEED = 4;
var OBSTACLE_CHANCE = 0.25;
var OBSTACLE_SIZE = 80;
var PLAYER_START_X = 2048 / 2;
var PLAYER_START_Y = 2732 - 400;
var CAMERA_OFFSET = 900; // How far from bottom the player is kept
// --- Game State ---
var player;
var platforms = [];
var obstacles = [];
var maxHeight = 0; // Highest Y the player has reached (lower y = higher)
var dragStartX = null;
var dragStartY = null;
var dragLastX = null;
var dragLastY = null;
var isDragging = false;
var scoreTxt;
var lastPlatformY = 0;
var cameraY = 0;
var gameOver = false;
// --- Decorative White Dots ---
var whiteDots = [];
var WHITE_DOT_COUNT = 40; // Number of dots
// --- GUI ---
scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// --- Helper Functions ---
// Generate a new platform at (x, y), optionally moving
function createPlatform(x, y, width, isMoving) {
var plat = new Platform();
plat.x = x;
plat.y = y;
plat.width = width;
plat.height = PLATFORM_HEIGHT;
plat.getChildAt(0).width = width;
plat.getChildAt(0).height = PLATFORM_HEIGHT;
plat.isMoving = isMoving;
plat.moveRange = isMoving ? PLATFORM_MOVE_RANGE : 0;
plat.moveSpeed = isMoving ? PLATFORM_MOVE_SPEED : 0;
plat.startX = x;
game.addChild(plat);
platforms.push(plat);
return plat;
}
// Generate a new obstacle on a platform
function createObstacle(x, y) {
var obs = new Obstacle();
obs.x = x;
obs.y = y - OBSTACLE_SIZE / 2 - 10;
obs.width = OBSTACLE_SIZE;
obs.height = OBSTACLE_SIZE;
obs.getChildAt(0).width = OBSTACLE_SIZE;
obs.getChildAt(0).height = OBSTACLE_SIZE;
game.addChild(obs);
obstacles.push(obs);
return obs;
}
// Remove platforms/obstacles below camera
function cleanupPlatformsObstacles() {
for (var i = platforms.length - 1; i >= 0; i--) {
if (platforms[i].y - cameraY > 2732 + 200) {
platforms[i].destroy();
platforms.splice(i, 1);
}
}
for (var j = obstacles.length - 1; j >= 0; j--) {
if (obstacles[j].y - cameraY > 2732 + 200) {
obstacles[j].destroy();
obstacles.splice(j, 1);
}
}
}
// Generate platforms up to a certain Y
function generatePlatformsUpTo(minY) {
while (lastPlatformY > minY) {
var gap = PLATFORM_GAP_MIN + Math.random() * (PLATFORM_GAP_MAX - PLATFORM_GAP_MIN);
var platY = lastPlatformY - gap;
var platWidth = PLATFORM_MIN_WIDTH + Math.random() * (PLATFORM_MAX_WIDTH - PLATFORM_MIN_WIDTH);
var platX = platWidth / 2 + Math.random() * (2048 - platWidth);
var isMoving = Math.random() < PLATFORM_MOVE_CHANCE;
var plat = createPlatform(platX, platY, platWidth, isMoving);
// Maybe add obstacle
if (Math.random() < OBSTACLE_CHANCE && platWidth > 200 + OBSTACLE_SIZE) {
var obsX = plat.x + (Math.random() - 0.5) * (platWidth - OBSTACLE_SIZE - 40);
createObstacle(obsX, platY);
}
lastPlatformY = platY;
}
}
// Reset game state
function resetGame() {
// Remove old objects
for (var i = 0; i < platforms.length; i++) platforms[i].destroy();
for (var j = 0; j < obstacles.length; j++) obstacles[j].destroy();
for (var d = 0; d < whiteDots.length; d++) whiteDots[d].destroy && whiteDots[d].destroy();
platforms = [];
obstacles = [];
whiteDots = [];
cameraY = 0;
lastPlatformY = PLAYER_START_Y + 120;
maxHeight = PLAYER_START_Y;
LK.setScore(0);
scoreTxt.setText('0');
gameOver = false;
// Reset background color to original
game.setBackgroundColor(0x222244);
// Create random white dots (decorative, do not affect gameplay)
for (var i = 0; i < WHITE_DOT_COUNT; i++) {
var dotSize = 8 + Math.random() * 22; // 8-30 px
var dotX = 40 + Math.random() * (2048 - 80);
var dotY = Math.random() * (2732 - 80);
var dot = LK.getAsset('whiteDot', {
width: dotSize,
height: dotSize,
color: 0xffffff,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
x: dotX,
y: dotY
});
game.addChild(dot);
whiteDots.push(dot);
}
// Create player
if (player) player.destroy();
player = new Player();
player.x = PLAYER_START_X;
player.y = PLAYER_START_Y;
player.vx = 0;
player.vy = 0;
player.isOnGround = false;
game.addChild(player);
// Create starting platform
createPlatform(PLAYER_START_X, PLAYER_START_Y + 80, 420, false);
// Generate initial platforms
generatePlatformsUpTo(PLAYER_START_Y - 2000);
}
// --- Input Handling ---
// Touch/drag to move player left/right, tap to jump
game.down = function (x, y, obj) {
if (gameOver) return;
dragStartX = x;
dragStartY = y;
dragLastX = x;
dragLastY = y;
isDragging = true;
};
game.move = function (x, y, obj) {
if (gameOver) return;
if (!isDragging) return;
var dx = x - dragLastX;
dragLastX = x;
dragLastY = y;
// Move player horizontally
player.x += dx * 1.2;
if (player.x < player.width / 2) player.x = player.width / 2;
if (player.x > 2048 - player.width / 2) player.x = 2048 - player.width / 2;
};
game.up = function (x, y, obj) {
if (gameOver) return;
isDragging = false;
// If tap (not drag), jump
if (Math.abs(x - dragStartX) < 30 && Math.abs(y - dragStartY) < 30) {
player.jump();
}
};
// --- Main Game Loop ---
game.update = function () {
if (gameOver) return;
// --- Player Physics ---
player.vy += GRAVITY;
player.y += player.vy;
player.x += player.vx;
// Clamp player to screen
if (player.x < player.width / 2) player.x = player.width / 2;
if (player.x > 2048 - player.width / 2) player.x = 2048 - player.width / 2;
// --- Platform Collision ---
player.isOnGround = false;
for (var i = 0; i < platforms.length; i++) {
var plat = platforms[i];
// Only check collision if falling
if (player.vy >= 0) {
var px = player.x;
var py = player.y + player.height / 2;
var platLeft = plat.x - plat.width / 2;
var platRight = plat.x + plat.width / 2;
var platTop = plat.y - plat.height / 2;
var platBottom = plat.y + plat.height / 2;
if (px > platLeft + 10 && px < platRight - 10 && py > platTop && py < platTop + 40 && player.y < plat.y) {
// Landed on platform
player.y = platTop - player.height / 2 + 1;
player.vy = 0;
player.isOnGround = true;
}
}
}
// --- Obstacle Collision ---
for (var j = 0; j < obstacles.length; j++) {
var obs = obstacles[j];
// Simple circle-rect collision
var dx = Math.abs(player.x - obs.x);
var dy = Math.abs(player.y - obs.y);
if (dx < player.width / 2 + OBSTACLE_SIZE / 2 - 10 && dy < player.height / 2 + OBSTACLE_SIZE / 2 - 10) {
// Hit obstacle
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
LK.showGameOver();
return;
}
}
// --- Fall Off Screen ---
if (player.y - cameraY > 2732 + 100) {
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
LK.showGameOver();
return;
}
// --- Camera Follow ---
if (player.y < maxHeight) {
maxHeight = player.y;
LK.setScore(Math.max(0, Math.floor((PLAYER_START_Y - maxHeight) / 10)));
scoreTxt.setText(LK.getScore());
}
// --- Scene transitions and visuals ---
// (No scene transitions in original endless climb version)
var targetCameraY = player.y - (2732 - CAMERA_OFFSET);
if (targetCameraY < cameraY) {
cameraY = targetCameraY;
}
// Move all objects up by cameraY
// Move all objects up by cameraY (endless climb illusion)
for (var k = 0; k < platforms.length; k++) {
// Move platform up by camera scroll delta
platforms[k].y -= cameraY - (platforms[k].baseCameraY || 0);
platforms[k].baseCameraY = cameraY;
platforms[k].update();
}
for (var l = 0; l < obstacles.length; l++) {
obstacles[l].y -= cameraY - (obstacles[l].baseCameraY || 0);
obstacles[l].baseCameraY = cameraY;
}
player.y -= cameraY - (player.baseCameraY || 0);
player.baseCameraY = cameraY;
// Move white dots with camera (decorative, do not affect gameplay)
for (var d = 0; d < whiteDots.length; d++) {
var dot = whiteDots[d];
dot.y -= cameraY - (dot.baseCameraY || 0);
dot.baseCameraY = cameraY;
}
// --- Generate More Platforms ---
generatePlatformsUpTo(cameraY - 1200);
// --- Cleanup ---
cleanupPlatformsObstacles();
};
// --- Game Over Handler (reset on restart) ---
LK.on('gameover', function () {
resetGame();
});
// --- Start Game ---
resetGame(); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Obstacle class: static obstacle (box or ellipse)
var Obstacle = Container.expand(function () {
var self = Container.call(this);
// Attach obstacle asset (ellipse shape)
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Platform class: static or moving platform
var Platform = Container.expand(function () {
var self = Container.call(this);
// Attach platform asset (box shape)
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
// Platform movement properties
self.isMoving = false;
self.moveDir = 1; // 1: right, -1: left
self.moveRange = 0; // in px
self.moveSpeed = 0; // px per frame
self.startX = 0;
// Called every tick
self.update = function () {
if (self.isMoving) {
self.x += self.moveDir * self.moveSpeed;
if (Math.abs(self.x - self.startX) > self.moveRange) {
self.moveDir *= -1;
}
}
};
return self;
});
// Player class
var Player = Container.expand(function () {
var self = Container.call(this);
// Attach player asset (box shape)
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// Physics properties
self.vx = 0;
self.vy = 0;
self.isOnGround = false;
self.width = playerGraphics.width;
self.height = playerGraphics.height;
// Jump method
self.jump = function () {
if (self.isOnGround) {
self.vy = -jumpStrength;
self.isOnGround = false;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222244
});
/****
* Game Code
****/
// --- Asset Initialization ---
// --- Game Constants ---
var GRAVITY = 2.2;
var MOVE_SPEED = 22;
var jumpStrength = 48;
var PLATFORM_MIN_WIDTH = 220;
var PLATFORM_MAX_WIDTH = 420;
var PLATFORM_HEIGHT = 40;
var PLATFORM_GAP_MIN = 220;
var PLATFORM_GAP_MAX = 420;
var PLATFORM_MOVE_CHANCE = 0.25;
var PLATFORM_MOVE_RANGE = 320;
var PLATFORM_MOVE_SPEED = 4;
var OBSTACLE_CHANCE = 0.25;
var OBSTACLE_SIZE = 80;
var PLAYER_START_X = 2048 / 2;
var PLAYER_START_Y = 2732 - 400;
var CAMERA_OFFSET = 900; // How far from bottom the player is kept
// --- Game State ---
var player;
var platforms = [];
var obstacles = [];
var maxHeight = 0; // Highest Y the player has reached (lower y = higher)
var dragStartX = null;
var dragStartY = null;
var dragLastX = null;
var dragLastY = null;
var isDragging = false;
var scoreTxt;
var lastPlatformY = 0;
var cameraY = 0;
var gameOver = false;
// --- Decorative White Dots ---
var whiteDots = [];
var WHITE_DOT_COUNT = 40; // Number of dots
// --- GUI ---
scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// --- Helper Functions ---
// Generate a new platform at (x, y), optionally moving
function createPlatform(x, y, width, isMoving) {
var plat = new Platform();
plat.x = x;
plat.y = y;
plat.width = width;
plat.height = PLATFORM_HEIGHT;
plat.getChildAt(0).width = width;
plat.getChildAt(0).height = PLATFORM_HEIGHT;
plat.isMoving = isMoving;
plat.moveRange = isMoving ? PLATFORM_MOVE_RANGE : 0;
plat.moveSpeed = isMoving ? PLATFORM_MOVE_SPEED : 0;
plat.startX = x;
game.addChild(plat);
platforms.push(plat);
return plat;
}
// Generate a new obstacle on a platform
function createObstacle(x, y) {
var obs = new Obstacle();
obs.x = x;
obs.y = y - OBSTACLE_SIZE / 2 - 10;
obs.width = OBSTACLE_SIZE;
obs.height = OBSTACLE_SIZE;
obs.getChildAt(0).width = OBSTACLE_SIZE;
obs.getChildAt(0).height = OBSTACLE_SIZE;
game.addChild(obs);
obstacles.push(obs);
return obs;
}
// Remove platforms/obstacles below camera
function cleanupPlatformsObstacles() {
for (var i = platforms.length - 1; i >= 0; i--) {
if (platforms[i].y - cameraY > 2732 + 200) {
platforms[i].destroy();
platforms.splice(i, 1);
}
}
for (var j = obstacles.length - 1; j >= 0; j--) {
if (obstacles[j].y - cameraY > 2732 + 200) {
obstacles[j].destroy();
obstacles.splice(j, 1);
}
}
}
// Generate platforms up to a certain Y
function generatePlatformsUpTo(minY) {
while (lastPlatformY > minY) {
var gap = PLATFORM_GAP_MIN + Math.random() * (PLATFORM_GAP_MAX - PLATFORM_GAP_MIN);
var platY = lastPlatformY - gap;
var platWidth = PLATFORM_MIN_WIDTH + Math.random() * (PLATFORM_MAX_WIDTH - PLATFORM_MIN_WIDTH);
var platX = platWidth / 2 + Math.random() * (2048 - platWidth);
var isMoving = Math.random() < PLATFORM_MOVE_CHANCE;
var plat = createPlatform(platX, platY, platWidth, isMoving);
// Maybe add obstacle
if (Math.random() < OBSTACLE_CHANCE && platWidth > 200 + OBSTACLE_SIZE) {
var obsX = plat.x + (Math.random() - 0.5) * (platWidth - OBSTACLE_SIZE - 40);
createObstacle(obsX, platY);
}
lastPlatformY = platY;
}
}
// Reset game state
function resetGame() {
// Remove old objects
for (var i = 0; i < platforms.length; i++) platforms[i].destroy();
for (var j = 0; j < obstacles.length; j++) obstacles[j].destroy();
for (var d = 0; d < whiteDots.length; d++) whiteDots[d].destroy && whiteDots[d].destroy();
platforms = [];
obstacles = [];
whiteDots = [];
cameraY = 0;
lastPlatformY = PLAYER_START_Y + 120;
maxHeight = PLAYER_START_Y;
LK.setScore(0);
scoreTxt.setText('0');
gameOver = false;
// Reset background color to original
game.setBackgroundColor(0x222244);
// Create random white dots (decorative, do not affect gameplay)
for (var i = 0; i < WHITE_DOT_COUNT; i++) {
var dotSize = 8 + Math.random() * 22; // 8-30 px
var dotX = 40 + Math.random() * (2048 - 80);
var dotY = Math.random() * (2732 - 80);
var dot = LK.getAsset('whiteDot', {
width: dotSize,
height: dotSize,
color: 0xffffff,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
x: dotX,
y: dotY
});
game.addChild(dot);
whiteDots.push(dot);
}
// Create player
if (player) player.destroy();
player = new Player();
player.x = PLAYER_START_X;
player.y = PLAYER_START_Y;
player.vx = 0;
player.vy = 0;
player.isOnGround = false;
game.addChild(player);
// Create starting platform
createPlatform(PLAYER_START_X, PLAYER_START_Y + 80, 420, false);
// Generate initial platforms
generatePlatformsUpTo(PLAYER_START_Y - 2000);
}
// --- Input Handling ---
// Touch/drag to move player left/right, tap to jump
game.down = function (x, y, obj) {
if (gameOver) return;
dragStartX = x;
dragStartY = y;
dragLastX = x;
dragLastY = y;
isDragging = true;
};
game.move = function (x, y, obj) {
if (gameOver) return;
if (!isDragging) return;
var dx = x - dragLastX;
dragLastX = x;
dragLastY = y;
// Move player horizontally
player.x += dx * 1.2;
if (player.x < player.width / 2) player.x = player.width / 2;
if (player.x > 2048 - player.width / 2) player.x = 2048 - player.width / 2;
};
game.up = function (x, y, obj) {
if (gameOver) return;
isDragging = false;
// If tap (not drag), jump
if (Math.abs(x - dragStartX) < 30 && Math.abs(y - dragStartY) < 30) {
player.jump();
}
};
// --- Main Game Loop ---
game.update = function () {
if (gameOver) return;
// --- Player Physics ---
player.vy += GRAVITY;
player.y += player.vy;
player.x += player.vx;
// Clamp player to screen
if (player.x < player.width / 2) player.x = player.width / 2;
if (player.x > 2048 - player.width / 2) player.x = 2048 - player.width / 2;
// --- Platform Collision ---
player.isOnGround = false;
for (var i = 0; i < platforms.length; i++) {
var plat = platforms[i];
// Only check collision if falling
if (player.vy >= 0) {
var px = player.x;
var py = player.y + player.height / 2;
var platLeft = plat.x - plat.width / 2;
var platRight = plat.x + plat.width / 2;
var platTop = plat.y - plat.height / 2;
var platBottom = plat.y + plat.height / 2;
if (px > platLeft + 10 && px < platRight - 10 && py > platTop && py < platTop + 40 && player.y < plat.y) {
// Landed on platform
player.y = platTop - player.height / 2 + 1;
player.vy = 0;
player.isOnGround = true;
}
}
}
// --- Obstacle Collision ---
for (var j = 0; j < obstacles.length; j++) {
var obs = obstacles[j];
// Simple circle-rect collision
var dx = Math.abs(player.x - obs.x);
var dy = Math.abs(player.y - obs.y);
if (dx < player.width / 2 + OBSTACLE_SIZE / 2 - 10 && dy < player.height / 2 + OBSTACLE_SIZE / 2 - 10) {
// Hit obstacle
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
LK.showGameOver();
return;
}
}
// --- Fall Off Screen ---
if (player.y - cameraY > 2732 + 100) {
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
LK.showGameOver();
return;
}
// --- Camera Follow ---
if (player.y < maxHeight) {
maxHeight = player.y;
LK.setScore(Math.max(0, Math.floor((PLAYER_START_Y - maxHeight) / 10)));
scoreTxt.setText(LK.getScore());
}
// --- Scene transitions and visuals ---
// (No scene transitions in original endless climb version)
var targetCameraY = player.y - (2732 - CAMERA_OFFSET);
if (targetCameraY < cameraY) {
cameraY = targetCameraY;
}
// Move all objects up by cameraY
// Move all objects up by cameraY (endless climb illusion)
for (var k = 0; k < platforms.length; k++) {
// Move platform up by camera scroll delta
platforms[k].y -= cameraY - (platforms[k].baseCameraY || 0);
platforms[k].baseCameraY = cameraY;
platforms[k].update();
}
for (var l = 0; l < obstacles.length; l++) {
obstacles[l].y -= cameraY - (obstacles[l].baseCameraY || 0);
obstacles[l].baseCameraY = cameraY;
}
player.y -= cameraY - (player.baseCameraY || 0);
player.baseCameraY = cameraY;
// Move white dots with camera (decorative, do not affect gameplay)
for (var d = 0; d < whiteDots.length; d++) {
var dot = whiteDots[d];
dot.y -= cameraY - (dot.baseCameraY || 0);
dot.baseCameraY = cameraY;
}
// --- Generate More Platforms ---
generatePlatformsUpTo(cameraY - 1200);
// --- Cleanup ---
cleanupPlatformsObstacles();
};
// --- Game Over Handler (reset on restart) ---
LK.on('gameover', function () {
resetGame();
});
// --- Start Game ---
resetGame();