/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Ball = Container.expand(function (color) {
var self = Container.call(this);
self.ballColor = color;
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5,
tint: color
});
return self;
});
var Tube = Container.expand(function (tubeIndex) {
var self = Container.call(this);
self.tubeIndex = tubeIndex;
self.balls = [];
self.maxBalls = 5;
self.isSelected = false;
self.wasSorted = false;
// Tube outline (darker background)
var outline = self.attachAsset('tubeOutline', {
anchorX: 0.5,
anchorY: 1.0
});
// Tube body
var tubeBody = self.attachAsset('tube', {
anchorX: 0.5,
anchorY: 1.0
});
self.tubeBody = tubeBody;
self.addBall = function (ball) {
if (self.balls.length < self.maxBalls) {
self.balls.push(ball);
self.addChild(ball);
self.updateBallPositions();
return true;
}
return false;
};
self.removeBall = function () {
if (self.balls.length > 0) {
var ball = self.balls.pop();
self.removeChild(ball);
return ball;
}
return null;
};
self.getTopBall = function () {
if (self.balls.length > 0) {
return self.balls[self.balls.length - 1];
}
return null;
};
self.canAcceptBall = function (ballColor) {
if (self.balls.length === 0) return true;
if (self.balls.length >= self.maxBalls) return false;
var topBall = self.getTopBall();
return topBall && topBall.ballColor === ballColor;
};
self.updateBallPositions = function () {
for (var i = 0; i < self.balls.length; i++) {
var ball = self.balls[i];
ball.x = 0;
ball.y = -120 - i * 110;
}
};
self.setSelected = function (selected) {
self.isSelected = selected;
if (selected) {
self.tubeBody.tint = 0xffff00;
} else {
self.tubeBody.tint = 0xffffff;
}
};
self.isSorted = function () {
if (self.balls.length === 0) return true;
var firstColor = self.balls[0].ballColor;
for (var i = 1; i < self.balls.length; i++) {
if (self.balls[i].ballColor !== firstColor) {
return false;
}
}
return true;
};
self.down = function (x, y, obj) {
handleTubeClick(self);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xd3d3d3
});
/****
* Game Code
****/
var tubes = [];
var selectedTube = null;
var gameWon = false;
// Ball colors
var ballColors = [0x0066ff,
// blue (mavi)
0xffff00,
// yellow (sarı)
0x00ff00,
// green (yeşil)
0xffffff,
// white (beyaz)
0xff69b4,
// pink (pembe)
0x800080,
// purple (mor)
0xff8c00,
// orange (turuncu)
0xff0000 // red (kırmızı)
];
// Create tubes
function createTubes() {
var margin = 50; // Smaller margin from screen edges
var availableWidth = 2048 - 2 * margin; // Screen width minus margins
var tubeSpacing = availableWidth / 5; // Space for 5 tubes with proper spacing
var startX = margin + tubeSpacing / 2; // Center the tubes by adding half spacing
// Top row - 5 tubes
for (var i = 0; i < 5; i++) {
var tube = new Tube(i);
tube.x = startX + i * tubeSpacing;
tube.y = 1000;
tubes.push(tube);
game.addChild(tube);
}
// Bottom row - 5 tubes
for (var i = 0; i < 5; i++) {
var tube = new Tube(i + 5);
tube.x = startX + i * tubeSpacing;
tube.y = 1800;
tubes.push(tube);
game.addChild(tube);
}
}
// Initialize balls in tubes
function initializeBalls() {
// Create a mix of colored balls for each tube
var ballsPerTube = 4;
var totalBalls = ballColors.length * ballsPerTube;
var allBalls = [];
// Create balls for each color
for (var c = 0; c < ballColors.length; c++) {
for (var b = 0; b < ballsPerTube; b++) {
allBalls.push(ballColors[c]);
}
}
// Shuffle the balls
for (var i = allBalls.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = allBalls[i];
allBalls[i] = allBalls[j];
allBalls[j] = temp;
}
// Distribute balls to tubes (8 tubes get balls, 2 remain empty)
var ballIndex = 0;
for (var t = 0; t < 8; t++) {
for (var b = 0; b < ballsPerTube; b++) {
var ball = new Ball(allBalls[ballIndex]);
tubes[t].addBall(ball);
ballIndex++;
}
}
}
function handleTubeClick(clickedTube) {
if (gameWon) return;
if (selectedTube === null) {
// Select tube if it has balls
if (clickedTube.balls.length > 0) {
selectedTube = clickedTube;
clickedTube.setSelected(true);
LK.getSound('ballMove').play();
}
} else {
if (selectedTube === clickedTube) {
// Deselect current tube
selectedTube.setSelected(false);
selectedTube = null;
} else {
// Try to move ball from selected tube to clicked tube
var topBall = selectedTube.getTopBall();
if (topBall && clickedTube.canAcceptBall(topBall.ballColor)) {
var ball = selectedTube.removeBall();
clickedTube.addBall(ball);
LK.getSound('ballPlace').play();
LK.getSound('ballMove').play();
// Check for win condition
checkWinCondition();
}
// Deselect tube
selectedTube.setSelected(false);
selectedTube = null;
}
}
}
function checkWinCondition() {
var sortedTubes = 0;
var emptyTubes = 0;
for (var i = 0; i < tubes.length; i++) {
var tube = tubes[i];
if (tube.balls.length === 0) {
emptyTubes++;
} else if (tube.isSorted()) {
// Check if this tube just became completely full with same color (wasn't sorted before)
if (!tube.wasSorted && tube.balls.length === tube.maxBalls && tube.isSorted()) {
createConfetti(tube);
tube.wasSorted = true;
}
sortedTubes++;
}
}
// Win if we have exactly 8 sorted tubes (one for each color) and 2 empty tubes
if (sortedTubes === 8 && emptyTubes === 2) {
gameWon = true;
LK.getSound('winSound').play();
// Flash screen green
LK.effects.flashScreen(0x2ecc71, 2000);
// Show win after a delay
LK.setTimeout(function () {
LK.showYouWin();
}, 1000);
}
}
// Create UI
var titleText = new Text2('Color Sort Tubes', {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
LK.gui.top.addChild(titleText);
var instructionText = new Text2('Tap a tube to select, then tap another to move the top ball', {
size: 60,
fill: 0xBDC3C7
});
instructionText.anchor.set(0.5, 1);
instructionText.y = -50;
LK.gui.bottom.addChild(instructionText);
function createConfetti(tube) {
var confettiColors = [0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xff00ff, 0x00ffff];
var confettiPieces = [];
// Create confetti pieces around the tube
for (var i = 0; i < 20; i++) {
var confetti = LK.getAsset('ball', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
tint: confettiColors[Math.floor(Math.random() * confettiColors.length)]
});
// Position confetti at tube location
confetti.x = tube.x;
confetti.y = tube.y - 200;
game.addChild(confetti);
confettiPieces.push(confetti);
// Animate confetti with random directions
var randomX = tube.x + (Math.random() - 0.5) * 400;
var randomY = tube.y - 400 - Math.random() * 200;
var duration = 1000 + Math.random() * 500;
tween(confetti, {
x: randomX,
y: randomY,
rotation: Math.random() * Math.PI * 4,
alpha: 0
}, {
duration: duration,
easing: tween.easeOut,
onFinish: function onFinish() {
if (confetti.parent) {
confetti.parent.removeChild(confetti);
}
}
});
}
}
// Initialize game
createTubes();
initializeBalls();
game.update = function () {
// Game logic is handled by events
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Ball = Container.expand(function (color) {
var self = Container.call(this);
self.ballColor = color;
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5,
tint: color
});
return self;
});
var Tube = Container.expand(function (tubeIndex) {
var self = Container.call(this);
self.tubeIndex = tubeIndex;
self.balls = [];
self.maxBalls = 5;
self.isSelected = false;
self.wasSorted = false;
// Tube outline (darker background)
var outline = self.attachAsset('tubeOutline', {
anchorX: 0.5,
anchorY: 1.0
});
// Tube body
var tubeBody = self.attachAsset('tube', {
anchorX: 0.5,
anchorY: 1.0
});
self.tubeBody = tubeBody;
self.addBall = function (ball) {
if (self.balls.length < self.maxBalls) {
self.balls.push(ball);
self.addChild(ball);
self.updateBallPositions();
return true;
}
return false;
};
self.removeBall = function () {
if (self.balls.length > 0) {
var ball = self.balls.pop();
self.removeChild(ball);
return ball;
}
return null;
};
self.getTopBall = function () {
if (self.balls.length > 0) {
return self.balls[self.balls.length - 1];
}
return null;
};
self.canAcceptBall = function (ballColor) {
if (self.balls.length === 0) return true;
if (self.balls.length >= self.maxBalls) return false;
var topBall = self.getTopBall();
return topBall && topBall.ballColor === ballColor;
};
self.updateBallPositions = function () {
for (var i = 0; i < self.balls.length; i++) {
var ball = self.balls[i];
ball.x = 0;
ball.y = -120 - i * 110;
}
};
self.setSelected = function (selected) {
self.isSelected = selected;
if (selected) {
self.tubeBody.tint = 0xffff00;
} else {
self.tubeBody.tint = 0xffffff;
}
};
self.isSorted = function () {
if (self.balls.length === 0) return true;
var firstColor = self.balls[0].ballColor;
for (var i = 1; i < self.balls.length; i++) {
if (self.balls[i].ballColor !== firstColor) {
return false;
}
}
return true;
};
self.down = function (x, y, obj) {
handleTubeClick(self);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xd3d3d3
});
/****
* Game Code
****/
var tubes = [];
var selectedTube = null;
var gameWon = false;
// Ball colors
var ballColors = [0x0066ff,
// blue (mavi)
0xffff00,
// yellow (sarı)
0x00ff00,
// green (yeşil)
0xffffff,
// white (beyaz)
0xff69b4,
// pink (pembe)
0x800080,
// purple (mor)
0xff8c00,
// orange (turuncu)
0xff0000 // red (kırmızı)
];
// Create tubes
function createTubes() {
var margin = 50; // Smaller margin from screen edges
var availableWidth = 2048 - 2 * margin; // Screen width minus margins
var tubeSpacing = availableWidth / 5; // Space for 5 tubes with proper spacing
var startX = margin + tubeSpacing / 2; // Center the tubes by adding half spacing
// Top row - 5 tubes
for (var i = 0; i < 5; i++) {
var tube = new Tube(i);
tube.x = startX + i * tubeSpacing;
tube.y = 1000;
tubes.push(tube);
game.addChild(tube);
}
// Bottom row - 5 tubes
for (var i = 0; i < 5; i++) {
var tube = new Tube(i + 5);
tube.x = startX + i * tubeSpacing;
tube.y = 1800;
tubes.push(tube);
game.addChild(tube);
}
}
// Initialize balls in tubes
function initializeBalls() {
// Create a mix of colored balls for each tube
var ballsPerTube = 4;
var totalBalls = ballColors.length * ballsPerTube;
var allBalls = [];
// Create balls for each color
for (var c = 0; c < ballColors.length; c++) {
for (var b = 0; b < ballsPerTube; b++) {
allBalls.push(ballColors[c]);
}
}
// Shuffle the balls
for (var i = allBalls.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = allBalls[i];
allBalls[i] = allBalls[j];
allBalls[j] = temp;
}
// Distribute balls to tubes (8 tubes get balls, 2 remain empty)
var ballIndex = 0;
for (var t = 0; t < 8; t++) {
for (var b = 0; b < ballsPerTube; b++) {
var ball = new Ball(allBalls[ballIndex]);
tubes[t].addBall(ball);
ballIndex++;
}
}
}
function handleTubeClick(clickedTube) {
if (gameWon) return;
if (selectedTube === null) {
// Select tube if it has balls
if (clickedTube.balls.length > 0) {
selectedTube = clickedTube;
clickedTube.setSelected(true);
LK.getSound('ballMove').play();
}
} else {
if (selectedTube === clickedTube) {
// Deselect current tube
selectedTube.setSelected(false);
selectedTube = null;
} else {
// Try to move ball from selected tube to clicked tube
var topBall = selectedTube.getTopBall();
if (topBall && clickedTube.canAcceptBall(topBall.ballColor)) {
var ball = selectedTube.removeBall();
clickedTube.addBall(ball);
LK.getSound('ballPlace').play();
LK.getSound('ballMove').play();
// Check for win condition
checkWinCondition();
}
// Deselect tube
selectedTube.setSelected(false);
selectedTube = null;
}
}
}
function checkWinCondition() {
var sortedTubes = 0;
var emptyTubes = 0;
for (var i = 0; i < tubes.length; i++) {
var tube = tubes[i];
if (tube.balls.length === 0) {
emptyTubes++;
} else if (tube.isSorted()) {
// Check if this tube just became completely full with same color (wasn't sorted before)
if (!tube.wasSorted && tube.balls.length === tube.maxBalls && tube.isSorted()) {
createConfetti(tube);
tube.wasSorted = true;
}
sortedTubes++;
}
}
// Win if we have exactly 8 sorted tubes (one for each color) and 2 empty tubes
if (sortedTubes === 8 && emptyTubes === 2) {
gameWon = true;
LK.getSound('winSound').play();
// Flash screen green
LK.effects.flashScreen(0x2ecc71, 2000);
// Show win after a delay
LK.setTimeout(function () {
LK.showYouWin();
}, 1000);
}
}
// Create UI
var titleText = new Text2('Color Sort Tubes', {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
LK.gui.top.addChild(titleText);
var instructionText = new Text2('Tap a tube to select, then tap another to move the top ball', {
size: 60,
fill: 0xBDC3C7
});
instructionText.anchor.set(0.5, 1);
instructionText.y = -50;
LK.gui.bottom.addChild(instructionText);
function createConfetti(tube) {
var confettiColors = [0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xff00ff, 0x00ffff];
var confettiPieces = [];
// Create confetti pieces around the tube
for (var i = 0; i < 20; i++) {
var confetti = LK.getAsset('ball', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
tint: confettiColors[Math.floor(Math.random() * confettiColors.length)]
});
// Position confetti at tube location
confetti.x = tube.x;
confetti.y = tube.y - 200;
game.addChild(confetti);
confettiPieces.push(confetti);
// Animate confetti with random directions
var randomX = tube.x + (Math.random() - 0.5) * 400;
var randomY = tube.y - 400 - Math.random() * 200;
var duration = 1000 + Math.random() * 500;
tween(confetti, {
x: randomX,
y: randomY,
rotation: Math.random() * Math.PI * 4,
alpha: 0
}, {
duration: duration,
easing: tween.easeOut,
onFinish: function onFinish() {
if (confetti.parent) {
confetti.parent.removeChild(confetti);
}
}
});
}
}
// Initialize game
createTubes();
initializeBalls();
game.update = function () {
// Game logic is handled by events
};