/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Leaf = Container.expand(function (gridX, gridY) { var self = Container.call(this); self.gridX = gridX; self.gridY = gridY; self.revealed = false; self.hasHedgehog = Math.random() < 0.3; // 30% chance var leafGraphics = self.attachAsset('leaf', { anchorX: 0.5, anchorY: 0.5 }); self.x = MAZE_OFFSET_X + gridX * GRID_SIZE + GRID_SIZE / 2; self.y = MAZE_OFFSET_Y + gridY * GRID_SIZE + GRID_SIZE / 2; self.down = function (x, y, obj) { if (!self.revealed) { self.reveal(); } }; self.reveal = function () { self.revealed = true; leafGraphics.alpha = 0.3; if (self.hasHedgehog) { var hedgehogGraphics = self.attachAsset('hedgehog', { anchorX: 0.5, anchorY: 0.5 }); LK.getSound('hedgehogLaugh').play(); LK.setScore(LK.getScore() + 10); scoreTxt.setText(LK.getScore()); // Give speed boost to player characters if (blossom) blossom.applySpeedBoost(); if (bliss) bliss.applySpeedBoost(); tween(hedgehogGraphics, { scaleX: 1.5, scaleY: 1.5 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { tween(hedgehogGraphics, { scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.easeIn }); } }); } }; return self; }); var PowerpuffCharacter = Container.expand(function (characterType) { var self = Container.call(this); self.characterType = characterType; self.isPlayerControlled = characterType === 'blossom' || characterType === 'bliss'; self.speed = 200; self.speedBoostTimer = 0; self.normalSpeed = 200; self.boostedSpeed = 400; self.gridX = 0; self.gridY = 0; self.targetX = 0; self.targetY = 0; self.isMoving = false; var characterGraphics = self.attachAsset(characterType, { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { if (self.speedBoostTimer > 0) { self.speedBoostTimer--; self.speed = self.boostedSpeed; characterGraphics.tint = 0xFFFF00; } else { self.speed = self.normalSpeed; characterGraphics.tint = 0xFFFFFF; } if (!self.isPlayerControlled) { self.moveTowardsCenter(); } }; self.moveTowardsCenter = function () { if (self.isMoving) return; var centerGridX = Math.floor(MAZE_SIZE / 2); var centerGridY = Math.floor(MAZE_SIZE / 2); var possibleMoves = []; var directions = [{ dx: 0, dy: -1 }, // up { dx: 1, dy: 0 }, // right { dx: 0, dy: 1 }, // down { dx: -1, dy: 0 } // left ]; for (var i = 0; i < directions.length; i++) { var newX = self.gridX + directions[i].dx; var newY = self.gridY + directions[i].dy; if (self.canMoveTo(newX, newY)) { var distanceToCenter = Math.abs(newX - centerGridX) + Math.abs(newY - centerGridY); possibleMoves.push({ x: newX, y: newY, distance: distanceToCenter }); } } if (possibleMoves.length > 0) { possibleMoves.sort(function (a, b) { return a.distance - b.distance; }); var bestMove = possibleMoves[0]; self.moveToGrid(bestMove.x, bestMove.y); } }; self.canMoveTo = function (gridX, gridY) { if (gridX < 0 || gridX >= MAZE_SIZE || gridY < 0 || gridY >= MAZE_SIZE) { return false; } return maze[gridY][gridX] === 0; }; self.moveToGrid = function (gridX, gridY) { if (!self.canMoveTo(gridX, gridY) || self.isMoving) { return false; } self.isMoving = true; self.gridX = gridX; self.gridY = gridY; self.targetX = MAZE_OFFSET_X + gridX * GRID_SIZE + GRID_SIZE / 2; self.targetY = MAZE_OFFSET_Y + gridY * GRID_SIZE + GRID_SIZE / 2; var moveDistance = Math.abs(self.targetX - self.x) + Math.abs(self.targetY - self.y); var moveDuration = moveDistance / self.speed * 1000; tween(self, { x: self.targetX, y: self.targetY }, { duration: moveDuration, easing: tween.linear, onFinish: function onFinish() { self.isMoving = false; self.checkWinCondition(); } }); return true; }; self.checkWinCondition = function () { var centerGridX = Math.floor(MAZE_SIZE / 2); var centerGridY = Math.floor(MAZE_SIZE / 2); if (self.gridX === centerGridX && self.gridY === centerGridY) { if (self.isPlayerControlled) { LK.getSound('victory').play(); LK.setScore(LK.getScore() + 100); LK.showYouWin(); } else { LK.showGameOver(); } } }; self.applySpeedBoost = function () { self.speedBoostTimer = 180; // 3 seconds at 60fps LK.getSound('speedBoost').play(); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ var MAZE_SIZE = 15; var GRID_SIZE = 120; var MAZE_OFFSET_X = (2048 - MAZE_SIZE * GRID_SIZE) / 2; var MAZE_OFFSET_Y = 200; var maze = []; var leaves = []; var blossom = null; var bliss = null; var bubbles = null; var buttercup = null; var draggedCharacter = null; // Generate simple maze function generateMaze() { for (var y = 0; y < MAZE_SIZE; y++) { maze[y] = []; for (var x = 0; x < MAZE_SIZE; x++) { // Create walls on borders and some internal walls if (x === 0 || x === MAZE_SIZE - 1 || y === 0 || y === MAZE_SIZE - 1) { maze[y][x] = 1; // Wall } else if (x % 2 === 0 && y % 2 === 0 && Math.random() < 0.3) { maze[y][x] = 1; // Random internal walls } else { maze[y][x] = 0; // Path } } } // Ensure center is accessible var centerX = Math.floor(MAZE_SIZE / 2); var centerY = Math.floor(MAZE_SIZE / 2); maze[centerY][centerX] = 0; // Ensure starting positions are accessible maze[1][1] = 0; // Blossom start maze[1][2] = 0; // Bliss start maze[MAZE_SIZE - 2][1] = 0; // Bubbles start maze[MAZE_SIZE - 2][2] = 0; // Buttercup start } // Render maze function renderMaze() { for (var y = 0; y < MAZE_SIZE; y++) { for (var x = 0; x < MAZE_SIZE; x++) { var cellX = MAZE_OFFSET_X + x * GRID_SIZE; var cellY = MAZE_OFFSET_Y + y * GRID_SIZE; if (maze[y][x] === 1) { // Wall var wall = LK.getAsset('mazeWall', { anchorX: 0, anchorY: 0, x: cellX, y: cellY }); game.addChild(wall); } else { // Path var path = LK.getAsset('mazePath', { anchorX: 0, anchorY: 0, x: cellX, y: cellY }); game.addChild(path); // Add leaves randomly on paths if (Math.random() < 0.2 && !(x === Math.floor(MAZE_SIZE / 2) && y === Math.floor(MAZE_SIZE / 2))) { var leaf = new Leaf(x, y); leaves.push(leaf); game.addChild(leaf); } } } } // Add center goal var center = LK.getAsset('mazeCenter', { anchorX: 0.5, anchorY: 0.5, x: MAZE_OFFSET_X + Math.floor(MAZE_SIZE / 2) * GRID_SIZE + GRID_SIZE / 2, y: MAZE_OFFSET_Y + Math.floor(MAZE_SIZE / 2) * GRID_SIZE + GRID_SIZE / 2 }); game.addChild(center); } // Score display var scoreTxt = new Text2('0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); scoreTxt.setText(LK.getScore()); // Timer display var timerTxt = new Text2('Time: 0', { size: 60, fill: 0xFFFFFF }); timerTxt.anchor.set(0.5, 0); timerTxt.y = 100; LK.gui.top.addChild(timerTxt); var gameTimer = 0; // Generate and render maze generateMaze(); renderMaze(); // Create characters blossom = new PowerpuffCharacter('blossom'); blossom.gridX = 1; blossom.gridY = 1; blossom.x = MAZE_OFFSET_X + 1 * GRID_SIZE + GRID_SIZE / 2; blossom.y = MAZE_OFFSET_Y + 1 * GRID_SIZE + GRID_SIZE / 2; game.addChild(blossom); bliss = new PowerpuffCharacter('bliss'); bliss.gridX = 2; bliss.gridY = 1; bliss.x = MAZE_OFFSET_X + 2 * GRID_SIZE + GRID_SIZE / 2; bliss.y = MAZE_OFFSET_Y + 1 * GRID_SIZE + GRID_SIZE / 2; game.addChild(bliss); bubbles = new PowerpuffCharacter('bubbles'); bubbles.gridX = 1; bubbles.gridY = MAZE_SIZE - 2; bubbles.x = MAZE_OFFSET_X + 1 * GRID_SIZE + GRID_SIZE / 2; bubbles.y = MAZE_OFFSET_Y + (MAZE_SIZE - 2) * GRID_SIZE + GRID_SIZE / 2; game.addChild(bubbles); buttercup = new PowerpuffCharacter('buttercup'); buttercup.gridX = 2; buttercup.gridY = MAZE_SIZE - 2; buttercup.x = MAZE_OFFSET_X + 2 * GRID_SIZE + GRID_SIZE / 2; buttercup.y = MAZE_OFFSET_Y + (MAZE_SIZE - 2) * GRID_SIZE + GRID_SIZE / 2; game.addChild(buttercup); // Touch controls game.down = function (x, y, obj) { var blossomDist = Math.abs(x - blossom.x) + Math.abs(y - blossom.y); var blissDist = Math.abs(x - bliss.x) + Math.abs(y - bliss.y); if (blossomDist < 100 && !blossom.isMoving) { draggedCharacter = blossom; } else if (blissDist < 100 && !bliss.isMoving) { draggedCharacter = bliss; } }; game.move = function (x, y, obj) { if (draggedCharacter) { // Convert touch position to grid coordinates var gridX = Math.floor((x - MAZE_OFFSET_X) / GRID_SIZE); var gridY = Math.floor((y - MAZE_OFFSET_Y) / GRID_SIZE); // Check if it's adjacent to current position var deltaX = Math.abs(gridX - draggedCharacter.gridX); var deltaY = Math.abs(gridY - draggedCharacter.gridY); if (deltaX === 1 && deltaY === 0 || deltaX === 0 && deltaY === 1) { draggedCharacter.moveToGrid(gridX, gridY); } } }; game.up = function (x, y, obj) { draggedCharacter = null; }; game.update = function () { gameTimer++; timerTxt.setText('Time: ' + Math.floor(gameTimer / 60)); // Game timeout after 3 minutes if (gameTimer > 10800) { LK.showGameOver(); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Leaf = Container.expand(function (gridX, gridY) {
var self = Container.call(this);
self.gridX = gridX;
self.gridY = gridY;
self.revealed = false;
self.hasHedgehog = Math.random() < 0.3; // 30% chance
var leafGraphics = self.attachAsset('leaf', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = MAZE_OFFSET_X + gridX * GRID_SIZE + GRID_SIZE / 2;
self.y = MAZE_OFFSET_Y + gridY * GRID_SIZE + GRID_SIZE / 2;
self.down = function (x, y, obj) {
if (!self.revealed) {
self.reveal();
}
};
self.reveal = function () {
self.revealed = true;
leafGraphics.alpha = 0.3;
if (self.hasHedgehog) {
var hedgehogGraphics = self.attachAsset('hedgehog', {
anchorX: 0.5,
anchorY: 0.5
});
LK.getSound('hedgehogLaugh').play();
LK.setScore(LK.getScore() + 10);
scoreTxt.setText(LK.getScore());
// Give speed boost to player characters
if (blossom) blossom.applySpeedBoost();
if (bliss) bliss.applySpeedBoost();
tween(hedgehogGraphics, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(hedgehogGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeIn
});
}
});
}
};
return self;
});
var PowerpuffCharacter = Container.expand(function (characterType) {
var self = Container.call(this);
self.characterType = characterType;
self.isPlayerControlled = characterType === 'blossom' || characterType === 'bliss';
self.speed = 200;
self.speedBoostTimer = 0;
self.normalSpeed = 200;
self.boostedSpeed = 400;
self.gridX = 0;
self.gridY = 0;
self.targetX = 0;
self.targetY = 0;
self.isMoving = false;
var characterGraphics = self.attachAsset(characterType, {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
if (self.speedBoostTimer > 0) {
self.speedBoostTimer--;
self.speed = self.boostedSpeed;
characterGraphics.tint = 0xFFFF00;
} else {
self.speed = self.normalSpeed;
characterGraphics.tint = 0xFFFFFF;
}
if (!self.isPlayerControlled) {
self.moveTowardsCenter();
}
};
self.moveTowardsCenter = function () {
if (self.isMoving) return;
var centerGridX = Math.floor(MAZE_SIZE / 2);
var centerGridY = Math.floor(MAZE_SIZE / 2);
var possibleMoves = [];
var directions = [{
dx: 0,
dy: -1
},
// up
{
dx: 1,
dy: 0
},
// right
{
dx: 0,
dy: 1
},
// down
{
dx: -1,
dy: 0
} // left
];
for (var i = 0; i < directions.length; i++) {
var newX = self.gridX + directions[i].dx;
var newY = self.gridY + directions[i].dy;
if (self.canMoveTo(newX, newY)) {
var distanceToCenter = Math.abs(newX - centerGridX) + Math.abs(newY - centerGridY);
possibleMoves.push({
x: newX,
y: newY,
distance: distanceToCenter
});
}
}
if (possibleMoves.length > 0) {
possibleMoves.sort(function (a, b) {
return a.distance - b.distance;
});
var bestMove = possibleMoves[0];
self.moveToGrid(bestMove.x, bestMove.y);
}
};
self.canMoveTo = function (gridX, gridY) {
if (gridX < 0 || gridX >= MAZE_SIZE || gridY < 0 || gridY >= MAZE_SIZE) {
return false;
}
return maze[gridY][gridX] === 0;
};
self.moveToGrid = function (gridX, gridY) {
if (!self.canMoveTo(gridX, gridY) || self.isMoving) {
return false;
}
self.isMoving = true;
self.gridX = gridX;
self.gridY = gridY;
self.targetX = MAZE_OFFSET_X + gridX * GRID_SIZE + GRID_SIZE / 2;
self.targetY = MAZE_OFFSET_Y + gridY * GRID_SIZE + GRID_SIZE / 2;
var moveDistance = Math.abs(self.targetX - self.x) + Math.abs(self.targetY - self.y);
var moveDuration = moveDistance / self.speed * 1000;
tween(self, {
x: self.targetX,
y: self.targetY
}, {
duration: moveDuration,
easing: tween.linear,
onFinish: function onFinish() {
self.isMoving = false;
self.checkWinCondition();
}
});
return true;
};
self.checkWinCondition = function () {
var centerGridX = Math.floor(MAZE_SIZE / 2);
var centerGridY = Math.floor(MAZE_SIZE / 2);
if (self.gridX === centerGridX && self.gridY === centerGridY) {
if (self.isPlayerControlled) {
LK.getSound('victory').play();
LK.setScore(LK.getScore() + 100);
LK.showYouWin();
} else {
LK.showGameOver();
}
}
};
self.applySpeedBoost = function () {
self.speedBoostTimer = 180; // 3 seconds at 60fps
LK.getSound('speedBoost').play();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
var MAZE_SIZE = 15;
var GRID_SIZE = 120;
var MAZE_OFFSET_X = (2048 - MAZE_SIZE * GRID_SIZE) / 2;
var MAZE_OFFSET_Y = 200;
var maze = [];
var leaves = [];
var blossom = null;
var bliss = null;
var bubbles = null;
var buttercup = null;
var draggedCharacter = null;
// Generate simple maze
function generateMaze() {
for (var y = 0; y < MAZE_SIZE; y++) {
maze[y] = [];
for (var x = 0; x < MAZE_SIZE; x++) {
// Create walls on borders and some internal walls
if (x === 0 || x === MAZE_SIZE - 1 || y === 0 || y === MAZE_SIZE - 1) {
maze[y][x] = 1; // Wall
} else if (x % 2 === 0 && y % 2 === 0 && Math.random() < 0.3) {
maze[y][x] = 1; // Random internal walls
} else {
maze[y][x] = 0; // Path
}
}
}
// Ensure center is accessible
var centerX = Math.floor(MAZE_SIZE / 2);
var centerY = Math.floor(MAZE_SIZE / 2);
maze[centerY][centerX] = 0;
// Ensure starting positions are accessible
maze[1][1] = 0; // Blossom start
maze[1][2] = 0; // Bliss start
maze[MAZE_SIZE - 2][1] = 0; // Bubbles start
maze[MAZE_SIZE - 2][2] = 0; // Buttercup start
}
// Render maze
function renderMaze() {
for (var y = 0; y < MAZE_SIZE; y++) {
for (var x = 0; x < MAZE_SIZE; x++) {
var cellX = MAZE_OFFSET_X + x * GRID_SIZE;
var cellY = MAZE_OFFSET_Y + y * GRID_SIZE;
if (maze[y][x] === 1) {
// Wall
var wall = LK.getAsset('mazeWall', {
anchorX: 0,
anchorY: 0,
x: cellX,
y: cellY
});
game.addChild(wall);
} else {
// Path
var path = LK.getAsset('mazePath', {
anchorX: 0,
anchorY: 0,
x: cellX,
y: cellY
});
game.addChild(path);
// Add leaves randomly on paths
if (Math.random() < 0.2 && !(x === Math.floor(MAZE_SIZE / 2) && y === Math.floor(MAZE_SIZE / 2))) {
var leaf = new Leaf(x, y);
leaves.push(leaf);
game.addChild(leaf);
}
}
}
}
// Add center goal
var center = LK.getAsset('mazeCenter', {
anchorX: 0.5,
anchorY: 0.5,
x: MAZE_OFFSET_X + Math.floor(MAZE_SIZE / 2) * GRID_SIZE + GRID_SIZE / 2,
y: MAZE_OFFSET_Y + Math.floor(MAZE_SIZE / 2) * GRID_SIZE + GRID_SIZE / 2
});
game.addChild(center);
}
// Score display
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.setText(LK.getScore());
// Timer display
var timerTxt = new Text2('Time: 0', {
size: 60,
fill: 0xFFFFFF
});
timerTxt.anchor.set(0.5, 0);
timerTxt.y = 100;
LK.gui.top.addChild(timerTxt);
var gameTimer = 0;
// Generate and render maze
generateMaze();
renderMaze();
// Create characters
blossom = new PowerpuffCharacter('blossom');
blossom.gridX = 1;
blossom.gridY = 1;
blossom.x = MAZE_OFFSET_X + 1 * GRID_SIZE + GRID_SIZE / 2;
blossom.y = MAZE_OFFSET_Y + 1 * GRID_SIZE + GRID_SIZE / 2;
game.addChild(blossom);
bliss = new PowerpuffCharacter('bliss');
bliss.gridX = 2;
bliss.gridY = 1;
bliss.x = MAZE_OFFSET_X + 2 * GRID_SIZE + GRID_SIZE / 2;
bliss.y = MAZE_OFFSET_Y + 1 * GRID_SIZE + GRID_SIZE / 2;
game.addChild(bliss);
bubbles = new PowerpuffCharacter('bubbles');
bubbles.gridX = 1;
bubbles.gridY = MAZE_SIZE - 2;
bubbles.x = MAZE_OFFSET_X + 1 * GRID_SIZE + GRID_SIZE / 2;
bubbles.y = MAZE_OFFSET_Y + (MAZE_SIZE - 2) * GRID_SIZE + GRID_SIZE / 2;
game.addChild(bubbles);
buttercup = new PowerpuffCharacter('buttercup');
buttercup.gridX = 2;
buttercup.gridY = MAZE_SIZE - 2;
buttercup.x = MAZE_OFFSET_X + 2 * GRID_SIZE + GRID_SIZE / 2;
buttercup.y = MAZE_OFFSET_Y + (MAZE_SIZE - 2) * GRID_SIZE + GRID_SIZE / 2;
game.addChild(buttercup);
// Touch controls
game.down = function (x, y, obj) {
var blossomDist = Math.abs(x - blossom.x) + Math.abs(y - blossom.y);
var blissDist = Math.abs(x - bliss.x) + Math.abs(y - bliss.y);
if (blossomDist < 100 && !blossom.isMoving) {
draggedCharacter = blossom;
} else if (blissDist < 100 && !bliss.isMoving) {
draggedCharacter = bliss;
}
};
game.move = function (x, y, obj) {
if (draggedCharacter) {
// Convert touch position to grid coordinates
var gridX = Math.floor((x - MAZE_OFFSET_X) / GRID_SIZE);
var gridY = Math.floor((y - MAZE_OFFSET_Y) / GRID_SIZE);
// Check if it's adjacent to current position
var deltaX = Math.abs(gridX - draggedCharacter.gridX);
var deltaY = Math.abs(gridY - draggedCharacter.gridY);
if (deltaX === 1 && deltaY === 0 || deltaX === 0 && deltaY === 1) {
draggedCharacter.moveToGrid(gridX, gridY);
}
}
};
game.up = function (x, y, obj) {
draggedCharacter = null;
};
game.update = function () {
gameTimer++;
timerTxt.setText('Time: ' + Math.floor(gameTimer / 60));
// Game timeout after 3 minutes
if (gameTimer > 10800) {
LK.showGameOver();
}
};