/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Collectible = Container.expand(function () { var self = Container.call(this); var collectibleGraphics = self.attachAsset('collectible', { anchorX: 0.5, anchorY: 0.5 }); self.width = collectibleGraphics.width; self.height = collectibleGraphics.height; self.collected = false; // Add a pulsing animation function pulse() { tween(collectibleGraphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(collectibleGraphics, { scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.easeInOut, onFinish: pulse }); } }); } pulse(); self.collect = function () { if (!self.collected) { self.collected = true; LK.getSound('collect').play(); // Animate the collectible when collected tween(collectibleGraphics, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { self.visible = false; } }); return true; } return false; }; return self; }); var Obstacle = Container.expand(function () { var self = Container.call(this); var obstacleGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); self.width = obstacleGraphics.width; self.height = obstacleGraphics.height; return self; }); var Platform = Container.expand(function () { var self = Container.call(this); var platformGraphics = self.attachAsset('platform', { anchorX: 0.5, anchorY: 0.5 }); self.width = platformGraphics.width; self.height = platformGraphics.height; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.velocity = { x: 0, y: 0 }; self.gravity = 0.8; self.jumpForce = -18; self.isJumping = false; self.isDead = false; self.speed = 8; self.jump = function () { if (!self.isJumping && !self.isDead) { self.velocity.y = self.jumpForce; self.isJumping = true; LK.getSound('jump').play(); // Rotate the player when jumping tween(playerGraphics, { rotation: Math.PI * 2 }, { duration: 500, easing: tween.easeOut }); } }; self.die = function () { if (!self.isDead) { self.isDead = true; LK.getSound('death').play(); // Flash the player red LK.effects.flashObject(self, 0xff0000, 500); // Show game over after a short delay LK.setTimeout(function () { LK.showGameOver(); }, 1000); } }; self.invincible = false; // Add invincibility property self.invincibilityDuration = 1000; // Duration in milliseconds self.update = function () { if (self.isDead || self.invincible) { return; } // Apply gravity self.velocity.y += self.gravity; // Apply velocity self.y += self.velocity.y; self.x += self.speed; // Check if player fell off the screen if (self.y > 2732 + 200) { self.reset(); // Reset player position instead of dying } }; self.reset = function () { self.velocity = { x: 0, y: 0 }; self.isJumping = false; self.isDead = false; self.x = 250; self.y = 2732 / 2; playerGraphics.rotation = 0; }; return self; }); var Spike = Container.expand(function () { var self = Container.call(this); var spikeGraphics = self.attachAsset('spike', { anchorX: 0.5, anchorY: 0.5 }); // Make it look more like a spike (rotate to point upward) spikeGraphics.rotation = Math.PI / 4; // 45 degrees self.width = spikeGraphics.width; self.height = spikeGraphics.height; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x34495e }); /**** * Game Code ****/ // Game variables var LevelGenerator = function LevelGenerator() { var self = {}; self.generateLevel = function (difficulty, startX) { var elements = []; var x = startX || 500; var spacing = 300 - difficulty * 20; // Reduce spacing as difficulty increases var platformCount = 10 + difficulty * 5; // Generate platforms with obstacles and collectibles for (var i = 0; i < platformCount; i++) { // Create a platform var platform = new Platform(); platform.x = x; platform.y = 2732 / 2 + 200 + Math.sin(i * 0.4) * 150; elements.push(platform); // Randomly add obstacles based on difficulty if (Math.random() < 0.3 + difficulty * 0.1) { var obstacle = new Obstacle(); obstacle.x = x; obstacle.y = platform.y - platform.height / 2 - obstacle.height / 2; elements.push(obstacle); } // Randomly add spikes based on difficulty if (Math.random() < 0.2 + difficulty * 0.05) { var spike = new Spike(); spike.x = x + (Math.random() * 100 - 50); spike.y = platform.y - platform.height / 2 - spike.height / 2; elements.push(spike); } // Randomly add collectibles if (Math.random() < 0.4) { var collectible = new Collectible(); collectible.x = x; collectible.y = platform.y - 120; elements.push(collectible); } // Increase x position for next platform x += spacing + Math.random() * 100; } return { elements: elements, endX: x }; }; return self; }; var player; var platforms = []; var obstacles = []; var spikes = []; var collectibles = []; var levelGenerator; var currentLevel = 1; var levelEndX = 0; var gameStarted = false; var cameraOffset = 0; // Setup score text var scoreTxt = new Text2('0', { size: 100, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Setup level text var levelTxt = new Text2('LEVEL 1', { size: 80, fill: 0xFFFFFF }); levelTxt.anchor.set(0.5, 0); levelTxt.y = 120; LK.gui.top.addChild(levelTxt); // Setup instructions var instructionsTxt = new Text2('TAP TO JUMP', { size: 80, fill: 0xFFFFFF }); instructionsTxt.anchor.set(0.5, 0.5); instructionsTxt.alpha = 0.8; LK.gui.center.addChild(instructionsTxt); // Initialize level generator levelGenerator = new LevelGenerator(); // Create player player = new Player(); player.reset(); game.addChild(player); // Generate first level function generateNewLevel() { // Clear existing level elements for (var i = platforms.length - 1; i >= 0; i--) { game.removeChild(platforms[i]); platforms.splice(i, 1); } for (var i = obstacles.length - 1; i >= 0; i--) { game.removeChild(obstacles[i]); obstacles.splice(i, 1); } for (var i = spikes.length - 1; i >= 0; i--) { game.removeChild(spikes[i]); spikes.splice(i, 1); } for (var i = collectibles.length - 1; i >= 0; i--) { game.removeChild(collectibles[i]); collectibles.splice(i, 1); } // Generate new level var level = levelGenerator.generateLevel(currentLevel - 1, 500); levelEndX = level.endX; // Add elements to the game for (var i = 0; i < level.elements.length; i++) { var element = level.elements[i]; game.addChild(element); // Add to appropriate array for collision detection if (element instanceof Platform) { platforms.push(element); } else if (element instanceof Obstacle) { obstacles.push(element); } else if (element instanceof Spike) { spikes.push(element); } else if (element instanceof Collectible) { collectibles.push(element); } } // Update level text levelTxt.setText('LEVEL ' + currentLevel); } // Check player collisions function checkCollisions() { // Check platform collisions var onGround = false; for (var i = 0; i < platforms.length; i++) { var platform = platforms[i]; // Simple collision detection if (player.x + 40 > platform.x - platform.width / 2 && player.x - 40 < platform.x + platform.width / 2 && player.y + 40 > platform.y - platform.height / 2 && player.y + 40 < platform.y + platform.height / 2 && player.velocity.y > 0) { player.y = platform.y - platform.height / 2 - 40; player.velocity.y = 0; player.isJumping = false; onGround = true; } } // Check obstacle collisions for (var i = 0; i < obstacles.length; i++) { var obstacle = obstacles[i]; if (player.intersects(obstacle) && !player.invincible) { player.die(); // Trigger player death player.invincible = true; // Set player to invincible LK.setTimeout(function () { // Reset invincibility after duration player.invincible = false; }, player.invincibilityDuration); } } // Check spike collisions for (var i = 0; i < spikes.length; i++) { var spike = spikes[i]; if (player.intersects(spike) && !player.invincible) { player.die(); // Trigger player death player.invincible = true; // Set player to invincible LK.setTimeout(function () { // Reset invincibility after duration player.invincible = false; }, player.invincibilityDuration); } } // Check collectible collisions for (var i = 0; i < collectibles.length; i++) { var collectible = collectibles[i]; if (!collectible.collected && player.intersects(collectible)) { if (collectible.collect()) { // Increase score LK.setScore(LK.getScore() + 10); scoreTxt.setText(LK.getScore()); } } } // If we're not on ground and not already jumping, start falling if (!onGround && !player.isJumping) { player.isJumping = true; } // Check if player reached the end of the level if (player.x > levelEndX - 300) { // Level complete, generate new level currentLevel++; player.reset(); generateNewLevel(); // Show level complete animation var levelCompleteTxt = new Text2('LEVEL COMPLETE!', { size: 120, fill: 0xFFFFFF }); levelCompleteTxt.anchor.set(0.5, 0.5); LK.gui.center.addChild(levelCompleteTxt); tween(levelCompleteTxt, { alpha: 0 }, { duration: 1500, onFinish: function onFinish() { LK.gui.center.removeChild(levelCompleteTxt); } }); } } // Camera follow player function updateCamera() { // Make the camera follow the player horizontally cameraOffset = player.x - 500; // Apply camera offset to all elements for (var i = 0; i < platforms.length; i++) { platforms[i].x = platforms[i]._originalX - cameraOffset; } for (var i = 0; i < obstacles.length; i++) { obstacles[i].x = obstacles[i]._originalX - cameraOffset; } for (var i = 0; i < spikes.length; i++) { spikes[i].x = spikes[i]._originalX - cameraOffset; } for (var i = 0; i < collectibles.length; i++) { collectibles[i].x = collectibles[i]._originalX - cameraOffset; } } // Handler for tap/click events game.down = function (x, y, obj) { if (!gameStarted) { gameStarted = true; instructionsTxt.visible = false; generateNewLevel(); // Start playing the background music LK.playMusic('gameMusic'); } else { player.jump(); } }; // Main game update function game.update = function () { if (!gameStarted) { return; } // Update player player.update(); // Check collisions checkCollisions(); // Store original positions for camera offset calculations if (LK.ticks === 1) { for (var i = 0; i < platforms.length; i++) { platforms[i]._originalX = platforms[i].x; } for (var i = 0; i < obstacles.length; i++) { obstacles[i]._originalX = obstacles[i].x; } for (var i = 0; i < spikes.length; i++) { spikes[i]._originalX = spikes[i].x; } for (var i = 0; i < collectibles.length; i++) { collectibles[i]._originalX = collectibles[i].x; } } // Update camera // updateCamera(); // Uncomment to implement scrolling camera };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Collectible = Container.expand(function () {
var self = Container.call(this);
var collectibleGraphics = self.attachAsset('collectible', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = collectibleGraphics.width;
self.height = collectibleGraphics.height;
self.collected = false;
// Add a pulsing animation
function pulse() {
tween(collectibleGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(collectibleGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: pulse
});
}
});
}
pulse();
self.collect = function () {
if (!self.collected) {
self.collected = true;
LK.getSound('collect').play();
// Animate the collectible when collected
tween(collectibleGraphics, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.visible = false;
}
});
return true;
}
return false;
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = obstacleGraphics.width;
self.height = obstacleGraphics.height;
return self;
});
var Platform = Container.expand(function () {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = platformGraphics.width;
self.height = platformGraphics.height;
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocity = {
x: 0,
y: 0
};
self.gravity = 0.8;
self.jumpForce = -18;
self.isJumping = false;
self.isDead = false;
self.speed = 8;
self.jump = function () {
if (!self.isJumping && !self.isDead) {
self.velocity.y = self.jumpForce;
self.isJumping = true;
LK.getSound('jump').play();
// Rotate the player when jumping
tween(playerGraphics, {
rotation: Math.PI * 2
}, {
duration: 500,
easing: tween.easeOut
});
}
};
self.die = function () {
if (!self.isDead) {
self.isDead = true;
LK.getSound('death').play();
// Flash the player red
LK.effects.flashObject(self, 0xff0000, 500);
// Show game over after a short delay
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
};
self.invincible = false; // Add invincibility property
self.invincibilityDuration = 1000; // Duration in milliseconds
self.update = function () {
if (self.isDead || self.invincible) {
return;
}
// Apply gravity
self.velocity.y += self.gravity;
// Apply velocity
self.y += self.velocity.y;
self.x += self.speed;
// Check if player fell off the screen
if (self.y > 2732 + 200) {
self.reset(); // Reset player position instead of dying
}
};
self.reset = function () {
self.velocity = {
x: 0,
y: 0
};
self.isJumping = false;
self.isDead = false;
self.x = 250;
self.y = 2732 / 2;
playerGraphics.rotation = 0;
};
return self;
});
var Spike = Container.expand(function () {
var self = Container.call(this);
var spikeGraphics = self.attachAsset('spike', {
anchorX: 0.5,
anchorY: 0.5
});
// Make it look more like a spike (rotate to point upward)
spikeGraphics.rotation = Math.PI / 4; // 45 degrees
self.width = spikeGraphics.width;
self.height = spikeGraphics.height;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x34495e
});
/****
* Game Code
****/
// Game variables
var LevelGenerator = function LevelGenerator() {
var self = {};
self.generateLevel = function (difficulty, startX) {
var elements = [];
var x = startX || 500;
var spacing = 300 - difficulty * 20; // Reduce spacing as difficulty increases
var platformCount = 10 + difficulty * 5;
// Generate platforms with obstacles and collectibles
for (var i = 0; i < platformCount; i++) {
// Create a platform
var platform = new Platform();
platform.x = x;
platform.y = 2732 / 2 + 200 + Math.sin(i * 0.4) * 150;
elements.push(platform);
// Randomly add obstacles based on difficulty
if (Math.random() < 0.3 + difficulty * 0.1) {
var obstacle = new Obstacle();
obstacle.x = x;
obstacle.y = platform.y - platform.height / 2 - obstacle.height / 2;
elements.push(obstacle);
}
// Randomly add spikes based on difficulty
if (Math.random() < 0.2 + difficulty * 0.05) {
var spike = new Spike();
spike.x = x + (Math.random() * 100 - 50);
spike.y = platform.y - platform.height / 2 - spike.height / 2;
elements.push(spike);
}
// Randomly add collectibles
if (Math.random() < 0.4) {
var collectible = new Collectible();
collectible.x = x;
collectible.y = platform.y - 120;
elements.push(collectible);
}
// Increase x position for next platform
x += spacing + Math.random() * 100;
}
return {
elements: elements,
endX: x
};
};
return self;
};
var player;
var platforms = [];
var obstacles = [];
var spikes = [];
var collectibles = [];
var levelGenerator;
var currentLevel = 1;
var levelEndX = 0;
var gameStarted = false;
var cameraOffset = 0;
// Setup score text
var scoreTxt = new Text2('0', {
size: 100,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Setup level text
var levelTxt = new Text2('LEVEL 1', {
size: 80,
fill: 0xFFFFFF
});
levelTxt.anchor.set(0.5, 0);
levelTxt.y = 120;
LK.gui.top.addChild(levelTxt);
// Setup instructions
var instructionsTxt = new Text2('TAP TO JUMP', {
size: 80,
fill: 0xFFFFFF
});
instructionsTxt.anchor.set(0.5, 0.5);
instructionsTxt.alpha = 0.8;
LK.gui.center.addChild(instructionsTxt);
// Initialize level generator
levelGenerator = new LevelGenerator();
// Create player
player = new Player();
player.reset();
game.addChild(player);
// Generate first level
function generateNewLevel() {
// Clear existing level elements
for (var i = platforms.length - 1; i >= 0; i--) {
game.removeChild(platforms[i]);
platforms.splice(i, 1);
}
for (var i = obstacles.length - 1; i >= 0; i--) {
game.removeChild(obstacles[i]);
obstacles.splice(i, 1);
}
for (var i = spikes.length - 1; i >= 0; i--) {
game.removeChild(spikes[i]);
spikes.splice(i, 1);
}
for (var i = collectibles.length - 1; i >= 0; i--) {
game.removeChild(collectibles[i]);
collectibles.splice(i, 1);
}
// Generate new level
var level = levelGenerator.generateLevel(currentLevel - 1, 500);
levelEndX = level.endX;
// Add elements to the game
for (var i = 0; i < level.elements.length; i++) {
var element = level.elements[i];
game.addChild(element);
// Add to appropriate array for collision detection
if (element instanceof Platform) {
platforms.push(element);
} else if (element instanceof Obstacle) {
obstacles.push(element);
} else if (element instanceof Spike) {
spikes.push(element);
} else if (element instanceof Collectible) {
collectibles.push(element);
}
}
// Update level text
levelTxt.setText('LEVEL ' + currentLevel);
}
// Check player collisions
function checkCollisions() {
// Check platform collisions
var onGround = false;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
// Simple collision detection
if (player.x + 40 > platform.x - platform.width / 2 && player.x - 40 < platform.x + platform.width / 2 && player.y + 40 > platform.y - platform.height / 2 && player.y + 40 < platform.y + platform.height / 2 && player.velocity.y > 0) {
player.y = platform.y - platform.height / 2 - 40;
player.velocity.y = 0;
player.isJumping = false;
onGround = true;
}
}
// Check obstacle collisions
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
if (player.intersects(obstacle) && !player.invincible) {
player.die(); // Trigger player death
player.invincible = true; // Set player to invincible
LK.setTimeout(function () {
// Reset invincibility after duration
player.invincible = false;
}, player.invincibilityDuration);
}
}
// Check spike collisions
for (var i = 0; i < spikes.length; i++) {
var spike = spikes[i];
if (player.intersects(spike) && !player.invincible) {
player.die(); // Trigger player death
player.invincible = true; // Set player to invincible
LK.setTimeout(function () {
// Reset invincibility after duration
player.invincible = false;
}, player.invincibilityDuration);
}
}
// Check collectible collisions
for (var i = 0; i < collectibles.length; i++) {
var collectible = collectibles[i];
if (!collectible.collected && player.intersects(collectible)) {
if (collectible.collect()) {
// Increase score
LK.setScore(LK.getScore() + 10);
scoreTxt.setText(LK.getScore());
}
}
}
// If we're not on ground and not already jumping, start falling
if (!onGround && !player.isJumping) {
player.isJumping = true;
}
// Check if player reached the end of the level
if (player.x > levelEndX - 300) {
// Level complete, generate new level
currentLevel++;
player.reset();
generateNewLevel();
// Show level complete animation
var levelCompleteTxt = new Text2('LEVEL COMPLETE!', {
size: 120,
fill: 0xFFFFFF
});
levelCompleteTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(levelCompleteTxt);
tween(levelCompleteTxt, {
alpha: 0
}, {
duration: 1500,
onFinish: function onFinish() {
LK.gui.center.removeChild(levelCompleteTxt);
}
});
}
}
// Camera follow player
function updateCamera() {
// Make the camera follow the player horizontally
cameraOffset = player.x - 500;
// Apply camera offset to all elements
for (var i = 0; i < platforms.length; i++) {
platforms[i].x = platforms[i]._originalX - cameraOffset;
}
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].x = obstacles[i]._originalX - cameraOffset;
}
for (var i = 0; i < spikes.length; i++) {
spikes[i].x = spikes[i]._originalX - cameraOffset;
}
for (var i = 0; i < collectibles.length; i++) {
collectibles[i].x = collectibles[i]._originalX - cameraOffset;
}
}
// Handler for tap/click events
game.down = function (x, y, obj) {
if (!gameStarted) {
gameStarted = true;
instructionsTxt.visible = false;
generateNewLevel();
// Start playing the background music
LK.playMusic('gameMusic');
} else {
player.jump();
}
};
// Main game update function
game.update = function () {
if (!gameStarted) {
return;
}
// Update player
player.update();
// Check collisions
checkCollisions();
// Store original positions for camera offset calculations
if (LK.ticks === 1) {
for (var i = 0; i < platforms.length; i++) {
platforms[i]._originalX = platforms[i].x;
}
for (var i = 0; i < obstacles.length; i++) {
obstacles[i]._originalX = obstacles[i].x;
}
for (var i = 0; i < spikes.length; i++) {
spikes[i]._originalX = spikes[i].x;
}
for (var i = 0; i < collectibles.length; i++) {
collectibles[i]._originalX = collectibles[i].x;
}
}
// Update camera
// updateCamera(); // Uncomment to implement scrolling camera
};