/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 15;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 15;
self.type = 'shield'; // Types: shield, speed, health
self.update = function () {
self.x -= self.speed;
// Gentle floating animation
powerupGraphics.y = Math.sin(LK.ticks * 0.1) * 10;
powerupGraphics.rotation += 0.05;
};
return self;
});
var SnowParticle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
particleGraphics.tint = 0xFFFFFF;
particleGraphics.scaleX = 0.3;
particleGraphics.scaleY = 0.3;
self.velocityX = -2 - Math.random() * 3; // Move left
self.velocityY = (Math.random() - 0.5) * 2; // Small vertical variation
self.life = 60 + Math.random() * 60; // 1-2 seconds
self.maxLife = self.life;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.life--;
// Fade out over time
particleGraphics.alpha = self.life / self.maxLife;
};
return self;
});
var Snowball = Container.expand(function () {
var self = Container.call(this);
var snowballGraphics = self.attachAsset('snowball', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 10;
self.baseSpeed = 10;
self.growthRate = 0.002;
self.update = function () {
// Keep snowball stationary - no movement
// Grow by 0.5 pixels per second (0.5/60 pixels per frame at 60fps)
var growthPerFrame = 0.5 / 60;
// Directly modify width and height for size changes
snowballGraphics.width += growthPerFrame;
snowballGraphics.height += growthPerFrame;
};
return self;
});
var Twilight = Container.expand(function () {
var self = Container.call(this);
var twilightGraphics = self.attachAsset('twilight', {
anchorX: 0.5,
anchorY: 0.5
});
self.verticalSpeed = 0;
self.maxSpeed = 15;
self.acceleration = 1.2;
self.deceleration = 0.8;
self.horizontalSpeed = 12; // Forward movement speed
self.health = 3;
self.isShielded = false;
self.shieldTime = 0;
self.update = function () {
// Keep Twilight within screen bounds
if (self.x < 100) {
self.x = 100;
}
if (self.x > 1948) {
self.x = 1948;
}
if (self.y < 100) {
self.y = 100;
}
if (self.y > 2632) {
self.y = 2632;
}
// Handle shield effect
if (self.isShielded) {
self.shieldTime--;
twilightGraphics.tint = Math.sin(LK.ticks * 0.3) > 0 ? 0xFFFFFF : 0x00FFFF;
if (self.shieldTime <= 0) {
self.isShielded = false;
twilightGraphics.tint = 0xFFFFFF;
}
}
};
self.moveUp = function () {
self.verticalSpeed = Math.max(-self.maxSpeed, self.verticalSpeed - self.acceleration);
};
self.moveDown = function () {
self.verticalSpeed = Math.min(self.maxSpeed, self.verticalSpeed + self.acceleration);
};
self.takeDamage = function () {
if (!self.isShielded) {
self.health--;
LK.getSound('hit').play();
LK.effects.flashObject(self, 0xFF0000, 500);
return true;
}
return false;
};
self.activateShield = function () {
self.isShielded = true;
self.shieldTime = 300; // 5 seconds at 60fps
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Add background
var background = game.attachAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
// Game variables
var twilight;
var snowball;
var obstacles = [];
var powerups = [];
var snowParticles = [];
var gameSpeed = 1;
var survivalTime = 0;
var targetSurvivalTime = 3600; // 60 seconds at 60fps
var isGameActive = true;
// UI elements
var healthTxt = new Text2('Health: 3', {
size: 80,
fill: 0xFFFFFF
});
healthTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(healthTxt);
healthTxt.x = 120; // Offset from menu icon
var timeTxt = new Text2('Time: 0s', {
size: 80,
fill: 0xFFFFFF
});
timeTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(timeTxt);
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreTxt);
// Initialize Twilight
twilight = game.addChild(new Twilight());
twilight.x = 400;
twilight.y = 1366; // Center vertically
// Initialize Snowball
snowball = game.addChild(new Snowball());
snowball.x = 100; // Right up against the left edge of screen
snowball.y = 1366; // Center vertically
// Snowball will grow gradually via its update method
// Drag controls
var isDragging = false;
game.down = function (x, y, obj) {
if (!isGameActive) return;
isDragging = true;
twilight.x = x;
twilight.y = y;
};
game.move = function (x, y, obj) {
if (!isGameActive || !isDragging) return;
twilight.x = x;
twilight.y = y;
};
game.up = function (x, y, obj) {
isDragging = false;
};
// Spawn obstacles
function spawnObstacle() {
var obstacle = new Obstacle();
obstacle.x = 2200;
obstacle.y = 200 + Math.random() * 2300; // Random vertical position
obstacles.push(obstacle);
game.addChild(obstacle);
}
// Spawn power-ups
function spawnPowerUp() {
var powerup = new PowerUp();
powerup.x = 2200;
powerup.y = 300 + Math.random() * 2100;
// Randomly assign power-up type
var types = ['shield'];
powerup.type = types[Math.floor(Math.random() * types.length)];
// Color based on type
var powerupGraphics = powerup.children[0];
if (powerup.type === 'shield') {
powerupGraphics.tint = 0x00FFFF;
}
powerups.push(powerup);
game.addChild(powerup);
}
// Update score display
function updateUI() {
healthTxt.setText('Health: ' + twilight.health);
timeTxt.setText('Time: ' + Math.floor(survivalTime / 60) + 's');
scoreTxt.setText('Score: ' + LK.getScore());
}
// Main game update
game.update = function () {
if (!isGameActive) return;
survivalTime++;
// Increase game speed over time
gameSpeed = 1 + survivalTime * 0.0002;
// Spawn obstacles
if (LK.ticks % Math.max(60, 120 - Math.floor(survivalTime * 0.02)) === 0) {
spawnObstacle();
}
// Spawn power-ups occasionally
if (LK.ticks % 600 === 0) {
// Every 10 seconds
spawnPowerUp();
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
// Remove off-screen obstacles
if (obstacle.x < -100) {
obstacle.destroy();
obstacles.splice(i, 1);
LK.setScore(LK.getScore() + 10);
continue;
}
// Check collision with snowball - obstacle breaks
if (obstacle.intersects(snowball)) {
LK.effects.flashObject(obstacle, 0xFFFFFF, 200);
obstacle.destroy();
obstacles.splice(i, 1);
LK.setScore(LK.getScore() + 25);
continue;
}
// Check collision with Twilight
if (obstacle.intersects(twilight)) {
if (twilight.takeDamage()) {
obstacle.destroy();
obstacles.splice(i, 1);
if (twilight.health <= 0) {
isGameActive = false;
LK.effects.flashScreen(0xFF0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
return;
}
}
}
}
// Update power-ups
for (var j = powerups.length - 1; j >= 0; j--) {
var powerup = powerups[j];
// Remove off-screen power-ups
if (powerup.x < -100) {
powerup.destroy();
powerups.splice(j, 1);
continue;
}
// Check collection by Twilight
if (powerup.intersects(twilight)) {
LK.getSound('collect').play();
if (powerup.type === 'shield') {
twilight.activateShield();
}
LK.setScore(LK.getScore() + 50);
powerup.destroy();
powerups.splice(j, 1);
}
}
// Check if snowball caught Twilight
if (snowball.intersects(twilight) && !twilight.isShielded) {
isGameActive = false;
LK.effects.flashScreen(0xFF0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
return;
}
// Check victory condition
if (survivalTime >= targetSurvivalTime) {
isGameActive = false;
LK.effects.flashScreen(0x00FF00, 1000);
LK.setTimeout(function () {
LK.showYouWin();
}, 1000);
return;
}
// Spawn snow particles from snowball
if (LK.ticks % 5 === 0) {
// Every 5 frames
var particle = new SnowParticle();
// Spawn from bottom of snowball
var snowballScale = 1 + LK.ticks * snowball.growthRate * 0.1;
var snowballRadius = 100 * snowballScale;
particle.x = snowball.x + (Math.random() - 0.5) * snowballRadius * 0.5;
particle.y = snowball.y + snowballRadius * 0.7; // Bottom of snowball
snowParticles.push(particle);
game.addChild(particle);
}
// Update and remove old snow particles
for (var p = snowParticles.length - 1; p >= 0; p--) {
var particle = snowParticles[p];
if (particle.life <= 0) {
particle.destroy();
snowParticles.splice(p, 1);
}
}
// Snowball stays stationary - no chase logic needed
updateUI();
};
// Start background music
LK.playMusic('chase'); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 15;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 15;
self.type = 'shield'; // Types: shield, speed, health
self.update = function () {
self.x -= self.speed;
// Gentle floating animation
powerupGraphics.y = Math.sin(LK.ticks * 0.1) * 10;
powerupGraphics.rotation += 0.05;
};
return self;
});
var SnowParticle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
particleGraphics.tint = 0xFFFFFF;
particleGraphics.scaleX = 0.3;
particleGraphics.scaleY = 0.3;
self.velocityX = -2 - Math.random() * 3; // Move left
self.velocityY = (Math.random() - 0.5) * 2; // Small vertical variation
self.life = 60 + Math.random() * 60; // 1-2 seconds
self.maxLife = self.life;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.life--;
// Fade out over time
particleGraphics.alpha = self.life / self.maxLife;
};
return self;
});
var Snowball = Container.expand(function () {
var self = Container.call(this);
var snowballGraphics = self.attachAsset('snowball', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 10;
self.baseSpeed = 10;
self.growthRate = 0.002;
self.update = function () {
// Keep snowball stationary - no movement
// Grow by 0.5 pixels per second (0.5/60 pixels per frame at 60fps)
var growthPerFrame = 0.5 / 60;
// Directly modify width and height for size changes
snowballGraphics.width += growthPerFrame;
snowballGraphics.height += growthPerFrame;
};
return self;
});
var Twilight = Container.expand(function () {
var self = Container.call(this);
var twilightGraphics = self.attachAsset('twilight', {
anchorX: 0.5,
anchorY: 0.5
});
self.verticalSpeed = 0;
self.maxSpeed = 15;
self.acceleration = 1.2;
self.deceleration = 0.8;
self.horizontalSpeed = 12; // Forward movement speed
self.health = 3;
self.isShielded = false;
self.shieldTime = 0;
self.update = function () {
// Keep Twilight within screen bounds
if (self.x < 100) {
self.x = 100;
}
if (self.x > 1948) {
self.x = 1948;
}
if (self.y < 100) {
self.y = 100;
}
if (self.y > 2632) {
self.y = 2632;
}
// Handle shield effect
if (self.isShielded) {
self.shieldTime--;
twilightGraphics.tint = Math.sin(LK.ticks * 0.3) > 0 ? 0xFFFFFF : 0x00FFFF;
if (self.shieldTime <= 0) {
self.isShielded = false;
twilightGraphics.tint = 0xFFFFFF;
}
}
};
self.moveUp = function () {
self.verticalSpeed = Math.max(-self.maxSpeed, self.verticalSpeed - self.acceleration);
};
self.moveDown = function () {
self.verticalSpeed = Math.min(self.maxSpeed, self.verticalSpeed + self.acceleration);
};
self.takeDamage = function () {
if (!self.isShielded) {
self.health--;
LK.getSound('hit').play();
LK.effects.flashObject(self, 0xFF0000, 500);
return true;
}
return false;
};
self.activateShield = function () {
self.isShielded = true;
self.shieldTime = 300; // 5 seconds at 60fps
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Add background
var background = game.attachAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
// Game variables
var twilight;
var snowball;
var obstacles = [];
var powerups = [];
var snowParticles = [];
var gameSpeed = 1;
var survivalTime = 0;
var targetSurvivalTime = 3600; // 60 seconds at 60fps
var isGameActive = true;
// UI elements
var healthTxt = new Text2('Health: 3', {
size: 80,
fill: 0xFFFFFF
});
healthTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(healthTxt);
healthTxt.x = 120; // Offset from menu icon
var timeTxt = new Text2('Time: 0s', {
size: 80,
fill: 0xFFFFFF
});
timeTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(timeTxt);
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreTxt);
// Initialize Twilight
twilight = game.addChild(new Twilight());
twilight.x = 400;
twilight.y = 1366; // Center vertically
// Initialize Snowball
snowball = game.addChild(new Snowball());
snowball.x = 100; // Right up against the left edge of screen
snowball.y = 1366; // Center vertically
// Snowball will grow gradually via its update method
// Drag controls
var isDragging = false;
game.down = function (x, y, obj) {
if (!isGameActive) return;
isDragging = true;
twilight.x = x;
twilight.y = y;
};
game.move = function (x, y, obj) {
if (!isGameActive || !isDragging) return;
twilight.x = x;
twilight.y = y;
};
game.up = function (x, y, obj) {
isDragging = false;
};
// Spawn obstacles
function spawnObstacle() {
var obstacle = new Obstacle();
obstacle.x = 2200;
obstacle.y = 200 + Math.random() * 2300; // Random vertical position
obstacles.push(obstacle);
game.addChild(obstacle);
}
// Spawn power-ups
function spawnPowerUp() {
var powerup = new PowerUp();
powerup.x = 2200;
powerup.y = 300 + Math.random() * 2100;
// Randomly assign power-up type
var types = ['shield'];
powerup.type = types[Math.floor(Math.random() * types.length)];
// Color based on type
var powerupGraphics = powerup.children[0];
if (powerup.type === 'shield') {
powerupGraphics.tint = 0x00FFFF;
}
powerups.push(powerup);
game.addChild(powerup);
}
// Update score display
function updateUI() {
healthTxt.setText('Health: ' + twilight.health);
timeTxt.setText('Time: ' + Math.floor(survivalTime / 60) + 's');
scoreTxt.setText('Score: ' + LK.getScore());
}
// Main game update
game.update = function () {
if (!isGameActive) return;
survivalTime++;
// Increase game speed over time
gameSpeed = 1 + survivalTime * 0.0002;
// Spawn obstacles
if (LK.ticks % Math.max(60, 120 - Math.floor(survivalTime * 0.02)) === 0) {
spawnObstacle();
}
// Spawn power-ups occasionally
if (LK.ticks % 600 === 0) {
// Every 10 seconds
spawnPowerUp();
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
// Remove off-screen obstacles
if (obstacle.x < -100) {
obstacle.destroy();
obstacles.splice(i, 1);
LK.setScore(LK.getScore() + 10);
continue;
}
// Check collision with snowball - obstacle breaks
if (obstacle.intersects(snowball)) {
LK.effects.flashObject(obstacle, 0xFFFFFF, 200);
obstacle.destroy();
obstacles.splice(i, 1);
LK.setScore(LK.getScore() + 25);
continue;
}
// Check collision with Twilight
if (obstacle.intersects(twilight)) {
if (twilight.takeDamage()) {
obstacle.destroy();
obstacles.splice(i, 1);
if (twilight.health <= 0) {
isGameActive = false;
LK.effects.flashScreen(0xFF0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
return;
}
}
}
}
// Update power-ups
for (var j = powerups.length - 1; j >= 0; j--) {
var powerup = powerups[j];
// Remove off-screen power-ups
if (powerup.x < -100) {
powerup.destroy();
powerups.splice(j, 1);
continue;
}
// Check collection by Twilight
if (powerup.intersects(twilight)) {
LK.getSound('collect').play();
if (powerup.type === 'shield') {
twilight.activateShield();
}
LK.setScore(LK.getScore() + 50);
powerup.destroy();
powerups.splice(j, 1);
}
}
// Check if snowball caught Twilight
if (snowball.intersects(twilight) && !twilight.isShielded) {
isGameActive = false;
LK.effects.flashScreen(0xFF0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
return;
}
// Check victory condition
if (survivalTime >= targetSurvivalTime) {
isGameActive = false;
LK.effects.flashScreen(0x00FF00, 1000);
LK.setTimeout(function () {
LK.showYouWin();
}, 1000);
return;
}
// Spawn snow particles from snowball
if (LK.ticks % 5 === 0) {
// Every 5 frames
var particle = new SnowParticle();
// Spawn from bottom of snowball
var snowballScale = 1 + LK.ticks * snowball.growthRate * 0.1;
var snowballRadius = 100 * snowballScale;
particle.x = snowball.x + (Math.random() - 0.5) * snowballRadius * 0.5;
particle.y = snowball.y + snowballRadius * 0.7; // Bottom of snowball
snowParticles.push(particle);
game.addChild(particle);
}
// Update and remove old snow particles
for (var p = snowParticles.length - 1; p >= 0; p--) {
var particle = snowParticles[p];
if (particle.life <= 0) {
particle.destroy();
snowParticles.splice(p, 1);
}
}
// Snowball stays stationary - no chase logic needed
updateUI();
};
// Start background music
LK.playMusic('chase');