/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var LevelButton = Container.expand(function (levelNumber, color, x, y) { var self = Container.call(this); self.levelNumber = levelNumber; self.x = x; self.y = y; var buttonGraphics = self.attachAsset('stableStone', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5, tint: color }); var levelText = new Text2(levelNumber.toString(), { size: 60, fill: 0xFFFFFF }); levelText.anchor.set(0.5, 0.5); self.addChild(levelText); self.down = function (x, y, obj) { if (gameState === 'levelSelect') { startLevel(self.levelNumber); } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.jumpTo = function (targetX, targetY, onComplete) { playerMoving = true; // Jump animation tween(self, { x: targetX, y: targetY - 30 }, { duration: 300, easing: tween.easeOut }); tween(self, { x: targetX, y: targetY }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { playerMoving = false; if (onComplete) onComplete(); } }); }; return self; }); var Stone = Container.expand(function (isStable, level) { var self = Container.call(this); self.isStable = isStable; self.level = level; self.hasBeenStepped = false; var stoneGraphics = self.attachAsset(isStable ? 'stableStone' : 'unstableStone', { anchorX: 0.5, anchorY: 0.5 }); // Add subtle visual hints for stability if (!isStable) { stoneGraphics.alpha = 0.9; } self.stepOn = function () { if (self.hasBeenStepped) return false; self.hasBeenStepped = true; if (self.isStable) { // Stable stone - slight wobble tween(stoneGraphics, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100 }); tween(stoneGraphics, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); return true; } else { // Unstable stone - crumble effect tween(stoneGraphics, { alpha: 0.3, scaleX: 0.8, scaleY: 0.8 }, { duration: 200 }); return false; } }; self.down = function (x, y, obj) { if (gameState === 'playing' && !playerMoving) { targetStone = self; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x4A90E2 }); /**** * Game Code ****/ // Game state variables var gameState = 'levelSelect'; // 'levelSelect', 'playing', 'gameOver' var currentLevel = 1; var timeLeft = 60; var gameTimer; var playerMoving = false; var targetStone = null; // Game objects var player; var stones = []; var startPlatform; var endPlatform; var levelButtons = []; // UI elements var timerText; var levelText; var instructionText; // Level configurations var levelConfigs = { 1: { color: 0xFFFFFF, timeLimit: 60, stableStones: 8, unstableStones: 4 }, 2: { color: 0x4A90E2, timeLimit: 50, stableStones: 7, unstableStones: 5 }, 3: { color: 0xFF6B35, timeLimit: 40, stableStones: 6, unstableStones: 6 }, 4: { color: 0x8E44AD, timeLimit: 35, stableStones: 5, unstableStones: 7 }, 5: { color: 0x27AE60, timeLimit: 30, stableStones: 4, unstableStones: 8 } }; // Initialize UI function initUI() { timerText = new Text2('Time: 60', { size: 80, fill: 0xFFFFFF }); timerText.anchor.set(0.5, 0); LK.gui.top.addChild(timerText); levelText = new Text2('Level 1', { size: 60, fill: 0xFFFFFF }); levelText.anchor.set(0, 0); levelText.x = 150; levelText.y = 50; LK.gui.topLeft.addChild(levelText); instructionText = new Text2('Tap stones to jump!', { size: 50, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 1); LK.gui.bottom.addChild(instructionText); } // Create level selection screen function createLevelSelect() { gameState = 'levelSelect'; clearGame(); // Title var titleText = new Text2('Stepping Stones Challenge', { size: 80, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 400; game.addChild(titleText); // Level buttons var colors = [0xFFFFFF, 0x4A90E2, 0xFF6B35, 0x8E44AD, 0x27AE60]; var positions = [{ x: 512, y: 800 }, { x: 1024, y: 800 }, { x: 1536, y: 800 }, { x: 768, y: 1000 }, { x: 1280, y: 1000 }]; for (var i = 0; i < 5; i++) { var levelButton = new LevelButton(i + 1, colors[i], positions[i].x, positions[i].y); levelButtons.push(levelButton); game.addChild(levelButton); } instructionText.setText('Choose your level!'); } // Start a specific level function startLevel(level) { currentLevel = level; gameState = 'playing'; var config = levelConfigs[level]; timeLeft = config.timeLimit; clearGame(); createLevel(); // Start timer gameTimer = LK.setInterval(function () { timeLeft--; timerText.setText('Time: ' + timeLeft); if (timeLeft <= 0) { gameOver(false); } }, 1000); levelText.setText('Level ' + level); instructionText.setText('Tap stones to jump!'); } // Create level layout function createLevel() { var config = levelConfigs[currentLevel]; // Create start platform startPlatform = game.addChild(LK.getAsset('startPlatform', { anchorX: 0.5, anchorY: 0.5, x: 200, y: 2000 })); // Create end platform endPlatform = game.addChild(LK.getAsset('endPlatform', { anchorX: 0.5, anchorY: 0.5, x: 1848, y: 2000 })); // Create player player = game.addChild(new Player()); player.x = 200; player.y = 1950; // Generate stone positions var totalStones = config.stableStones + config.unstableStones; var stonePositions = []; // Create a path of stones for (var i = 0; i < totalStones; i++) { var x = 400 + i * 150 + (Math.random() * 100 - 50); var y = 1800 + (Math.random() * 400 - 200); stonePositions.push({ x: x, y: y }); } // Randomly assign stability var stableCount = config.stableStones; for (var i = 0; i < stonePositions.length; i++) { var isStable = stableCount > 0 && (Math.random() < 0.6 || stableCount >= stonePositions.length - i); if (isStable) stableCount--; var stone = new Stone(isStable, currentLevel); stone.x = stonePositions[i].x; stone.y = stonePositions[i].y; stones.push(stone); game.addChild(stone); } } // Clear game objects function clearGame() { // Clear stones for (var i = 0; i < stones.length; i++) { stones[i].destroy(); } stones = []; // Clear level buttons for (var i = 0; i < levelButtons.length; i++) { levelButtons[i].destroy(); } levelButtons = []; // Clear platforms and player if (startPlatform) { startPlatform.destroy(); startPlatform = null; } if (endPlatform) { endPlatform.destroy(); endPlatform = null; } if (player) { player.destroy(); player = null; } // Clear timer if (gameTimer) { LK.clearInterval(gameTimer); gameTimer = null; } // Clear any remaining children while (game.children.length > 0) { game.children[0].destroy(); } } // Game over handling function gameOver(success) { gameState = 'gameOver'; if (gameTimer) { LK.clearInterval(gameTimer); gameTimer = null; } if (success) { LK.getSound('success').play(); LK.setScore(LK.getScore() + timeLeft + currentLevel * 10); if (currentLevel >= 5) { LK.showYouWin(); } else { // Show success message and move to next level LK.setTimeout(function () { startLevel(currentLevel + 1); }, 2000); } } else { LK.getSound('fall').play(); LK.showGameOver(); } } // Initialize game initUI(); createLevelSelect(); // Game update loop game.update = function () { if (gameState === 'playing') { // Handle stone tapping if (targetStone && !playerMoving) { var distance = Math.sqrt(Math.pow(targetStone.x - player.x, 2) + Math.pow(targetStone.y - player.y, 2)); if (distance < 200) { // Within jumping range LK.getSound('jump').play(); player.jumpTo(targetStone.x, targetStone.y, function () { var success = targetStone.stepOn(); if (!success) { gameOver(false); } else { // Check if reached end platform var endDistance = Math.sqrt(Math.pow(endPlatform.x - player.x, 2) + Math.pow(endPlatform.y - player.y, 2)); if (endDistance < 150) { gameOver(true); } } }); } targetStone = null; } // Check if player can reach end platform directly if (!playerMoving && endPlatform) { var endDistance = Math.sqrt(Math.pow(endPlatform.x - player.x, 2) + Math.pow(endPlatform.y - player.y, 2)); if (endDistance < 200) { // Allow direct jump to end platform if (LK.ticks % 10 === 0) { instructionText.setText('Tap end platform to finish!'); } } } } }; // Handle direct clicks on end platform game.down = function (x, y, obj) { if (gameState === 'playing' && !playerMoving && endPlatform) { var endDistance = Math.sqrt(Math.pow(endPlatform.x - player.x, 2) + Math.pow(endPlatform.y - player.y, 2)); if (endDistance < 200) { // Check if click is on end platform var localPos = endPlatform.toLocal({ x: x, y: y }); if (Math.abs(localPos.x) < 100 && Math.abs(localPos.y) < 50) { LK.getSound('jump').play(); player.jumpTo(endPlatform.x, endPlatform.y - 50, function () { gameOver(true); }); } } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var LevelButton = Container.expand(function (levelNumber, color, x, y) {
var self = Container.call(this);
self.levelNumber = levelNumber;
self.x = x;
self.y = y;
var buttonGraphics = self.attachAsset('stableStone', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5,
tint: color
});
var levelText = new Text2(levelNumber.toString(), {
size: 60,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0.5);
self.addChild(levelText);
self.down = function (x, y, obj) {
if (gameState === 'levelSelect') {
startLevel(self.levelNumber);
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.jumpTo = function (targetX, targetY, onComplete) {
playerMoving = true;
// Jump animation
tween(self, {
x: targetX,
y: targetY - 30
}, {
duration: 300,
easing: tween.easeOut
});
tween(self, {
x: targetX,
y: targetY
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
playerMoving = false;
if (onComplete) onComplete();
}
});
};
return self;
});
var Stone = Container.expand(function (isStable, level) {
var self = Container.call(this);
self.isStable = isStable;
self.level = level;
self.hasBeenStepped = false;
var stoneGraphics = self.attachAsset(isStable ? 'stableStone' : 'unstableStone', {
anchorX: 0.5,
anchorY: 0.5
});
// Add subtle visual hints for stability
if (!isStable) {
stoneGraphics.alpha = 0.9;
}
self.stepOn = function () {
if (self.hasBeenStepped) return false;
self.hasBeenStepped = true;
if (self.isStable) {
// Stable stone - slight wobble
tween(stoneGraphics, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100
});
tween(stoneGraphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
return true;
} else {
// Unstable stone - crumble effect
tween(stoneGraphics, {
alpha: 0.3,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 200
});
return false;
}
};
self.down = function (x, y, obj) {
if (gameState === 'playing' && !playerMoving) {
targetStone = self;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x4A90E2
});
/****
* Game Code
****/
// Game state variables
var gameState = 'levelSelect'; // 'levelSelect', 'playing', 'gameOver'
var currentLevel = 1;
var timeLeft = 60;
var gameTimer;
var playerMoving = false;
var targetStone = null;
// Game objects
var player;
var stones = [];
var startPlatform;
var endPlatform;
var levelButtons = [];
// UI elements
var timerText;
var levelText;
var instructionText;
// Level configurations
var levelConfigs = {
1: {
color: 0xFFFFFF,
timeLimit: 60,
stableStones: 8,
unstableStones: 4
},
2: {
color: 0x4A90E2,
timeLimit: 50,
stableStones: 7,
unstableStones: 5
},
3: {
color: 0xFF6B35,
timeLimit: 40,
stableStones: 6,
unstableStones: 6
},
4: {
color: 0x8E44AD,
timeLimit: 35,
stableStones: 5,
unstableStones: 7
},
5: {
color: 0x27AE60,
timeLimit: 30,
stableStones: 4,
unstableStones: 8
}
};
// Initialize UI
function initUI() {
timerText = new Text2('Time: 60', {
size: 80,
fill: 0xFFFFFF
});
timerText.anchor.set(0.5, 0);
LK.gui.top.addChild(timerText);
levelText = new Text2('Level 1', {
size: 60,
fill: 0xFFFFFF
});
levelText.anchor.set(0, 0);
levelText.x = 150;
levelText.y = 50;
LK.gui.topLeft.addChild(levelText);
instructionText = new Text2('Tap stones to jump!', {
size: 50,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 1);
LK.gui.bottom.addChild(instructionText);
}
// Create level selection screen
function createLevelSelect() {
gameState = 'levelSelect';
clearGame();
// Title
var titleText = new Text2('Stepping Stones Challenge', {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
game.addChild(titleText);
// Level buttons
var colors = [0xFFFFFF, 0x4A90E2, 0xFF6B35, 0x8E44AD, 0x27AE60];
var positions = [{
x: 512,
y: 800
}, {
x: 1024,
y: 800
}, {
x: 1536,
y: 800
}, {
x: 768,
y: 1000
}, {
x: 1280,
y: 1000
}];
for (var i = 0; i < 5; i++) {
var levelButton = new LevelButton(i + 1, colors[i], positions[i].x, positions[i].y);
levelButtons.push(levelButton);
game.addChild(levelButton);
}
instructionText.setText('Choose your level!');
}
// Start a specific level
function startLevel(level) {
currentLevel = level;
gameState = 'playing';
var config = levelConfigs[level];
timeLeft = config.timeLimit;
clearGame();
createLevel();
// Start timer
gameTimer = LK.setInterval(function () {
timeLeft--;
timerText.setText('Time: ' + timeLeft);
if (timeLeft <= 0) {
gameOver(false);
}
}, 1000);
levelText.setText('Level ' + level);
instructionText.setText('Tap stones to jump!');
}
// Create level layout
function createLevel() {
var config = levelConfigs[currentLevel];
// Create start platform
startPlatform = game.addChild(LK.getAsset('startPlatform', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: 2000
}));
// Create end platform
endPlatform = game.addChild(LK.getAsset('endPlatform', {
anchorX: 0.5,
anchorY: 0.5,
x: 1848,
y: 2000
}));
// Create player
player = game.addChild(new Player());
player.x = 200;
player.y = 1950;
// Generate stone positions
var totalStones = config.stableStones + config.unstableStones;
var stonePositions = [];
// Create a path of stones
for (var i = 0; i < totalStones; i++) {
var x = 400 + i * 150 + (Math.random() * 100 - 50);
var y = 1800 + (Math.random() * 400 - 200);
stonePositions.push({
x: x,
y: y
});
}
// Randomly assign stability
var stableCount = config.stableStones;
for (var i = 0; i < stonePositions.length; i++) {
var isStable = stableCount > 0 && (Math.random() < 0.6 || stableCount >= stonePositions.length - i);
if (isStable) stableCount--;
var stone = new Stone(isStable, currentLevel);
stone.x = stonePositions[i].x;
stone.y = stonePositions[i].y;
stones.push(stone);
game.addChild(stone);
}
}
// Clear game objects
function clearGame() {
// Clear stones
for (var i = 0; i < stones.length; i++) {
stones[i].destroy();
}
stones = [];
// Clear level buttons
for (var i = 0; i < levelButtons.length; i++) {
levelButtons[i].destroy();
}
levelButtons = [];
// Clear platforms and player
if (startPlatform) {
startPlatform.destroy();
startPlatform = null;
}
if (endPlatform) {
endPlatform.destroy();
endPlatform = null;
}
if (player) {
player.destroy();
player = null;
}
// Clear timer
if (gameTimer) {
LK.clearInterval(gameTimer);
gameTimer = null;
}
// Clear any remaining children
while (game.children.length > 0) {
game.children[0].destroy();
}
}
// Game over handling
function gameOver(success) {
gameState = 'gameOver';
if (gameTimer) {
LK.clearInterval(gameTimer);
gameTimer = null;
}
if (success) {
LK.getSound('success').play();
LK.setScore(LK.getScore() + timeLeft + currentLevel * 10);
if (currentLevel >= 5) {
LK.showYouWin();
} else {
// Show success message and move to next level
LK.setTimeout(function () {
startLevel(currentLevel + 1);
}, 2000);
}
} else {
LK.getSound('fall').play();
LK.showGameOver();
}
}
// Initialize game
initUI();
createLevelSelect();
// Game update loop
game.update = function () {
if (gameState === 'playing') {
// Handle stone tapping
if (targetStone && !playerMoving) {
var distance = Math.sqrt(Math.pow(targetStone.x - player.x, 2) + Math.pow(targetStone.y - player.y, 2));
if (distance < 200) {
// Within jumping range
LK.getSound('jump').play();
player.jumpTo(targetStone.x, targetStone.y, function () {
var success = targetStone.stepOn();
if (!success) {
gameOver(false);
} else {
// Check if reached end platform
var endDistance = Math.sqrt(Math.pow(endPlatform.x - player.x, 2) + Math.pow(endPlatform.y - player.y, 2));
if (endDistance < 150) {
gameOver(true);
}
}
});
}
targetStone = null;
}
// Check if player can reach end platform directly
if (!playerMoving && endPlatform) {
var endDistance = Math.sqrt(Math.pow(endPlatform.x - player.x, 2) + Math.pow(endPlatform.y - player.y, 2));
if (endDistance < 200) {
// Allow direct jump to end platform
if (LK.ticks % 10 === 0) {
instructionText.setText('Tap end platform to finish!');
}
}
}
}
};
// Handle direct clicks on end platform
game.down = function (x, y, obj) {
if (gameState === 'playing' && !playerMoving && endPlatform) {
var endDistance = Math.sqrt(Math.pow(endPlatform.x - player.x, 2) + Math.pow(endPlatform.y - player.y, 2));
if (endDistance < 200) {
// Check if click is on end platform
var localPos = endPlatform.toLocal({
x: x,
y: y
});
if (Math.abs(localPos.x) < 100 && Math.abs(localPos.y) < 50) {
LK.getSound('jump').play();
player.jumpTo(endPlatform.x, endPlatform.y - 50, function () {
gameOver(true);
});
}
}
}
};