/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Biker = Container.expand(function () { var self = Container.call(this); var bikerGraphics = self.attachAsset('biker', { anchorX: 0.5, anchorY: 0.5 }); // State variables self.velocity = { x: 0, y: 0 }; self.isJumping = false; self.isDead = false; self.gravity = 0.5; self.jumpForce = -20; // Increase jump force for quicker response self.jump = function (isHighJump) { if (!self.isJumping && !self.isDead) { self.velocity.y = isHighJump ? self.jumpForce * 2 : self.jumpForce; self.isJumping = isHighJump ? true : !self.isJumping; LK.getSound('jump').play(); } }; self.update = function () { if (self.isDead) { return; } // Apply gravity self.velocity.y += self.gravity; // Update position self.y += self.velocity.y; // Cap falling speed if (self.velocity.y > 15) { self.velocity.y = 15; } // Tilt the biker based on vertical velocity var targetRotation = self.velocity.y * 0.03; bikerGraphics.rotation = targetRotation; }; self.die = function () { if (!self.isDead) { self.isDead = true; LK.getSound('crash').play(); // Animate the death tween(bikerGraphics, { rotation: Math.PI }, { duration: 800, easing: tween.bounceOut }); // Flash the biker red LK.effects.flashObject(self, 0xff0000, 500); // Game over after a short delay LK.setTimeout(function () { LK.showGameOver(); }, 1000); } }; return self; }); var Coin = Container.expand(function () { var self = Container.call(this); var coinGraphics = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); self.width = coinGraphics.width; self.height = coinGraphics.height; self.speed = 5; self.active = true; // Animation self.update = function () { if (!self.active) { return; } // Spin the coin coinGraphics.rotation += 0.05; self.x -= self.speed; // Remove when off screen if (self.x < -self.width) { self.active = false; self.destroy(); } }; self.collect = function () { if (self.active) { self.active = false; // Animate coin collection tween(self, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 300, onFinish: function onFinish() { self.destroy(); } }); LK.getSound('coin').play(); return true; } return false; }; return self; }); var Ground = Container.expand(function () { var self = Container.call(this); var groundGraphics = self.attachAsset('ground', { anchorX: 0, anchorY: 0 }); self.speed = 5; self.update = function () { self.x -= self.speed; // Loop the ground if (self.x <= -groundGraphics.width) { self.x += groundGraphics.width; } }; return self; }); var Jump = Container.expand(function () { var self = Container.call(this); var jumpGraphics = self.attachAsset('jump', { anchorX: 0.5, anchorY: 1.0 }); self.width = jumpGraphics.width; self.height = jumpGraphics.height; self.speed = 5; self.active = true; self.update = function () { if (!self.active) { return; } self.x -= self.speed; // Remove when off screen if (self.x < -self.width) { self.active = false; self.destroy(); } }; return self; }); var Obstacle = Container.expand(function () { var self = Container.call(this); var obstacleGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 1.0 }); self.width = obstacleGraphics.width; self.height = obstacleGraphics.height; self.speed = 5; self.active = true; self.update = function () { if (!self.active) { return; } self.x -= self.speed; // Remove when off screen if (self.x < -self.width) { self.active = false; self.destroy(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB // Sky blue background }); /**** * Game Code ****/ // Game variables var biker; var groundTiles = []; var obstacles = []; var jumps = []; var coins = []; var distance = 0; var groundY = 2732 - 250; // Ground position from top var gameSpeed = 5; var spawnDistance = 0; var lastObstaclePos = 0; var gameActive = false; var difficultyTimer = 0; var coinsCollected = 0; // Create score display var scoreTxt = new Text2('Distance: 0m', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Create coin display var coinTxt = new Text2('Coins: 0', { size: 80, fill: 0xFFCC00 }); coinTxt.anchor.set(0.5, 0); coinTxt.y = 100; LK.gui.top.addChild(coinTxt); // Initialize high score from storage var highScore = storage.highScore || 0; var highScoreTxt = new Text2('Best: ' + highScore + 'm', { size: 60, fill: 0xFFFFFF }); highScoreTxt.anchor.set(1.0, 0); highScoreTxt.y = 10; highScoreTxt.x = -10; LK.gui.topRight.addChild(highScoreTxt); // Create tap to start message var startTxt = new Text2('Tap to Start', { size: 120, fill: 0xFFFFFF }); startTxt.anchor.set(0.5, 0.5); LK.gui.center.addChild(startTxt); // Initialize the game elements function initGame() { // Attach background image var background = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(background); // Reset variables obstacles = []; jumps = []; coins = []; distance = 0; gameSpeed = 5; spawnDistance = 0; lastObstaclePos = 0; gameActive = false; difficultyTimer = 0; coinsCollected = 0; // Update UI scoreTxt.setText('Distance: 0m'); coinTxt.setText('Coins: 0'); startTxt.visible = true; // Create ground if (groundTiles.length === 0) { for (var i = 0; i < 2; i++) { var ground = new Ground(); ground.x = i * ground.width; ground.y = groundY; groundTiles.push(ground); game.addChild(ground); } } else { for (var i = 0; i < groundTiles.length; i++) { groundTiles[i].x = i * groundTiles[i].width; } } // Create player if not exists if (!biker) { biker = new Biker(); game.addChild(biker); } // Position player biker.x = 2048 / 2; // Center the player horizontally biker.y = groundY - 30; biker.velocity = { x: 0, y: 0 }; biker.isJumping = false; biker.isDead = false; // Play background music LK.playMusic('bgMusic', { fade: { start: 0, end: 0.6, duration: 1000 } }); } // Start the game function startGame() { if (!gameActive) { gameActive = true; startTxt.visible = false; } } // Spawn obstacles and collectibles function spawnObjects() { if (!gameActive) { return; } spawnDistance += gameSpeed; // Minimum distance between objects var minDistance = 500; // Check if we should spawn a new object if (spawnDistance - lastObstaclePos > minDistance) { var rand = Math.random(); // Determine what type of object to spawn if (rand < 0.5) { // Spawn obstacle var obstacle = new Obstacle(); obstacle.x = 2048 + obstacle.width; obstacle.y = groundY; obstacle.speed = gameSpeed; obstacles.push(obstacle); game.addChild(obstacle); lastObstaclePos = spawnDistance; } else if (rand < 0.8) { // Spawn jump ramp var jump = new Jump(); jump.x = 2048 + jump.width; jump.y = groundY; jump.speed = gameSpeed; jumps.push(jump); game.addChild(jump); lastObstaclePos = spawnDistance; // Spawn coin above the jump var coin = new Coin(); coin.x = jump.x; coin.y = groundY - 150 - Math.random() * 100; coin.speed = gameSpeed; coins.push(coin); game.addChild(coin); } else { // Spawn just a coin var coin = new Coin(); coin.x = 2048 + coin.width; coin.y = groundY - 100 - Math.random() * 150; coin.speed = gameSpeed; coins.push(coin); game.addChild(coin); lastObstaclePos = spawnDistance; } } } // Check collision with ground function checkGroundCollision() { if (biker.y >= groundY - 30) { biker.y = groundY - 30; biker.velocity.y = 0; biker.isJumping = false; } } // Check collision with obstacles function checkObstacleCollision() { if (!gameActive || biker.isDead) { return; } // Check obstacles for (var i = obstacles.length - 1; i >= 0; i--) { var obstacle = obstacles[i]; if (obstacle.active && biker.intersects(obstacle)) { biker.die(); return; } } // Check jumps (no collision, just boost) for (var i = jumps.length - 1; i >= 0; i--) { var jump = jumps[i]; if (jump.active && biker.intersects(jump) && !biker.isJumping) { biker.velocity.y = biker.jumpForce * 1.2; // Extra boost from ramp biker.isJumping = true; LK.getSound('jump').play(); } } // Check coins for (var i = coins.length - 1; i >= 0; i--) { var coin = coins[i]; if (coin.active && biker.intersects(coin)) { if (coin.collect()) { coins.splice(i, 1); coinsCollected++; coinTxt.setText('Coins: ' + coinsCollected); } } } } // Update game difficulty function updateDifficulty() { if (!gameActive) { return; } difficultyTimer++; // Increase speed every 5 seconds if (difficultyTimer % 300 === 0) { gameSpeed += 1.0; // Update all object speeds for (var i = 0; i < groundTiles.length; i++) { groundTiles[i].speed = gameSpeed; } for (var i = 0; i < obstacles.length; i++) { obstacles[i].speed = gameSpeed; } for (var i = 0; i < jumps.length; i++) { jumps[i].speed = gameSpeed; } for (var i = 0; i < coins.length; i++) { coins[i].speed = gameSpeed; } } } // Clean up objects that are no longer active function cleanupObjects() { for (var i = obstacles.length - 1; i >= 0; i--) { if (!obstacles[i].active) { obstacles.splice(i, 1); } } for (var i = jumps.length - 1; i >= 0; i--) { if (!jumps[i].active) { jumps.splice(i, 1); } } for (var i = coins.length - 1; i >= 0; i--) { if (!coins[i].active) { coins.splice(i, 1); } } } // Update score function updateScore() { if (gameActive && !biker.isDead) { distance += gameSpeed / 10; var distanceInt = Math.floor(distance); scoreTxt.setText('Distance: ' + distanceInt + 'm'); // Update high score if (distanceInt > highScore) { highScore = distanceInt; highScoreTxt.setText('Best: ' + highScore + 'm'); storage.highScore = highScore; } } } // Event handlers game.down = function (x, y, obj) { if (!gameActive) { startGame(); } else if (!biker.isDead) { biker.jump(y < 1700); // High jump if tap is in the upper 60% of the screen } }; // Game update function game.update = function () { // Initialize on first run if (LK.ticks === 1) { initGame(); } // Update all game objects if (biker) { biker.update(); } for (var i = 0; i < groundTiles.length; i++) { groundTiles[i].update(); } for (var i = 0; i < obstacles.length; i++) { obstacles[i].update(); } for (var i = 0; i < jumps.length; i++) { jumps[i].update(); } for (var i = 0; i < coins.length; i++) { coins[i].update(); } // Game logic if (gameActive) { checkGroundCollision(); checkObstacleCollision(); spawnObjects(); updateDifficulty(); updateScore(); cleanupObjects(); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Biker = Container.expand(function () {
var self = Container.call(this);
var bikerGraphics = self.attachAsset('biker', {
anchorX: 0.5,
anchorY: 0.5
});
// State variables
self.velocity = {
x: 0,
y: 0
};
self.isJumping = false;
self.isDead = false;
self.gravity = 0.5;
self.jumpForce = -20; // Increase jump force for quicker response
self.jump = function (isHighJump) {
if (!self.isJumping && !self.isDead) {
self.velocity.y = isHighJump ? self.jumpForce * 2 : self.jumpForce;
self.isJumping = isHighJump ? true : !self.isJumping;
LK.getSound('jump').play();
}
};
self.update = function () {
if (self.isDead) {
return;
}
// Apply gravity
self.velocity.y += self.gravity;
// Update position
self.y += self.velocity.y;
// Cap falling speed
if (self.velocity.y > 15) {
self.velocity.y = 15;
}
// Tilt the biker based on vertical velocity
var targetRotation = self.velocity.y * 0.03;
bikerGraphics.rotation = targetRotation;
};
self.die = function () {
if (!self.isDead) {
self.isDead = true;
LK.getSound('crash').play();
// Animate the death
tween(bikerGraphics, {
rotation: Math.PI
}, {
duration: 800,
easing: tween.bounceOut
});
// Flash the biker red
LK.effects.flashObject(self, 0xff0000, 500);
// Game over after a short delay
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = coinGraphics.width;
self.height = coinGraphics.height;
self.speed = 5;
self.active = true;
// Animation
self.update = function () {
if (!self.active) {
return;
}
// Spin the coin
coinGraphics.rotation += 0.05;
self.x -= self.speed;
// Remove when off screen
if (self.x < -self.width) {
self.active = false;
self.destroy();
}
};
self.collect = function () {
if (self.active) {
self.active = false;
// Animate coin collection
tween(self, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
LK.getSound('coin').play();
return true;
}
return false;
};
return self;
});
var Ground = Container.expand(function () {
var self = Container.call(this);
var groundGraphics = self.attachAsset('ground', {
anchorX: 0,
anchorY: 0
});
self.speed = 5;
self.update = function () {
self.x -= self.speed;
// Loop the ground
if (self.x <= -groundGraphics.width) {
self.x += groundGraphics.width;
}
};
return self;
});
var Jump = Container.expand(function () {
var self = Container.call(this);
var jumpGraphics = self.attachAsset('jump', {
anchorX: 0.5,
anchorY: 1.0
});
self.width = jumpGraphics.width;
self.height = jumpGraphics.height;
self.speed = 5;
self.active = true;
self.update = function () {
if (!self.active) {
return;
}
self.x -= self.speed;
// Remove when off screen
if (self.x < -self.width) {
self.active = false;
self.destroy();
}
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0
});
self.width = obstacleGraphics.width;
self.height = obstacleGraphics.height;
self.speed = 5;
self.active = true;
self.update = function () {
if (!self.active) {
return;
}
self.x -= self.speed;
// Remove when off screen
if (self.x < -self.width) {
self.active = false;
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue background
});
/****
* Game Code
****/
// Game variables
var biker;
var groundTiles = [];
var obstacles = [];
var jumps = [];
var coins = [];
var distance = 0;
var groundY = 2732 - 250; // Ground position from top
var gameSpeed = 5;
var spawnDistance = 0;
var lastObstaclePos = 0;
var gameActive = false;
var difficultyTimer = 0;
var coinsCollected = 0;
// Create score display
var scoreTxt = new Text2('Distance: 0m', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create coin display
var coinTxt = new Text2('Coins: 0', {
size: 80,
fill: 0xFFCC00
});
coinTxt.anchor.set(0.5, 0);
coinTxt.y = 100;
LK.gui.top.addChild(coinTxt);
// Initialize high score from storage
var highScore = storage.highScore || 0;
var highScoreTxt = new Text2('Best: ' + highScore + 'm', {
size: 60,
fill: 0xFFFFFF
});
highScoreTxt.anchor.set(1.0, 0);
highScoreTxt.y = 10;
highScoreTxt.x = -10;
LK.gui.topRight.addChild(highScoreTxt);
// Create tap to start message
var startTxt = new Text2('Tap to Start', {
size: 120,
fill: 0xFFFFFF
});
startTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(startTxt);
// Initialize the game elements
function initGame() {
// Attach background image
var background = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(background);
// Reset variables
obstacles = [];
jumps = [];
coins = [];
distance = 0;
gameSpeed = 5;
spawnDistance = 0;
lastObstaclePos = 0;
gameActive = false;
difficultyTimer = 0;
coinsCollected = 0;
// Update UI
scoreTxt.setText('Distance: 0m');
coinTxt.setText('Coins: 0');
startTxt.visible = true;
// Create ground
if (groundTiles.length === 0) {
for (var i = 0; i < 2; i++) {
var ground = new Ground();
ground.x = i * ground.width;
ground.y = groundY;
groundTiles.push(ground);
game.addChild(ground);
}
} else {
for (var i = 0; i < groundTiles.length; i++) {
groundTiles[i].x = i * groundTiles[i].width;
}
}
// Create player if not exists
if (!biker) {
biker = new Biker();
game.addChild(biker);
}
// Position player
biker.x = 2048 / 2; // Center the player horizontally
biker.y = groundY - 30;
biker.velocity = {
x: 0,
y: 0
};
biker.isJumping = false;
biker.isDead = false;
// Play background music
LK.playMusic('bgMusic', {
fade: {
start: 0,
end: 0.6,
duration: 1000
}
});
}
// Start the game
function startGame() {
if (!gameActive) {
gameActive = true;
startTxt.visible = false;
}
}
// Spawn obstacles and collectibles
function spawnObjects() {
if (!gameActive) {
return;
}
spawnDistance += gameSpeed;
// Minimum distance between objects
var minDistance = 500;
// Check if we should spawn a new object
if (spawnDistance - lastObstaclePos > minDistance) {
var rand = Math.random();
// Determine what type of object to spawn
if (rand < 0.5) {
// Spawn obstacle
var obstacle = new Obstacle();
obstacle.x = 2048 + obstacle.width;
obstacle.y = groundY;
obstacle.speed = gameSpeed;
obstacles.push(obstacle);
game.addChild(obstacle);
lastObstaclePos = spawnDistance;
} else if (rand < 0.8) {
// Spawn jump ramp
var jump = new Jump();
jump.x = 2048 + jump.width;
jump.y = groundY;
jump.speed = gameSpeed;
jumps.push(jump);
game.addChild(jump);
lastObstaclePos = spawnDistance;
// Spawn coin above the jump
var coin = new Coin();
coin.x = jump.x;
coin.y = groundY - 150 - Math.random() * 100;
coin.speed = gameSpeed;
coins.push(coin);
game.addChild(coin);
} else {
// Spawn just a coin
var coin = new Coin();
coin.x = 2048 + coin.width;
coin.y = groundY - 100 - Math.random() * 150;
coin.speed = gameSpeed;
coins.push(coin);
game.addChild(coin);
lastObstaclePos = spawnDistance;
}
}
}
// Check collision with ground
function checkGroundCollision() {
if (biker.y >= groundY - 30) {
biker.y = groundY - 30;
biker.velocity.y = 0;
biker.isJumping = false;
}
}
// Check collision with obstacles
function checkObstacleCollision() {
if (!gameActive || biker.isDead) {
return;
}
// Check obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
if (obstacle.active && biker.intersects(obstacle)) {
biker.die();
return;
}
}
// Check jumps (no collision, just boost)
for (var i = jumps.length - 1; i >= 0; i--) {
var jump = jumps[i];
if (jump.active && biker.intersects(jump) && !biker.isJumping) {
biker.velocity.y = biker.jumpForce * 1.2; // Extra boost from ramp
biker.isJumping = true;
LK.getSound('jump').play();
}
}
// Check coins
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
if (coin.active && biker.intersects(coin)) {
if (coin.collect()) {
coins.splice(i, 1);
coinsCollected++;
coinTxt.setText('Coins: ' + coinsCollected);
}
}
}
}
// Update game difficulty
function updateDifficulty() {
if (!gameActive) {
return;
}
difficultyTimer++;
// Increase speed every 5 seconds
if (difficultyTimer % 300 === 0) {
gameSpeed += 1.0;
// Update all object speeds
for (var i = 0; i < groundTiles.length; i++) {
groundTiles[i].speed = gameSpeed;
}
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].speed = gameSpeed;
}
for (var i = 0; i < jumps.length; i++) {
jumps[i].speed = gameSpeed;
}
for (var i = 0; i < coins.length; i++) {
coins[i].speed = gameSpeed;
}
}
}
// Clean up objects that are no longer active
function cleanupObjects() {
for (var i = obstacles.length - 1; i >= 0; i--) {
if (!obstacles[i].active) {
obstacles.splice(i, 1);
}
}
for (var i = jumps.length - 1; i >= 0; i--) {
if (!jumps[i].active) {
jumps.splice(i, 1);
}
}
for (var i = coins.length - 1; i >= 0; i--) {
if (!coins[i].active) {
coins.splice(i, 1);
}
}
}
// Update score
function updateScore() {
if (gameActive && !biker.isDead) {
distance += gameSpeed / 10;
var distanceInt = Math.floor(distance);
scoreTxt.setText('Distance: ' + distanceInt + 'm');
// Update high score
if (distanceInt > highScore) {
highScore = distanceInt;
highScoreTxt.setText('Best: ' + highScore + 'm');
storage.highScore = highScore;
}
}
}
// Event handlers
game.down = function (x, y, obj) {
if (!gameActive) {
startGame();
} else if (!biker.isDead) {
biker.jump(y < 1700); // High jump if tap is in the upper 60% of the screen
}
};
// Game update function
game.update = function () {
// Initialize on first run
if (LK.ticks === 1) {
initGame();
}
// Update all game objects
if (biker) {
biker.update();
}
for (var i = 0; i < groundTiles.length; i++) {
groundTiles[i].update();
}
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].update();
}
for (var i = 0; i < jumps.length; i++) {
jumps[i].update();
}
for (var i = 0; i < coins.length; i++) {
coins[i].update();
}
// Game logic
if (gameActive) {
checkGroundCollision();
checkObstacleCollision();
spawnObjects();
updateDifficulty();
updateScore();
cleanupObjects();
}
};