/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Balloon = Container.expand(function (balloonColor) {
var self = Container.call(this);
var graphics = self.attachAsset('balloon', {
anchorX: 0.5,
anchorY: 0.5
});
graphics.tint = balloonColor;
self.popAnimationPlaying = false;
// Floating animation
var floatOffset = Math.random() * 2 - 1;
tween(self, {
y: self.y + floatOffset * 20
}, {
duration: 2000 + Math.random() * 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (!self.popAnimationPlaying) {
tween(self, {
y: self.y - floatOffset * 20
}, {
duration: 2000 + Math.random() * 1000,
easing: tween.easeInOut
});
}
}
});
self.down = function (x, y, obj) {
if (!self.popAnimationPlaying) {
self.popAnimationPlaying = true;
LK.getSound('popSound').play();
// Pop animation
tween(self, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
}
};
return self;
});
var Confetti = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('confetti', {
anchorX: 0.5,
anchorY: 0.5
});
var colors = [0xff6b6b, 0x4ecdc4, 0x45b7d1, 0xfeca57, 0xff9ff3, 0x54a0ff];
graphics.tint = colors[Math.floor(Math.random() * colors.length)];
self.velocityX = (Math.random() - 0.5) * 10;
self.velocityY = Math.random() * -15 - 5;
self.gravity = 0.5;
self.rotation = Math.random() * Math.PI * 2;
self.rotationSpeed = (Math.random() - 0.5) * 0.2;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.velocityY += self.gravity;
self.rotation += self.rotationSpeed;
if (self.y > 2732 + 50) {
self.destroy();
}
};
return self;
});
var LevelButton = Container.expand(function (difficulty, text, color) {
var self = Container.call(this);
var buttonBg = self.attachAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
});
buttonBg.tint = color;
var buttonText = new Text2(text, {
size: 40,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
self.difficulty = difficulty;
self.down = function (x, y, obj) {
// Button press animation
tween(self, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.easeOut
});
}
});
startPuzzle(self.difficulty);
};
return self;
});
var PuzzlePiece = Container.expand(function (correctX, correctY, pieceIndex) {
var self = Container.call(this);
var graphics = self.attachAsset('puzzlePiece', {
anchorX: 0.5,
anchorY: 0.5
});
self.correctX = correctX;
self.correctY = correctY;
self.pieceIndex = pieceIndex;
self.isPlaced = false;
self.isDragging = false;
self.startX = 0;
self.startY = 0;
// Set different colors for visual distinction
var colors = [0xff69b4, 0x4ecdc4, 0x45b7d1, 0x96ceb4, 0xfeca57, 0xff9ff3, 0x54a0ff, 0x5f27cd];
graphics.tint = colors[pieceIndex % colors.length];
self.down = function (x, y, obj) {
if (!self.isPlaced) {
self.isDragging = true;
self.startX = self.x;
self.startY = self.y;
// Bring to front
self.parent.addChild(self);
}
};
self.checkSnap = function () {
var distance = Math.sqrt(Math.pow(self.x - self.correctX, 2) + Math.pow(self.y - self.correctY, 2));
if (distance < 40) {
self.x = self.correctX;
self.y = self.correctY;
self.isPlaced = true;
self.isDragging = false;
LK.getSound('snapSound').play();
// Scale animation
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
}
});
checkPuzzleComplete();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb
});
/****
* Game Code
****/
var currentState = 'menu'; // 'menu', 'puzzle', 'celebration'
var currentDifficulty = 'easy';
var puzzlePieces = [];
var puzzleBoard = null;
var balloons = [];
var confettiParticles = [];
var draggedPiece = null;
// Difficulty settings
var difficultySettings = {
easy: {
pieces: 9,
gridSize: 3,
pieceSize: 120
},
medium: {
pieces: 16,
gridSize: 4,
pieceSize: 100
},
hard: {
pieces: 25,
gridSize: 5,
pieceSize: 80
}
};
// Level selection buttons
var easyButton = new LevelButton('easy', 'EASY\n9 Pieces', 0x4ecdc4);
var mediumButton = new LevelButton('medium', 'MEDIUM\n16 Pieces', 0xf39c12);
var hardButton = new LevelButton('hard', 'HARD\n25 Pieces', 0xe74c3c);
// Position buttons
easyButton.x = 1024;
easyButton.y = 1000;
mediumButton.x = 1024;
mediumButton.y = 1200;
hardButton.x = 1024;
hardButton.y = 1400;
// Add buttons to game
game.addChild(easyButton);
game.addChild(mediumButton);
game.addChild(hardButton);
// Title text
var titleText = new Text2('Powerpuff Girls\nJigsaw Puzzle', {
size: 80,
fill: 0xFF1493
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 600;
game.addChild(titleText);
function startPuzzle(difficulty) {
currentState = 'puzzle';
currentDifficulty = difficulty;
// Hide menu elements
easyButton.visible = false;
mediumButton.visible = false;
hardButton.visible = false;
titleText.visible = false;
createPuzzle();
}
function createPuzzle() {
var settings = difficultySettings[currentDifficulty];
puzzlePieces = [];
// Create puzzle board
puzzleBoard = LK.getAsset('puzzleBoard', {
anchorX: 0.5,
anchorY: 0.5
});
puzzleBoard.width = settings.gridSize * settings.pieceSize;
puzzleBoard.height = settings.gridSize * settings.pieceSize;
puzzleBoard.x = 1024;
puzzleBoard.y = 1000;
game.addChild(puzzleBoard);
// Create puzzle pieces
for (var i = 0; i < settings.pieces; i++) {
var row = Math.floor(i / settings.gridSize);
var col = i % settings.gridSize;
var correctX = puzzleBoard.x - settings.gridSize * settings.pieceSize / 2 + col * settings.pieceSize + settings.pieceSize / 2;
var correctY = puzzleBoard.y - settings.gridSize * settings.pieceSize / 2 + row * settings.pieceSize + settings.pieceSize / 2;
var piece = new PuzzlePiece(correctX, correctY, i);
piece.width = settings.pieceSize - 4;
piece.height = settings.pieceSize - 4;
// Scatter pieces randomly
piece.x = Math.random() * 1500 + 200;
piece.y = Math.random() * 800 + 200;
// Make sure pieces don't overlap with board initially
while (Math.abs(piece.x - puzzleBoard.x) < 450 && Math.abs(piece.y - puzzleBoard.y) < 450) {
piece.x = Math.random() * 1500 + 200;
piece.y = Math.random() * 800 + 200;
}
puzzlePieces.push(piece);
game.addChild(piece);
}
}
function checkPuzzleComplete() {
var placedPieces = 0;
for (var i = 0; i < puzzlePieces.length; i++) {
if (puzzlePieces[i].isPlaced) {
placedPieces++;
}
}
if (placedPieces === puzzlePieces.length) {
LK.getSound('winSound').play();
startCelebration();
}
}
function startCelebration() {
currentState = 'celebration';
// Create balloons
var balloonColors = [0xff6b6b, 0x4ecdc4, 0x45b7d1, 0xfeca57, 0xff9ff3, 0x54a0ff];
for (var i = 0; i < 12; i++) {
var balloon = new Balloon(balloonColors[i % balloonColors.length]);
balloon.x = Math.random() * 1800 + 124;
balloon.y = Math.random() * 1000 + 1500;
balloons.push(balloon);
game.addChild(balloon);
}
// Create confetti
for (var j = 0; j < 50; j++) {
var confetti = new Confetti();
confetti.x = Math.random() * 2048;
confetti.y = -50;
confettiParticles.push(confetti);
game.addChild(confetti);
}
// Add back to menu button
var backButton = new LevelButton('menu', 'BACK TO MENU', 0x2c3e50);
backButton.x = 1024;
backButton.y = 2500;
game.addChild(backButton);
backButton.down = function () {
resetToMenu();
};
}
function resetToMenu() {
currentState = 'menu';
// Clear all game objects
for (var i = 0; i < puzzlePieces.length; i++) {
puzzlePieces[i].destroy();
}
puzzlePieces = [];
if (puzzleBoard) {
puzzleBoard.destroy();
puzzleBoard = null;
}
for (var j = 0; j < balloons.length; j++) {
balloons[j].destroy();
}
balloons = [];
for (var k = 0; k < confettiParticles.length; k++) {
confettiParticles[k].destroy();
}
confettiParticles = [];
// Show menu elements
easyButton.visible = true;
mediumButton.visible = true;
hardButton.visible = true;
titleText.visible = true;
// Remove back button
game.children.forEach(function (child) {
if (child.difficulty === 'menu') {
child.destroy();
}
});
}
game.move = function (x, y, obj) {
if (currentState === 'puzzle' && draggedPiece && draggedPiece.isDragging) {
draggedPiece.x = x;
draggedPiece.y = y;
}
};
game.down = function (x, y, obj) {
if (currentState === 'puzzle') {
// Find the topmost piece at this position
for (var i = puzzlePieces.length - 1; i >= 0; i--) {
var piece = puzzlePieces[i];
if (!piece.isPlaced && x >= piece.x - piece.width / 2 && x <= piece.x + piece.width / 2 && y >= piece.y - piece.height / 2 && y <= piece.y + piece.height / 2) {
draggedPiece = piece;
piece.isDragging = true;
piece.startX = piece.x;
piece.startY = piece.y;
// Bring to front
game.addChild(piece);
break;
}
}
}
};
game.up = function (x, y, obj) {
if (currentState === 'puzzle' && draggedPiece) {
draggedPiece.checkSnap();
draggedPiece.isDragging = false;
draggedPiece = null;
}
};
game.update = function () {
// Update confetti particles
for (var i = confettiParticles.length - 1; i >= 0; i--) {
var confetti = confettiParticles[i];
if (confetti.parent) {
// Confetti update is handled in the class
} else {
confettiParticles.splice(i, 1);
}
}
// Clean up destroyed balloons
for (var j = balloons.length - 1; j >= 0; j--) {
if (!balloons[j].parent) {
balloons.splice(j, 1);
}
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Balloon = Container.expand(function (balloonColor) {
var self = Container.call(this);
var graphics = self.attachAsset('balloon', {
anchorX: 0.5,
anchorY: 0.5
});
graphics.tint = balloonColor;
self.popAnimationPlaying = false;
// Floating animation
var floatOffset = Math.random() * 2 - 1;
tween(self, {
y: self.y + floatOffset * 20
}, {
duration: 2000 + Math.random() * 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (!self.popAnimationPlaying) {
tween(self, {
y: self.y - floatOffset * 20
}, {
duration: 2000 + Math.random() * 1000,
easing: tween.easeInOut
});
}
}
});
self.down = function (x, y, obj) {
if (!self.popAnimationPlaying) {
self.popAnimationPlaying = true;
LK.getSound('popSound').play();
// Pop animation
tween(self, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
}
};
return self;
});
var Confetti = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('confetti', {
anchorX: 0.5,
anchorY: 0.5
});
var colors = [0xff6b6b, 0x4ecdc4, 0x45b7d1, 0xfeca57, 0xff9ff3, 0x54a0ff];
graphics.tint = colors[Math.floor(Math.random() * colors.length)];
self.velocityX = (Math.random() - 0.5) * 10;
self.velocityY = Math.random() * -15 - 5;
self.gravity = 0.5;
self.rotation = Math.random() * Math.PI * 2;
self.rotationSpeed = (Math.random() - 0.5) * 0.2;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.velocityY += self.gravity;
self.rotation += self.rotationSpeed;
if (self.y > 2732 + 50) {
self.destroy();
}
};
return self;
});
var LevelButton = Container.expand(function (difficulty, text, color) {
var self = Container.call(this);
var buttonBg = self.attachAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
});
buttonBg.tint = color;
var buttonText = new Text2(text, {
size: 40,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
self.difficulty = difficulty;
self.down = function (x, y, obj) {
// Button press animation
tween(self, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.easeOut
});
}
});
startPuzzle(self.difficulty);
};
return self;
});
var PuzzlePiece = Container.expand(function (correctX, correctY, pieceIndex) {
var self = Container.call(this);
var graphics = self.attachAsset('puzzlePiece', {
anchorX: 0.5,
anchorY: 0.5
});
self.correctX = correctX;
self.correctY = correctY;
self.pieceIndex = pieceIndex;
self.isPlaced = false;
self.isDragging = false;
self.startX = 0;
self.startY = 0;
// Set different colors for visual distinction
var colors = [0xff69b4, 0x4ecdc4, 0x45b7d1, 0x96ceb4, 0xfeca57, 0xff9ff3, 0x54a0ff, 0x5f27cd];
graphics.tint = colors[pieceIndex % colors.length];
self.down = function (x, y, obj) {
if (!self.isPlaced) {
self.isDragging = true;
self.startX = self.x;
self.startY = self.y;
// Bring to front
self.parent.addChild(self);
}
};
self.checkSnap = function () {
var distance = Math.sqrt(Math.pow(self.x - self.correctX, 2) + Math.pow(self.y - self.correctY, 2));
if (distance < 40) {
self.x = self.correctX;
self.y = self.correctY;
self.isPlaced = true;
self.isDragging = false;
LK.getSound('snapSound').play();
// Scale animation
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
}
});
checkPuzzleComplete();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb
});
/****
* Game Code
****/
var currentState = 'menu'; // 'menu', 'puzzle', 'celebration'
var currentDifficulty = 'easy';
var puzzlePieces = [];
var puzzleBoard = null;
var balloons = [];
var confettiParticles = [];
var draggedPiece = null;
// Difficulty settings
var difficultySettings = {
easy: {
pieces: 9,
gridSize: 3,
pieceSize: 120
},
medium: {
pieces: 16,
gridSize: 4,
pieceSize: 100
},
hard: {
pieces: 25,
gridSize: 5,
pieceSize: 80
}
};
// Level selection buttons
var easyButton = new LevelButton('easy', 'EASY\n9 Pieces', 0x4ecdc4);
var mediumButton = new LevelButton('medium', 'MEDIUM\n16 Pieces', 0xf39c12);
var hardButton = new LevelButton('hard', 'HARD\n25 Pieces', 0xe74c3c);
// Position buttons
easyButton.x = 1024;
easyButton.y = 1000;
mediumButton.x = 1024;
mediumButton.y = 1200;
hardButton.x = 1024;
hardButton.y = 1400;
// Add buttons to game
game.addChild(easyButton);
game.addChild(mediumButton);
game.addChild(hardButton);
// Title text
var titleText = new Text2('Powerpuff Girls\nJigsaw Puzzle', {
size: 80,
fill: 0xFF1493
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 600;
game.addChild(titleText);
function startPuzzle(difficulty) {
currentState = 'puzzle';
currentDifficulty = difficulty;
// Hide menu elements
easyButton.visible = false;
mediumButton.visible = false;
hardButton.visible = false;
titleText.visible = false;
createPuzzle();
}
function createPuzzle() {
var settings = difficultySettings[currentDifficulty];
puzzlePieces = [];
// Create puzzle board
puzzleBoard = LK.getAsset('puzzleBoard', {
anchorX: 0.5,
anchorY: 0.5
});
puzzleBoard.width = settings.gridSize * settings.pieceSize;
puzzleBoard.height = settings.gridSize * settings.pieceSize;
puzzleBoard.x = 1024;
puzzleBoard.y = 1000;
game.addChild(puzzleBoard);
// Create puzzle pieces
for (var i = 0; i < settings.pieces; i++) {
var row = Math.floor(i / settings.gridSize);
var col = i % settings.gridSize;
var correctX = puzzleBoard.x - settings.gridSize * settings.pieceSize / 2 + col * settings.pieceSize + settings.pieceSize / 2;
var correctY = puzzleBoard.y - settings.gridSize * settings.pieceSize / 2 + row * settings.pieceSize + settings.pieceSize / 2;
var piece = new PuzzlePiece(correctX, correctY, i);
piece.width = settings.pieceSize - 4;
piece.height = settings.pieceSize - 4;
// Scatter pieces randomly
piece.x = Math.random() * 1500 + 200;
piece.y = Math.random() * 800 + 200;
// Make sure pieces don't overlap with board initially
while (Math.abs(piece.x - puzzleBoard.x) < 450 && Math.abs(piece.y - puzzleBoard.y) < 450) {
piece.x = Math.random() * 1500 + 200;
piece.y = Math.random() * 800 + 200;
}
puzzlePieces.push(piece);
game.addChild(piece);
}
}
function checkPuzzleComplete() {
var placedPieces = 0;
for (var i = 0; i < puzzlePieces.length; i++) {
if (puzzlePieces[i].isPlaced) {
placedPieces++;
}
}
if (placedPieces === puzzlePieces.length) {
LK.getSound('winSound').play();
startCelebration();
}
}
function startCelebration() {
currentState = 'celebration';
// Create balloons
var balloonColors = [0xff6b6b, 0x4ecdc4, 0x45b7d1, 0xfeca57, 0xff9ff3, 0x54a0ff];
for (var i = 0; i < 12; i++) {
var balloon = new Balloon(balloonColors[i % balloonColors.length]);
balloon.x = Math.random() * 1800 + 124;
balloon.y = Math.random() * 1000 + 1500;
balloons.push(balloon);
game.addChild(balloon);
}
// Create confetti
for (var j = 0; j < 50; j++) {
var confetti = new Confetti();
confetti.x = Math.random() * 2048;
confetti.y = -50;
confettiParticles.push(confetti);
game.addChild(confetti);
}
// Add back to menu button
var backButton = new LevelButton('menu', 'BACK TO MENU', 0x2c3e50);
backButton.x = 1024;
backButton.y = 2500;
game.addChild(backButton);
backButton.down = function () {
resetToMenu();
};
}
function resetToMenu() {
currentState = 'menu';
// Clear all game objects
for (var i = 0; i < puzzlePieces.length; i++) {
puzzlePieces[i].destroy();
}
puzzlePieces = [];
if (puzzleBoard) {
puzzleBoard.destroy();
puzzleBoard = null;
}
for (var j = 0; j < balloons.length; j++) {
balloons[j].destroy();
}
balloons = [];
for (var k = 0; k < confettiParticles.length; k++) {
confettiParticles[k].destroy();
}
confettiParticles = [];
// Show menu elements
easyButton.visible = true;
mediumButton.visible = true;
hardButton.visible = true;
titleText.visible = true;
// Remove back button
game.children.forEach(function (child) {
if (child.difficulty === 'menu') {
child.destroy();
}
});
}
game.move = function (x, y, obj) {
if (currentState === 'puzzle' && draggedPiece && draggedPiece.isDragging) {
draggedPiece.x = x;
draggedPiece.y = y;
}
};
game.down = function (x, y, obj) {
if (currentState === 'puzzle') {
// Find the topmost piece at this position
for (var i = puzzlePieces.length - 1; i >= 0; i--) {
var piece = puzzlePieces[i];
if (!piece.isPlaced && x >= piece.x - piece.width / 2 && x <= piece.x + piece.width / 2 && y >= piece.y - piece.height / 2 && y <= piece.y + piece.height / 2) {
draggedPiece = piece;
piece.isDragging = true;
piece.startX = piece.x;
piece.startY = piece.y;
// Bring to front
game.addChild(piece);
break;
}
}
}
};
game.up = function (x, y, obj) {
if (currentState === 'puzzle' && draggedPiece) {
draggedPiece.checkSnap();
draggedPiece.isDragging = false;
draggedPiece = null;
}
};
game.update = function () {
// Update confetti particles
for (var i = confettiParticles.length - 1; i >= 0; i--) {
var confetti = confettiParticles[i];
if (confetti.parent) {
// Confetti update is handled in the class
} else {
confettiParticles.splice(i, 1);
}
}
// Clean up destroyed balloons
for (var j = balloons.length - 1; j >= 0; j--) {
if (!balloons[j].parent) {
balloons.splice(j, 1);
}
}
};