/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BluePowerup = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('bluePowerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.lastY = undefined;
self.lastPlayerIntersecting = false;
// Add pulsing animation
tween(graphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(graphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
self.update = function () {
self.y += self.speed;
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.lastY = undefined;
self.lastPlayerIntersecting = false;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var Star = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2 + Math.random() * 3;
self.lastY = undefined;
graphics.alpha = 0.3 + Math.random() * 0.7;
self.update = function () {
self.y += self.speed;
};
return self;
});
var YellowPowerup = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('yellowPowerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.lastY = undefined;
self.lastPlayerIntersecting = false;
// Add rotation animation
tween(graphics, {
rotation: Math.PI * 2
}, {
duration: 2000,
easing: tween.linear,
onFinish: function onFinish() {
graphics.rotation = 0;
}
});
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game variables
var obstacles = [];
var stars = [];
var bluePowerups = [];
var yellowPowerups = [];
var player;
var scoreTimer = 0;
var spawnTimer = 0;
var spawnDelay = 60; // Start spawning every 60 ticks (1 second)
var difficultyTimer = 0;
var starSpawnTimer = 0;
var baseObstacleSpeed = 8;
var baseSpawnDelay = 60;
// Powerup system
var lastBlueSpawnScore = 0;
var lastYellowSpawnScore = 0;
var speedBoostActive = false;
var speedBoostTimer = 0;
var immunityActive = false;
var immunityTimer = 0;
// Create score display
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create player
player = game.addChild(new Player());
player.x = 2048 / 2;
player.y = 2732 - 200;
// Start background music
LK.playMusic('bgMusic');
// Game update function
game.update = function () {
// Calculate difficulty multiplier based on score
var difficultyMultiplier = 1 + LK.getScore() * 0.1;
var speedMultiplier = 1 + LK.getScore() * 0.15;
// Update score every second (60 ticks)
scoreTimer++;
if (scoreTimer >= 60) {
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
// Animate score text scale up and back down
tween(scoreTxt, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(scoreTxt, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 300,
easing: tween.easeIn
});
}
});
scoreTimer = 0;
}
// Spawn blue powerup every 10 scores
if (LK.getScore() >= lastBlueSpawnScore + 10 && LK.getScore() > 0) {
var bluePowerup = new BluePowerup();
bluePowerup.x = Math.random() * (2048 - 50) + 25;
bluePowerup.y = -25;
bluePowerup.lastY = bluePowerup.y;
bluePowerups.push(bluePowerup);
game.addChild(bluePowerup);
lastBlueSpawnScore = LK.getScore();
}
// Spawn yellow powerup every 30 scores
if (LK.getScore() >= lastYellowSpawnScore + 30 && LK.getScore() > 0) {
var yellowPowerup = new YellowPowerup();
yellowPowerup.x = Math.random() * (2048 - 50) + 25;
yellowPowerup.y = -25;
yellowPowerup.lastY = yellowPowerup.y;
yellowPowerups.push(yellowPowerup);
game.addChild(yellowPowerup);
lastYellowSpawnScore = LK.getScore();
}
// Update powerup effects
if (speedBoostActive) {
speedBoostTimer--;
if (speedBoostTimer <= 0) {
speedBoostActive = false;
// Reset player tint
tween(player, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
}
if (immunityActive) {
immunityTimer--;
if (immunityTimer <= 0) {
immunityActive = false;
// Reset player tint
tween(player, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
}
// Spawn background stars
starSpawnTimer++;
if (starSpawnTimer >= Math.max(5, 15 - Math.floor(LK.getScore() / 5))) {
var star = new Star();
star.x = Math.random() * 2048;
star.y = -10;
star.lastY = star.y;
star.speed *= 1 + LK.getScore() * 0.05;
stars.push(star);
game.addChild(star);
starSpawnTimer = 0;
}
// Update stars
for (var s = stars.length - 1; s >= 0; s--) {
var star = stars[s];
if (star.lastY === undefined) star.lastY = star.y;
if (star.lastY <= 2732 + 20 && star.y > 2732 + 20) {
star.destroy();
stars.splice(s, 1);
continue;
}
star.lastY = star.y;
}
// Update blue powerups
for (var b = bluePowerups.length - 1; b >= 0; b--) {
var bluePowerup = bluePowerups[b];
if (bluePowerup.lastY === undefined) bluePowerup.lastY = bluePowerup.y;
// Check if went off screen
if (bluePowerup.lastY <= 2732 + 60 && bluePowerup.y > 2732 + 60) {
bluePowerup.destroy();
bluePowerups.splice(b, 1);
continue;
}
// Check collision with player
var currentIntersecting = bluePowerup.intersects(player);
if (!bluePowerup.lastPlayerIntersecting && currentIntersecting) {
// Activate speed boost for 8 seconds (480 ticks)
speedBoostActive = true;
speedBoostTimer = 480;
// Visual feedback
tween(player, {
tint: 0x2196f3
}, {
duration: 200
});
LK.getSound('powerup').play();
bluePowerup.destroy();
bluePowerups.splice(b, 1);
continue;
}
bluePowerup.lastY = bluePowerup.y;
bluePowerup.lastPlayerIntersecting = currentIntersecting;
}
// Update yellow powerups
for (var y = yellowPowerups.length - 1; y >= 0; y--) {
var yellowPowerup = yellowPowerups[y];
if (yellowPowerup.lastY === undefined) yellowPowerup.lastY = yellowPowerup.y;
// Check if went off screen
if (yellowPowerup.lastY <= 2732 + 60 && yellowPowerup.y > 2732 + 60) {
yellowPowerup.destroy();
yellowPowerups.splice(y, 1);
continue;
}
// Check collision with player
var currentIntersecting = yellowPowerup.intersects(player);
if (!yellowPowerup.lastPlayerIntersecting && currentIntersecting) {
// Activate immunity for 13 seconds (780 ticks)
immunityActive = true;
immunityTimer = 780;
// Visual feedback
tween(player, {
tint: 0xffeb3b
}, {
duration: 200
});
LK.getSound('powerup').play();
yellowPowerup.destroy();
yellowPowerups.splice(y, 1);
continue;
}
yellowPowerup.lastY = yellowPowerup.y;
yellowPowerup.lastPlayerIntersecting = currentIntersecting;
}
// Increase difficulty over time
difficultyTimer++;
if (difficultyTimer >= 180) {
// Every 3 seconds, make it progressively harder
spawnDelay = Math.max(15, baseSpawnDelay - Math.floor(LK.getScore() / 3) * 3);
difficultyTimer = 0;
}
// Spawn obstacles with progressive difficulty
spawnTimer++;
var currentSpawnDelay = Math.max(15, spawnDelay - Math.floor(difficultyMultiplier * 5));
// Apply speed boost effect - spawn obstacles faster
if (speedBoostActive) {
currentSpawnDelay = Math.max(8, Math.floor(currentSpawnDelay / 1.5));
}
if (spawnTimer >= currentSpawnDelay) {
var obstacle = new Obstacle();
obstacle.x = Math.random() * (2048 - 60) + 30;
obstacle.y = -30;
obstacle.lastY = obstacle.y;
// Dramatic speed increase based on score
obstacle.speed = (baseObstacleSpeed + Math.floor(LK.getScore() / 5) * 3) * speedMultiplier;
// Apply speed boost effect - make obstacles faster
if (speedBoostActive) {
obstacle.speed *= 1.5;
}
// More dramatic size variation
var sizeMultiplier = 0.8 + Math.random() * (0.7 + LK.getScore() * 0.05);
obstacle.scaleX = sizeMultiplier;
obstacle.scaleY = sizeMultiplier;
// Add tween effect for more dynamic obstacles
tween(obstacle, {
rotation: (Math.random() - 0.5) * Math.PI
}, {
duration: 1000 + Math.random() * 2000
});
obstacles.push(obstacle);
game.addChild(obstacle);
spawnTimer = 0;
}
// Update obstacles and check collisions
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
// Initialize lastY if undefined
if (obstacle.lastY === undefined) obstacle.lastY = obstacle.y;
// Check if obstacle went off screen
if (obstacle.lastY <= 2732 + 100 && obstacle.y > 2732 + 100) {
obstacle.destroy();
obstacles.splice(i, 1);
continue;
}
// Check collision with player
var currentIntersecting = obstacle.intersects(player);
if (!obstacle.lastPlayerIntersecting && currentIntersecting) {
// Check if player has immunity
if (!immunityActive) {
// Game over on collision
LK.getSound('gameOver').play();
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver();
return;
} else {
// Player is immune - flash effect but no game over
LK.effects.flashObject(player, 0xffffff, 200);
}
}
// Update last states
obstacle.lastY = obstacle.y;
obstacle.lastPlayerIntersecting = currentIntersecting;
}
};
// Touch/drag controls
function handleMove(x, y, obj) {
// Always move player horizontally to follow mouse, regardless of drag state
player.x = Math.max(40, Math.min(2048 - 40, x)); // Keep player within bounds
player.y = 2732 - 200; // Keep player centered vertically at bottom
}
game.move = handleMove;
game.down = function (x, y, obj) {
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
// No drag logic needed anymore
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BluePowerup = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('bluePowerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.lastY = undefined;
self.lastPlayerIntersecting = false;
// Add pulsing animation
tween(graphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(graphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
self.update = function () {
self.y += self.speed;
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.lastY = undefined;
self.lastPlayerIntersecting = false;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var Star = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2 + Math.random() * 3;
self.lastY = undefined;
graphics.alpha = 0.3 + Math.random() * 0.7;
self.update = function () {
self.y += self.speed;
};
return self;
});
var YellowPowerup = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('yellowPowerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.lastY = undefined;
self.lastPlayerIntersecting = false;
// Add rotation animation
tween(graphics, {
rotation: Math.PI * 2
}, {
duration: 2000,
easing: tween.linear,
onFinish: function onFinish() {
graphics.rotation = 0;
}
});
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game variables
var obstacles = [];
var stars = [];
var bluePowerups = [];
var yellowPowerups = [];
var player;
var scoreTimer = 0;
var spawnTimer = 0;
var spawnDelay = 60; // Start spawning every 60 ticks (1 second)
var difficultyTimer = 0;
var starSpawnTimer = 0;
var baseObstacleSpeed = 8;
var baseSpawnDelay = 60;
// Powerup system
var lastBlueSpawnScore = 0;
var lastYellowSpawnScore = 0;
var speedBoostActive = false;
var speedBoostTimer = 0;
var immunityActive = false;
var immunityTimer = 0;
// Create score display
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create player
player = game.addChild(new Player());
player.x = 2048 / 2;
player.y = 2732 - 200;
// Start background music
LK.playMusic('bgMusic');
// Game update function
game.update = function () {
// Calculate difficulty multiplier based on score
var difficultyMultiplier = 1 + LK.getScore() * 0.1;
var speedMultiplier = 1 + LK.getScore() * 0.15;
// Update score every second (60 ticks)
scoreTimer++;
if (scoreTimer >= 60) {
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
// Animate score text scale up and back down
tween(scoreTxt, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(scoreTxt, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 300,
easing: tween.easeIn
});
}
});
scoreTimer = 0;
}
// Spawn blue powerup every 10 scores
if (LK.getScore() >= lastBlueSpawnScore + 10 && LK.getScore() > 0) {
var bluePowerup = new BluePowerup();
bluePowerup.x = Math.random() * (2048 - 50) + 25;
bluePowerup.y = -25;
bluePowerup.lastY = bluePowerup.y;
bluePowerups.push(bluePowerup);
game.addChild(bluePowerup);
lastBlueSpawnScore = LK.getScore();
}
// Spawn yellow powerup every 30 scores
if (LK.getScore() >= lastYellowSpawnScore + 30 && LK.getScore() > 0) {
var yellowPowerup = new YellowPowerup();
yellowPowerup.x = Math.random() * (2048 - 50) + 25;
yellowPowerup.y = -25;
yellowPowerup.lastY = yellowPowerup.y;
yellowPowerups.push(yellowPowerup);
game.addChild(yellowPowerup);
lastYellowSpawnScore = LK.getScore();
}
// Update powerup effects
if (speedBoostActive) {
speedBoostTimer--;
if (speedBoostTimer <= 0) {
speedBoostActive = false;
// Reset player tint
tween(player, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
}
if (immunityActive) {
immunityTimer--;
if (immunityTimer <= 0) {
immunityActive = false;
// Reset player tint
tween(player, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
}
// Spawn background stars
starSpawnTimer++;
if (starSpawnTimer >= Math.max(5, 15 - Math.floor(LK.getScore() / 5))) {
var star = new Star();
star.x = Math.random() * 2048;
star.y = -10;
star.lastY = star.y;
star.speed *= 1 + LK.getScore() * 0.05;
stars.push(star);
game.addChild(star);
starSpawnTimer = 0;
}
// Update stars
for (var s = stars.length - 1; s >= 0; s--) {
var star = stars[s];
if (star.lastY === undefined) star.lastY = star.y;
if (star.lastY <= 2732 + 20 && star.y > 2732 + 20) {
star.destroy();
stars.splice(s, 1);
continue;
}
star.lastY = star.y;
}
// Update blue powerups
for (var b = bluePowerups.length - 1; b >= 0; b--) {
var bluePowerup = bluePowerups[b];
if (bluePowerup.lastY === undefined) bluePowerup.lastY = bluePowerup.y;
// Check if went off screen
if (bluePowerup.lastY <= 2732 + 60 && bluePowerup.y > 2732 + 60) {
bluePowerup.destroy();
bluePowerups.splice(b, 1);
continue;
}
// Check collision with player
var currentIntersecting = bluePowerup.intersects(player);
if (!bluePowerup.lastPlayerIntersecting && currentIntersecting) {
// Activate speed boost for 8 seconds (480 ticks)
speedBoostActive = true;
speedBoostTimer = 480;
// Visual feedback
tween(player, {
tint: 0x2196f3
}, {
duration: 200
});
LK.getSound('powerup').play();
bluePowerup.destroy();
bluePowerups.splice(b, 1);
continue;
}
bluePowerup.lastY = bluePowerup.y;
bluePowerup.lastPlayerIntersecting = currentIntersecting;
}
// Update yellow powerups
for (var y = yellowPowerups.length - 1; y >= 0; y--) {
var yellowPowerup = yellowPowerups[y];
if (yellowPowerup.lastY === undefined) yellowPowerup.lastY = yellowPowerup.y;
// Check if went off screen
if (yellowPowerup.lastY <= 2732 + 60 && yellowPowerup.y > 2732 + 60) {
yellowPowerup.destroy();
yellowPowerups.splice(y, 1);
continue;
}
// Check collision with player
var currentIntersecting = yellowPowerup.intersects(player);
if (!yellowPowerup.lastPlayerIntersecting && currentIntersecting) {
// Activate immunity for 13 seconds (780 ticks)
immunityActive = true;
immunityTimer = 780;
// Visual feedback
tween(player, {
tint: 0xffeb3b
}, {
duration: 200
});
LK.getSound('powerup').play();
yellowPowerup.destroy();
yellowPowerups.splice(y, 1);
continue;
}
yellowPowerup.lastY = yellowPowerup.y;
yellowPowerup.lastPlayerIntersecting = currentIntersecting;
}
// Increase difficulty over time
difficultyTimer++;
if (difficultyTimer >= 180) {
// Every 3 seconds, make it progressively harder
spawnDelay = Math.max(15, baseSpawnDelay - Math.floor(LK.getScore() / 3) * 3);
difficultyTimer = 0;
}
// Spawn obstacles with progressive difficulty
spawnTimer++;
var currentSpawnDelay = Math.max(15, spawnDelay - Math.floor(difficultyMultiplier * 5));
// Apply speed boost effect - spawn obstacles faster
if (speedBoostActive) {
currentSpawnDelay = Math.max(8, Math.floor(currentSpawnDelay / 1.5));
}
if (spawnTimer >= currentSpawnDelay) {
var obstacle = new Obstacle();
obstacle.x = Math.random() * (2048 - 60) + 30;
obstacle.y = -30;
obstacle.lastY = obstacle.y;
// Dramatic speed increase based on score
obstacle.speed = (baseObstacleSpeed + Math.floor(LK.getScore() / 5) * 3) * speedMultiplier;
// Apply speed boost effect - make obstacles faster
if (speedBoostActive) {
obstacle.speed *= 1.5;
}
// More dramatic size variation
var sizeMultiplier = 0.8 + Math.random() * (0.7 + LK.getScore() * 0.05);
obstacle.scaleX = sizeMultiplier;
obstacle.scaleY = sizeMultiplier;
// Add tween effect for more dynamic obstacles
tween(obstacle, {
rotation: (Math.random() - 0.5) * Math.PI
}, {
duration: 1000 + Math.random() * 2000
});
obstacles.push(obstacle);
game.addChild(obstacle);
spawnTimer = 0;
}
// Update obstacles and check collisions
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
// Initialize lastY if undefined
if (obstacle.lastY === undefined) obstacle.lastY = obstacle.y;
// Check if obstacle went off screen
if (obstacle.lastY <= 2732 + 100 && obstacle.y > 2732 + 100) {
obstacle.destroy();
obstacles.splice(i, 1);
continue;
}
// Check collision with player
var currentIntersecting = obstacle.intersects(player);
if (!obstacle.lastPlayerIntersecting && currentIntersecting) {
// Check if player has immunity
if (!immunityActive) {
// Game over on collision
LK.getSound('gameOver').play();
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver();
return;
} else {
// Player is immune - flash effect but no game over
LK.effects.flashObject(player, 0xffffff, 200);
}
}
// Update last states
obstacle.lastY = obstacle.y;
obstacle.lastPlayerIntersecting = currentIntersecting;
}
};
// Touch/drag controls
function handleMove(x, y, obj) {
// Always move player horizontally to follow mouse, regardless of drag state
player.x = Math.max(40, Math.min(2048 - 40, x)); // Keep player within bounds
player.y = 2732 - 200; // Keep player centered vertically at bottom
}
game.move = handleMove;
game.down = function (x, y, obj) {
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
// No drag logic needed anymore
};