/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Collectible = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'button';
var collectibleGraphics = self.attachAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.update = function () {
// Simple animation
collectibleGraphics.rotation += 0.02;
// Floating effect
collectibleGraphics.y = Math.sin(LK.ticks * 0.05) * 5;
};
self.collect = function () {
if (self.collected) {
return;
}
self.collected = true;
LK.getSound('collect').play();
// Collect animation
tween(collectibleGraphics, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
return self.type;
};
return self;
});
var Hazard = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'scissors';
var hazardGraphics = self.attachAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5
});
self.moving = false;
self.moveSpeed = 0;
self.moveDirection = 1;
self.moveDistance = 0;
self.startX = 0;
self.setMoving = function (speed, distance) {
self.moving = true;
self.moveSpeed = speed;
self.moveDistance = distance;
self.startX = self.x;
};
self.update = function () {
if (self.moving) {
self.x += self.moveSpeed * self.moveDirection;
if (Math.abs(self.x - self.startX) > self.moveDistance) {
self.moveDirection *= -1;
}
}
// Animation
if (self.type === 'scissors') {
hazardGraphics.rotation = Math.sin(LK.ticks * 0.05) * 0.2;
}
};
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;
self.moving = false;
self.moveSpeed = 0;
self.moveDirection = 1;
self.moveDistance = 0;
self.startX = 0;
self.setMoving = function (speed, distance) {
self.moving = true;
self.moveSpeed = speed;
self.moveDistance = distance;
self.startX = self.x;
};
self.update = function () {
if (self.moving) {
self.x += self.moveSpeed * self.moveDirection;
if (Math.abs(self.x - self.startX) > self.moveDistance) {
self.moveDirection *= -1;
}
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'random';
self.collected = false;
// Choose a random power-up type
var types = ['fly', 'big', 'invincible'];
self.powerType = types[Math.floor(Math.random() * types.length)];
// Set color based on type
if (self.powerType === 'fly') {
powerupGraphics.tint = 0x88CCFF;
} else if (self.powerType === 'big') {
powerupGraphics.tint = 0xFF8866;
} else if (self.powerType === 'invincible') {
powerupGraphics.tint = 0xFFDD44;
}
self.update = function () {
// Floating and rotation animation
powerupGraphics.rotation += 0.03;
powerupGraphics.y = Math.sin(LK.ticks * 0.1) * 8;
};
self.collect = function () {
if (self.collected) {
return null;
}
self.collected = true;
// Collect animation
tween(powerupGraphics, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
return self.powerType;
};
return self;
});
var Sackboy = Container.expand(function () {
var self = Container.call(this);
var body = self.attachAsset('sackboy', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xDDAA66
});
// Physics properties
self.velocity = {
x: 0,
y: 0
};
self.gravity = 0.5;
self.bounce = 0.8;
self.grounded = false;
self.alive = true;
self.powered = false;
self.powerType = null;
self.powerTime = 0;
// Apply physics
self.update = function () {
if (!self.alive) {
return;
}
// Apply gravity
self.velocity.y += self.gravity;
// Apply velocity
self.x += self.velocity.x;
self.y += self.velocity.y;
// Handle power-ups
if (self.powered) {
self.powerTime--;
// Power-up effects
if (self.powerType === 'fly') {
self.velocity.y = Math.min(self.velocity.y, 1);
} else if (self.powerType === 'big') {
// Already scaled in activatePower
} else if (self.powerType === 'invincible') {
// Visual pulsing effect
body.alpha = 0.5 + Math.sin(LK.ticks * 0.2) * 0.5;
}
// End power-up
if (self.powerTime <= 0) {
self.deactivatePower();
}
}
// Screen boundaries
if (self.x < 50) {
self.x = 50;
self.velocity.x *= -0.5;
} else if (self.x > 2048 - 50) {
self.x = 2048 - 50;
self.velocity.x *= -0.5;
}
// Bottom boundary - game over
if (self.y > 2732 + 100) {
self.die();
}
// Simple animation
body.rotation += self.velocity.x * 0.01;
};
self.bounce = function (power) {
self.velocity.y = -power;
self.grounded = false;
LK.getSound('bounce').play();
};
self.activatePower = function (type) {
self.powered = true;
self.powerType = type;
self.powerTime = 300; // 5 seconds at 60fps
if (type === 'big') {
tween(body, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeOut
});
} else if (type === 'invincible') {
body.tint = 0xFFDD44;
} else if (type === 'fly') {
body.tint = 0x88CCFF;
}
LK.getSound('powerup').play();
};
self.deactivatePower = function () {
self.powered = false;
// Reset visual effects
if (self.powerType === 'big') {
tween(body, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
} else if (self.powerType === 'invincible' || self.powerType === 'fly') {
body.tint = 0xDDAA66;
body.alpha = 1;
}
self.powerType = null;
};
self.die = function () {
if (!self.alive) {
return;
}
self.alive = false;
LK.getSound('hurt').play();
// Visual effect for death
tween(body, {
alpha: 0,
rotation: Math.PI * 4,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 1000,
easing: tween.easeIn,
onFinish: function onFinish() {
LK.showGameOver();
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x88BBCC
});
/****
* Game Code
****/
// Game variables
var sackboy;
var platforms = [];
var collectibles = [];
var hazards = [];
var powerups = [];
var score = 0;
var level = 1;
var maxLevel = 3;
var touchStart = {
x: 0,
y: 0
};
var touchDragging = false;
// UI elements
var scoreTxt;
var levelTxt;
var instructionsTxt;
function initGame() {
// Reset game state
platforms = [];
collectibles = [];
hazards = [];
powerups = [];
score = 0;
// Get saved level or start at level 1
level = storage.level || 1;
if (level > maxLevel) {
level = 1;
}
// Set up UI
setupUI();
// Create Sackboy
sackboy = new Sackboy();
sackboy.x = 1024;
sackboy.y = 2000;
game.addChild(sackboy);
// Create level based on current level
createLevel(level);
// Play background music
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 0.6,
duration: 1000
}
});
}
function setupUI() {
// Score text
scoreTxt = new Text2('Buttons: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
// Level text
levelTxt = new Text2('Level ' + level, {
size: 80,
fill: 0xFFFFFF
});
levelTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(levelTxt);
// Instructions
instructionsTxt = new Text2('Tilt to move Sackboy\nCollect buttons & bounce higher!', {
size: 60,
fill: 0xFFFFFF
});
instructionsTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(instructionsTxt);
// Hide instructions after 3 seconds
LK.setTimeout(function () {
tween(instructionsTxt, {
alpha: 0
}, {
duration: 1000
});
}, 3000);
}
function createLevel(levelNum) {
// Position platforms and collectibles based on level
if (levelNum === 1) {
// Level 1: Simple introduction level
createPlatform(1024, 2200);
createPlatform(600, 1900);
createPlatform(1450, 1900);
createPlatform(1024, 1600);
createPlatform(600, 1300);
createPlatform(1450, 1300);
createPlatform(1024, 1000);
createPlatform(600, 700);
createPlatform(1450, 700);
// Add collectibles
createCollectible('button', 600, 1800);
createCollectible('button', 1450, 1800);
createCollectible('button', 1024, 1500);
createCollectible('yarn', 600, 1200);
createCollectible('button', 1450, 1200);
createCollectible('yarn', 1024, 900);
// Add power-up
createPowerUp(1024, 600);
} else if (levelNum === 2) {
// Level 2: Add some moving platforms and hazards
createPlatform(1024, 2200);
var movingPlatform1 = createPlatform(600, 1900);
movingPlatform1.setMoving(2, 300);
createPlatform(1450, 1900);
createPlatform(1024, 1600);
// Add hazards
createHazard('scissors', 1024, 1500);
var movingPlatform2 = createPlatform(600, 1300);
movingPlatform2.setMoving(3, 400);
createPlatform(1450, 1300);
createPlatform(1024, 1000);
createHazard('thread', 600, 900);
createPlatform(1450, 700);
// Add collectibles
createCollectible('button', 600, 1800);
createCollectible('button', 1450, 1800);
createCollectible('yarn', 800, 1500);
createCollectible('button', 1250, 1500);
createCollectible('button', 600, 1200);
createCollectible('yarn', 1450, 1200);
createCollectible('yarn', 1024, 900);
createCollectible('button', 1450, 600);
// Add power-ups
createPowerUp(800, 600);
} else if (levelNum === 3) {
// Level 3: Most challenging level
createPlatform(1024, 2200);
var movingPlatform1 = createPlatform(600, 1900);
movingPlatform1.setMoving(3, 400);
var movingPlatform2 = createPlatform(1450, 1800);
movingPlatform2.setMoving(4, 300);
createPlatform(1024, 1600);
// Add hazards
createHazard('scissors', 800, 1500);
createHazard('scissors', 1250, 1500);
var movingHazard = createHazard('thread', 1024, 1400);
movingHazard.setMoving(5, 500);
var movingPlatform3 = createPlatform(600, 1300);
movingPlatform3.setMoving(3, 350);
var movingPlatform4 = createPlatform(1450, 1200);
movingPlatform4.setMoving(4, 400);
createPlatform(1024, 1000);
createHazard('thread', 600, 900);
createHazard('scissors', 1450, 900);
createPlatform(800, 700);
createPlatform(1250, 600);
// Add collectibles
createCollectible('button', 600, 1800);
createCollectible('yarn', 1450, 1700);
createCollectible('button', 800, 1500);
createCollectible('button', 1250, 1500);
createCollectible('yarn', 600, 1200);
createCollectible('button', 1450, 1100);
createCollectible('yarn', 1024, 900);
createCollectible('button', 800, 600);
createCollectible('yarn', 1250, 500);
// Add power-ups
createPowerUp(600, 800);
createPowerUp(1450, 800);
}
}
function createPlatform(x, y) {
var platform = new Platform();
platform.x = x;
platform.y = y;
game.addChild(platform);
platforms.push(platform);
return platform;
}
function createCollectible(type, x, y) {
var collectible = new Collectible(type);
collectible.x = x;
collectible.y = y;
game.addChild(collectible);
collectibles.push(collectible);
return collectible;
}
function createHazard(type, x, y) {
var hazard = new Hazard(type);
hazard.x = x;
hazard.y = y;
game.addChild(hazard);
hazards.push(hazard);
return hazard;
}
function createPowerUp(x, y) {
var powerup = new PowerUp();
powerup.x = x;
powerup.y = y;
game.addChild(powerup);
powerups.push(powerup);
return powerup;
}
function updateScore(points) {
score += points;
scoreTxt.setText('Buttons: ' + score);
// Check win condition
if (score >= 10) {
completeLevel();
}
}
function completeLevel() {
// Save progress
level++;
storage.level = level;
if (level > maxLevel) {
// Player completed all levels
LK.showYouWin();
} else {
// Show level complete message
var levelCompleteTxt = new Text2('Level Complete!', {
size: 120,
fill: 0xFFFFFF
});
levelCompleteTxt.anchor.set(0.5, 0.5);
levelCompleteTxt.x = 1024;
levelCompleteTxt.y = 1366;
game.addChild(levelCompleteTxt);
// Fade out and load next level
LK.setTimeout(function () {
tween(levelCompleteTxt, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
levelCompleteTxt.destroy();
initGame();
}
});
}, 2000);
}
}
function checkCollisions() {
if (!sackboy.alive) {
return;
}
// Check platform collisions
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
// Only bounce when falling
if (sackboy.velocity.y > 0 && sackboy.intersects(platform)) {
// Check if Sackboy is above the platform
if (sackboy.y < platform.y - platform.height / 2) {
sackboy.y = platform.y - platform.height / 2 - sackboy.height / 2;
sackboy.bounce(15);
}
}
}
// Check collectible collisions
for (var j = collectibles.length - 1; j >= 0; j--) {
var collectible = collectibles[j];
if (sackboy.intersects(collectible) && !collectible.collected) {
var type = collectible.collect();
if (type === 'button') {
updateScore(1);
} else if (type === 'yarn') {
// Yarn gives extra bounce
sackboy.bounce(25);
}
collectibles.splice(j, 1);
}
}
// Check hazard collisions
for (var k = 0; k < hazards.length; k++) {
var hazard = hazards[k];
if (sackboy.intersects(hazard)) {
// Check if invincible
if (sackboy.powered && sackboy.powerType === 'invincible') {
// Invincible - ignore hazard
continue;
}
sackboy.die();
break;
}
}
// Check power-up collisions
for (var l = powerups.length - 1; l >= 0; l--) {
var powerup = powerups[l];
if (sackboy.intersects(powerup) && !powerup.collected) {
var powerType = powerup.collect();
if (powerType) {
sackboy.activatePower(powerType);
}
powerups.splice(l, 1);
}
}
}
// Game control touch handlers
game.down = function (x, y, obj) {
touchStart.x = x;
touchStart.y = y;
touchDragging = true;
};
game.move = function (x, y, obj) {
if (touchDragging && sackboy && sackboy.alive) {
// Calculate drag amount
var dragX = x - touchStart.x;
// Apply horizontal velocity based on drag
sackboy.velocity.x = dragX * 0.1;
// Update touch position
touchStart.x = x;
touchStart.y = y;
}
};
game.up = function (x, y, obj) {
touchDragging = false;
// Gradually slow down horizontal velocity
if (sackboy && sackboy.alive) {
sackboy.velocity.x *= 0.5;
}
};
// Main game update loop
game.update = function () {
// Check collisions
checkCollisions();
// Update all game objects
for (var i = 0; i < platforms.length; i++) {
platforms[i].update();
}
for (var j = 0; j < collectibles.length; j++) {
collectibles[j].update();
}
for (var k = 0; k < hazards.length; k++) {
hazards[k].update();
}
for (var l = 0; l < powerups.length; l++) {
powerups[l].update();
}
// Automatically slow down horizontal velocity
if (sackboy && sackboy.alive) {
sackboy.velocity.x *= 0.98;
}
};
// Initialize the game
initGame(); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Collectible = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'button';
var collectibleGraphics = self.attachAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.update = function () {
// Simple animation
collectibleGraphics.rotation += 0.02;
// Floating effect
collectibleGraphics.y = Math.sin(LK.ticks * 0.05) * 5;
};
self.collect = function () {
if (self.collected) {
return;
}
self.collected = true;
LK.getSound('collect').play();
// Collect animation
tween(collectibleGraphics, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
return self.type;
};
return self;
});
var Hazard = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'scissors';
var hazardGraphics = self.attachAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5
});
self.moving = false;
self.moveSpeed = 0;
self.moveDirection = 1;
self.moveDistance = 0;
self.startX = 0;
self.setMoving = function (speed, distance) {
self.moving = true;
self.moveSpeed = speed;
self.moveDistance = distance;
self.startX = self.x;
};
self.update = function () {
if (self.moving) {
self.x += self.moveSpeed * self.moveDirection;
if (Math.abs(self.x - self.startX) > self.moveDistance) {
self.moveDirection *= -1;
}
}
// Animation
if (self.type === 'scissors') {
hazardGraphics.rotation = Math.sin(LK.ticks * 0.05) * 0.2;
}
};
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;
self.moving = false;
self.moveSpeed = 0;
self.moveDirection = 1;
self.moveDistance = 0;
self.startX = 0;
self.setMoving = function (speed, distance) {
self.moving = true;
self.moveSpeed = speed;
self.moveDistance = distance;
self.startX = self.x;
};
self.update = function () {
if (self.moving) {
self.x += self.moveSpeed * self.moveDirection;
if (Math.abs(self.x - self.startX) > self.moveDistance) {
self.moveDirection *= -1;
}
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'random';
self.collected = false;
// Choose a random power-up type
var types = ['fly', 'big', 'invincible'];
self.powerType = types[Math.floor(Math.random() * types.length)];
// Set color based on type
if (self.powerType === 'fly') {
powerupGraphics.tint = 0x88CCFF;
} else if (self.powerType === 'big') {
powerupGraphics.tint = 0xFF8866;
} else if (self.powerType === 'invincible') {
powerupGraphics.tint = 0xFFDD44;
}
self.update = function () {
// Floating and rotation animation
powerupGraphics.rotation += 0.03;
powerupGraphics.y = Math.sin(LK.ticks * 0.1) * 8;
};
self.collect = function () {
if (self.collected) {
return null;
}
self.collected = true;
// Collect animation
tween(powerupGraphics, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
return self.powerType;
};
return self;
});
var Sackboy = Container.expand(function () {
var self = Container.call(this);
var body = self.attachAsset('sackboy', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xDDAA66
});
// Physics properties
self.velocity = {
x: 0,
y: 0
};
self.gravity = 0.5;
self.bounce = 0.8;
self.grounded = false;
self.alive = true;
self.powered = false;
self.powerType = null;
self.powerTime = 0;
// Apply physics
self.update = function () {
if (!self.alive) {
return;
}
// Apply gravity
self.velocity.y += self.gravity;
// Apply velocity
self.x += self.velocity.x;
self.y += self.velocity.y;
// Handle power-ups
if (self.powered) {
self.powerTime--;
// Power-up effects
if (self.powerType === 'fly') {
self.velocity.y = Math.min(self.velocity.y, 1);
} else if (self.powerType === 'big') {
// Already scaled in activatePower
} else if (self.powerType === 'invincible') {
// Visual pulsing effect
body.alpha = 0.5 + Math.sin(LK.ticks * 0.2) * 0.5;
}
// End power-up
if (self.powerTime <= 0) {
self.deactivatePower();
}
}
// Screen boundaries
if (self.x < 50) {
self.x = 50;
self.velocity.x *= -0.5;
} else if (self.x > 2048 - 50) {
self.x = 2048 - 50;
self.velocity.x *= -0.5;
}
// Bottom boundary - game over
if (self.y > 2732 + 100) {
self.die();
}
// Simple animation
body.rotation += self.velocity.x * 0.01;
};
self.bounce = function (power) {
self.velocity.y = -power;
self.grounded = false;
LK.getSound('bounce').play();
};
self.activatePower = function (type) {
self.powered = true;
self.powerType = type;
self.powerTime = 300; // 5 seconds at 60fps
if (type === 'big') {
tween(body, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeOut
});
} else if (type === 'invincible') {
body.tint = 0xFFDD44;
} else if (type === 'fly') {
body.tint = 0x88CCFF;
}
LK.getSound('powerup').play();
};
self.deactivatePower = function () {
self.powered = false;
// Reset visual effects
if (self.powerType === 'big') {
tween(body, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
} else if (self.powerType === 'invincible' || self.powerType === 'fly') {
body.tint = 0xDDAA66;
body.alpha = 1;
}
self.powerType = null;
};
self.die = function () {
if (!self.alive) {
return;
}
self.alive = false;
LK.getSound('hurt').play();
// Visual effect for death
tween(body, {
alpha: 0,
rotation: Math.PI * 4,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 1000,
easing: tween.easeIn,
onFinish: function onFinish() {
LK.showGameOver();
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x88BBCC
});
/****
* Game Code
****/
// Game variables
var sackboy;
var platforms = [];
var collectibles = [];
var hazards = [];
var powerups = [];
var score = 0;
var level = 1;
var maxLevel = 3;
var touchStart = {
x: 0,
y: 0
};
var touchDragging = false;
// UI elements
var scoreTxt;
var levelTxt;
var instructionsTxt;
function initGame() {
// Reset game state
platforms = [];
collectibles = [];
hazards = [];
powerups = [];
score = 0;
// Get saved level or start at level 1
level = storage.level || 1;
if (level > maxLevel) {
level = 1;
}
// Set up UI
setupUI();
// Create Sackboy
sackboy = new Sackboy();
sackboy.x = 1024;
sackboy.y = 2000;
game.addChild(sackboy);
// Create level based on current level
createLevel(level);
// Play background music
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 0.6,
duration: 1000
}
});
}
function setupUI() {
// Score text
scoreTxt = new Text2('Buttons: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
// Level text
levelTxt = new Text2('Level ' + level, {
size: 80,
fill: 0xFFFFFF
});
levelTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(levelTxt);
// Instructions
instructionsTxt = new Text2('Tilt to move Sackboy\nCollect buttons & bounce higher!', {
size: 60,
fill: 0xFFFFFF
});
instructionsTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(instructionsTxt);
// Hide instructions after 3 seconds
LK.setTimeout(function () {
tween(instructionsTxt, {
alpha: 0
}, {
duration: 1000
});
}, 3000);
}
function createLevel(levelNum) {
// Position platforms and collectibles based on level
if (levelNum === 1) {
// Level 1: Simple introduction level
createPlatform(1024, 2200);
createPlatform(600, 1900);
createPlatform(1450, 1900);
createPlatform(1024, 1600);
createPlatform(600, 1300);
createPlatform(1450, 1300);
createPlatform(1024, 1000);
createPlatform(600, 700);
createPlatform(1450, 700);
// Add collectibles
createCollectible('button', 600, 1800);
createCollectible('button', 1450, 1800);
createCollectible('button', 1024, 1500);
createCollectible('yarn', 600, 1200);
createCollectible('button', 1450, 1200);
createCollectible('yarn', 1024, 900);
// Add power-up
createPowerUp(1024, 600);
} else if (levelNum === 2) {
// Level 2: Add some moving platforms and hazards
createPlatform(1024, 2200);
var movingPlatform1 = createPlatform(600, 1900);
movingPlatform1.setMoving(2, 300);
createPlatform(1450, 1900);
createPlatform(1024, 1600);
// Add hazards
createHazard('scissors', 1024, 1500);
var movingPlatform2 = createPlatform(600, 1300);
movingPlatform2.setMoving(3, 400);
createPlatform(1450, 1300);
createPlatform(1024, 1000);
createHazard('thread', 600, 900);
createPlatform(1450, 700);
// Add collectibles
createCollectible('button', 600, 1800);
createCollectible('button', 1450, 1800);
createCollectible('yarn', 800, 1500);
createCollectible('button', 1250, 1500);
createCollectible('button', 600, 1200);
createCollectible('yarn', 1450, 1200);
createCollectible('yarn', 1024, 900);
createCollectible('button', 1450, 600);
// Add power-ups
createPowerUp(800, 600);
} else if (levelNum === 3) {
// Level 3: Most challenging level
createPlatform(1024, 2200);
var movingPlatform1 = createPlatform(600, 1900);
movingPlatform1.setMoving(3, 400);
var movingPlatform2 = createPlatform(1450, 1800);
movingPlatform2.setMoving(4, 300);
createPlatform(1024, 1600);
// Add hazards
createHazard('scissors', 800, 1500);
createHazard('scissors', 1250, 1500);
var movingHazard = createHazard('thread', 1024, 1400);
movingHazard.setMoving(5, 500);
var movingPlatform3 = createPlatform(600, 1300);
movingPlatform3.setMoving(3, 350);
var movingPlatform4 = createPlatform(1450, 1200);
movingPlatform4.setMoving(4, 400);
createPlatform(1024, 1000);
createHazard('thread', 600, 900);
createHazard('scissors', 1450, 900);
createPlatform(800, 700);
createPlatform(1250, 600);
// Add collectibles
createCollectible('button', 600, 1800);
createCollectible('yarn', 1450, 1700);
createCollectible('button', 800, 1500);
createCollectible('button', 1250, 1500);
createCollectible('yarn', 600, 1200);
createCollectible('button', 1450, 1100);
createCollectible('yarn', 1024, 900);
createCollectible('button', 800, 600);
createCollectible('yarn', 1250, 500);
// Add power-ups
createPowerUp(600, 800);
createPowerUp(1450, 800);
}
}
function createPlatform(x, y) {
var platform = new Platform();
platform.x = x;
platform.y = y;
game.addChild(platform);
platforms.push(platform);
return platform;
}
function createCollectible(type, x, y) {
var collectible = new Collectible(type);
collectible.x = x;
collectible.y = y;
game.addChild(collectible);
collectibles.push(collectible);
return collectible;
}
function createHazard(type, x, y) {
var hazard = new Hazard(type);
hazard.x = x;
hazard.y = y;
game.addChild(hazard);
hazards.push(hazard);
return hazard;
}
function createPowerUp(x, y) {
var powerup = new PowerUp();
powerup.x = x;
powerup.y = y;
game.addChild(powerup);
powerups.push(powerup);
return powerup;
}
function updateScore(points) {
score += points;
scoreTxt.setText('Buttons: ' + score);
// Check win condition
if (score >= 10) {
completeLevel();
}
}
function completeLevel() {
// Save progress
level++;
storage.level = level;
if (level > maxLevel) {
// Player completed all levels
LK.showYouWin();
} else {
// Show level complete message
var levelCompleteTxt = new Text2('Level Complete!', {
size: 120,
fill: 0xFFFFFF
});
levelCompleteTxt.anchor.set(0.5, 0.5);
levelCompleteTxt.x = 1024;
levelCompleteTxt.y = 1366;
game.addChild(levelCompleteTxt);
// Fade out and load next level
LK.setTimeout(function () {
tween(levelCompleteTxt, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
levelCompleteTxt.destroy();
initGame();
}
});
}, 2000);
}
}
function checkCollisions() {
if (!sackboy.alive) {
return;
}
// Check platform collisions
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
// Only bounce when falling
if (sackboy.velocity.y > 0 && sackboy.intersects(platform)) {
// Check if Sackboy is above the platform
if (sackboy.y < platform.y - platform.height / 2) {
sackboy.y = platform.y - platform.height / 2 - sackboy.height / 2;
sackboy.bounce(15);
}
}
}
// Check collectible collisions
for (var j = collectibles.length - 1; j >= 0; j--) {
var collectible = collectibles[j];
if (sackboy.intersects(collectible) && !collectible.collected) {
var type = collectible.collect();
if (type === 'button') {
updateScore(1);
} else if (type === 'yarn') {
// Yarn gives extra bounce
sackboy.bounce(25);
}
collectibles.splice(j, 1);
}
}
// Check hazard collisions
for (var k = 0; k < hazards.length; k++) {
var hazard = hazards[k];
if (sackboy.intersects(hazard)) {
// Check if invincible
if (sackboy.powered && sackboy.powerType === 'invincible') {
// Invincible - ignore hazard
continue;
}
sackboy.die();
break;
}
}
// Check power-up collisions
for (var l = powerups.length - 1; l >= 0; l--) {
var powerup = powerups[l];
if (sackboy.intersects(powerup) && !powerup.collected) {
var powerType = powerup.collect();
if (powerType) {
sackboy.activatePower(powerType);
}
powerups.splice(l, 1);
}
}
}
// Game control touch handlers
game.down = function (x, y, obj) {
touchStart.x = x;
touchStart.y = y;
touchDragging = true;
};
game.move = function (x, y, obj) {
if (touchDragging && sackboy && sackboy.alive) {
// Calculate drag amount
var dragX = x - touchStart.x;
// Apply horizontal velocity based on drag
sackboy.velocity.x = dragX * 0.1;
// Update touch position
touchStart.x = x;
touchStart.y = y;
}
};
game.up = function (x, y, obj) {
touchDragging = false;
// Gradually slow down horizontal velocity
if (sackboy && sackboy.alive) {
sackboy.velocity.x *= 0.5;
}
};
// Main game update loop
game.update = function () {
// Check collisions
checkCollisions();
// Update all game objects
for (var i = 0; i < platforms.length; i++) {
platforms[i].update();
}
for (var j = 0; j < collectibles.length; j++) {
collectibles[j].update();
}
for (var k = 0; k < hazards.length; k++) {
hazards[k].update();
}
for (var l = 0; l < powerups.length; l++) {
powerups[l].update();
}
// Automatically slow down horizontal velocity
if (sackboy && sackboy.alive) {
sackboy.velocity.x *= 0.98;
}
};
// Initialize the game
initGame();