/**** * 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);
}
}
};