/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Character = Container.expand(function (level) { var self = Container.call(this); self.level = level || 1; self.merging = false; self.settled = false; self.velocityX = 0; self.velocityY = 0; self.gravity = 0.5; self.bounce = 0.3; self.friction = 0.98; self.lastY = undefined; var graphics = self.attachAsset('character' + self.level, { anchorX: 0.5, anchorY: 0.5 }); self.radius = graphics.width / 2; // Add character labels for visual feedback var levelText = new Text2(self.level.toString(), { size: 40, fill: 0x000000 }); levelText.anchor.set(0.5, 0.5); self.addChild(levelText); self.update = function () { if (self.merging) return; // Apply gravity self.velocityY += self.gravity; // Apply velocity self.x += self.velocityX; self.y += self.velocityY; // Apply friction self.velocityX *= self.friction; // Check if character crosses game over boundary (only when settled and completely outside) if (self.settled && self.y - self.radius <= 1400 && !gameOver) { gameOver = true; LK.showGameOver(); return; } // Check collision with walls if (self.x - self.radius <= leftWall.x + leftWall.width / 2) { self.x = leftWall.x + leftWall.width / 2 + self.radius; self.velocityX = 0; } if (self.x + self.radius >= rightWall.x - rightWall.width / 2) { self.x = rightWall.x - rightWall.width / 2 - self.radius; self.velocityX = 0; } // Check collision with floor if (self.y + self.radius >= floor.y - floor.height / 2) { self.y = floor.y - floor.height / 2 - self.radius; self.velocityY = 0; self.settled = true; } // Check for collisions with other characters for (var i = 0; i < characters.length; i++) { var other = characters[i]; if (other !== self && !other.merging && !self.merging) { var distance = Math.sqrt(Math.pow(self.x - other.x, 2) + Math.pow(self.y - other.y, 2)); var minDistance = self.radius + other.radius; // Check for collision if (distance < minDistance && distance > 0) { // Calculate collision normal var normalX = (other.x - self.x) / distance; var normalY = (other.y - self.y) / distance; // Separate objects var overlap = minDistance - distance; var separationX = normalX * overlap * 0.5; var separationY = normalY * overlap * 0.5; self.x -= separationX; self.y -= separationY; other.x += separationX; other.y += separationY; // Stop movement on collision to prevent bouncing self.velocityX *= 0.5; self.velocityY *= 0.5; other.velocityX *= 0.5; other.velocityY *= 0.5; // Check for merging only if same level and touching if (other.level === self.level && distance < minDistance) { self.mergeWith(other); break; } } } } // Update lastY for boundary detection self.lastY = self.y; }; self.mergeWith = function (other) { if (self.merging || other.merging) return; if (self.level >= 11) return; // Max level reached self.merging = true; other.merging = true; // Calculate merge position var mergeX = (self.x + other.x) / 2; var mergeY = (self.y + other.y) / 2; // Play merge sound LK.getSound('merge').play(); // Create merge effect tween(self, { alpha: 0, scaleX: 1.2, scaleY: 1.2 }, { duration: 100, easing: tween.easeOut }); tween(other, { alpha: 0, scaleX: 1.2, scaleY: 1.2 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { // Remove old characters var selfIndex = characters.indexOf(self); var otherIndex = characters.indexOf(other); if (selfIndex > -1) characters.splice(selfIndex, 1); if (otherIndex > -1) characters.splice(otherIndex, 1); self.destroy(); other.destroy(); // Create new character var newCharacter = new Character(self.level + 1); newCharacter.x = mergeX; newCharacter.y = mergeY; newCharacter.velocityY = -5; // Small upward bounce characters.push(newCharacter); gameContainer.addChild(newCharacter); // Update score LK.setScore(LK.getScore() + self.level * 10); scoreText.setText(LK.getScore()); // Spawn effect tween(newCharacter, { scaleX: 1, scaleY: 1 }, { duration: 150, easing: tween.bounceOut }); newCharacter.scaleX = 0.5; newCharacter.scaleY = 0.5; } }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ // Sound effects // Drop zone indicator // Container walls // Pink circle - ultimate // Orange circle - capybara with hat // Purple circle - capybara // Yellow circle - giant duck // Green circle - duck // Blue circle - cat with glasses // Teal circle - cat // Red circle - basic // Character assets - progression from simple to complex // Game variables var characters = []; var nextCharacterLevel = 1; var dropPosition = 1024; // Center of screen var gameOver = false; var dropCooldown = 0; // Create game container var gameContainer = new Container(); game.addChild(gameContainer); // Create container walls and floor var leftWall = gameContainer.attachAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 624, y: 1866 }); var rightWall = gameContainer.attachAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 1424, y: 1866 }); var floor = gameContainer.attachAsset('floor', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2166 }); // Create drop zone indicator var dropZone = gameContainer.attachAsset('dropZone', { anchorX: 0.5, anchorY: 0.5, x: dropPosition, y: 1400, alpha: 0.3 }); // Create UI elements var scoreText = new Text2('0', { size: 80, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); scoreText.y = 100; var nextCharacterText = new Text2('Next: Level 1', { size: 60, fill: 0xFFFFFF }); nextCharacterText.anchor.set(0.5, 0); LK.gui.top.addChild(nextCharacterText); nextCharacterText.y = 200; // Game over line var gameOverLine = new Container(); var lineGraphics = LK.getAsset('floor', { anchorX: 0.5, anchorY: 0.5, width: 800, height: 5 }); lineGraphics.tint = 0xFF0000; lineGraphics.alpha = 0.5; gameOverLine.addChild(lineGraphics); gameOverLine.x = 1024; gameOverLine.y = 1450; gameContainer.addChild(gameOverLine); // Check if there are any matching characters for the given level function hasMatchingCharacters(level) { var count = 0; for (var i = 0; i < characters.length; i++) { if (characters[i].level === level && !characters[i].merging) { count++; if (count >= 2) return true; } } return false; } // Generate next character level (weighted towards lower levels) function generateNextCharacter() { var rand = Math.random(); if (rand < 0.35) return 1; if (rand < 0.6) return 2; if (rand < 0.75) return 3; if (rand < 0.85) return 4; if (rand < 0.92) return 5; if (rand < 0.97) return 6; return 7; } // Check if game is over - disabled for infinite gameplay function checkGameOver() { // Game over functionality removed - infinite game return false; } // Drop character function dropCharacter() { if (dropCooldown > 0) return; var character = new Character(nextCharacterLevel); character.x = dropPosition; character.y = 1300; character.velocityY = 2; characters.push(character); gameContainer.addChild(character); // Play drop sound LK.getSound('drop').play(); // Generate next character nextCharacterLevel = generateNextCharacter(); nextCharacterText.setText('Next: Level ' + nextCharacterLevel); updatePreviewCharacter(); // Set cooldown dropCooldown = 30; // 0.5 seconds at 60fps } // Handle mouse/touch input game.move = function (x, y, obj) { // Update drop position dropPosition = Math.max(leftWall.x + leftWall.width / 2 + 60, Math.min(rightWall.x - rightWall.width / 2 - 60, x)); dropZone.x = dropPosition; }; game.down = function (x, y, obj) { // Update drop position and drop character dropPosition = Math.max(leftWall.x + leftWall.width / 2 + 60, Math.min(rightWall.x - rightWall.width / 2 - 60, x)); dropZone.x = dropPosition; dropCharacter(); }; // Main game loop game.update = function () { // Update cooldown if (dropCooldown > 0) { dropCooldown--; } // Update drop zone alpha based on cooldown dropZone.alpha = dropCooldown > 0 ? 0.1 : 0.3; // Clean up destroyed characters for (var i = characters.length - 1; i >= 0; i--) { if (characters[i].destroyed) { characters.splice(i, 1); } } }; // Create preview container for next character var previewContainer = new Container(); previewContainer.x = 1800; // Top-right corner previewContainer.y = 200; LK.gui.addChild(previewContainer); // Create preview character display var previewCharacter = null; // Function to update preview character function updatePreviewCharacter() { // Remove existing preview if (previewCharacter) { previewCharacter.destroy(); } // Create new preview character previewCharacter = previewContainer.attachAsset('character' + nextCharacterLevel, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); // Add preview label var previewLabel = new Text2('Next', { size: 40, fill: 0xFFFFFF }); previewLabel.anchor.set(0.5, 0.5); previewLabel.y = -80; previewContainer.addChild(previewLabel); } // Initialize first character level nextCharacterLevel = generateNextCharacter(); nextCharacterText.setText('Next: Level ' + nextCharacterLevel); updatePreviewCharacter();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Character = Container.expand(function (level) {
var self = Container.call(this);
self.level = level || 1;
self.merging = false;
self.settled = false;
self.velocityX = 0;
self.velocityY = 0;
self.gravity = 0.5;
self.bounce = 0.3;
self.friction = 0.98;
self.lastY = undefined;
var graphics = self.attachAsset('character' + self.level, {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = graphics.width / 2;
// Add character labels for visual feedback
var levelText = new Text2(self.level.toString(), {
size: 40,
fill: 0x000000
});
levelText.anchor.set(0.5, 0.5);
self.addChild(levelText);
self.update = function () {
if (self.merging) return;
// Apply gravity
self.velocityY += self.gravity;
// Apply velocity
self.x += self.velocityX;
self.y += self.velocityY;
// Apply friction
self.velocityX *= self.friction;
// Check if character crosses game over boundary (only when settled and completely outside)
if (self.settled && self.y - self.radius <= 1400 && !gameOver) {
gameOver = true;
LK.showGameOver();
return;
}
// Check collision with walls
if (self.x - self.radius <= leftWall.x + leftWall.width / 2) {
self.x = leftWall.x + leftWall.width / 2 + self.radius;
self.velocityX = 0;
}
if (self.x + self.radius >= rightWall.x - rightWall.width / 2) {
self.x = rightWall.x - rightWall.width / 2 - self.radius;
self.velocityX = 0;
}
// Check collision with floor
if (self.y + self.radius >= floor.y - floor.height / 2) {
self.y = floor.y - floor.height / 2 - self.radius;
self.velocityY = 0;
self.settled = true;
}
// Check for collisions with other characters
for (var i = 0; i < characters.length; i++) {
var other = characters[i];
if (other !== self && !other.merging && !self.merging) {
var distance = Math.sqrt(Math.pow(self.x - other.x, 2) + Math.pow(self.y - other.y, 2));
var minDistance = self.radius + other.radius;
// Check for collision
if (distance < minDistance && distance > 0) {
// Calculate collision normal
var normalX = (other.x - self.x) / distance;
var normalY = (other.y - self.y) / distance;
// Separate objects
var overlap = minDistance - distance;
var separationX = normalX * overlap * 0.5;
var separationY = normalY * overlap * 0.5;
self.x -= separationX;
self.y -= separationY;
other.x += separationX;
other.y += separationY;
// Stop movement on collision to prevent bouncing
self.velocityX *= 0.5;
self.velocityY *= 0.5;
other.velocityX *= 0.5;
other.velocityY *= 0.5;
// Check for merging only if same level and touching
if (other.level === self.level && distance < minDistance) {
self.mergeWith(other);
break;
}
}
}
}
// Update lastY for boundary detection
self.lastY = self.y;
};
self.mergeWith = function (other) {
if (self.merging || other.merging) return;
if (self.level >= 11) return; // Max level reached
self.merging = true;
other.merging = true;
// Calculate merge position
var mergeX = (self.x + other.x) / 2;
var mergeY = (self.y + other.y) / 2;
// Play merge sound
LK.getSound('merge').play();
// Create merge effect
tween(self, {
alpha: 0,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100,
easing: tween.easeOut
});
tween(other, {
alpha: 0,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
// Remove old characters
var selfIndex = characters.indexOf(self);
var otherIndex = characters.indexOf(other);
if (selfIndex > -1) characters.splice(selfIndex, 1);
if (otherIndex > -1) characters.splice(otherIndex, 1);
self.destroy();
other.destroy();
// Create new character
var newCharacter = new Character(self.level + 1);
newCharacter.x = mergeX;
newCharacter.y = mergeY;
newCharacter.velocityY = -5; // Small upward bounce
characters.push(newCharacter);
gameContainer.addChild(newCharacter);
// Update score
LK.setScore(LK.getScore() + self.level * 10);
scoreText.setText(LK.getScore());
// Spawn effect
tween(newCharacter, {
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.bounceOut
});
newCharacter.scaleX = 0.5;
newCharacter.scaleY = 0.5;
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Sound effects
// Drop zone indicator
// Container walls
// Pink circle - ultimate
// Orange circle - capybara with hat
// Purple circle - capybara
// Yellow circle - giant duck
// Green circle - duck
// Blue circle - cat with glasses
// Teal circle - cat
// Red circle - basic
// Character assets - progression from simple to complex
// Game variables
var characters = [];
var nextCharacterLevel = 1;
var dropPosition = 1024; // Center of screen
var gameOver = false;
var dropCooldown = 0;
// Create game container
var gameContainer = new Container();
game.addChild(gameContainer);
// Create container walls and floor
var leftWall = gameContainer.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 624,
y: 1866
});
var rightWall = gameContainer.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 1424,
y: 1866
});
var floor = gameContainer.attachAsset('floor', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2166
});
// Create drop zone indicator
var dropZone = gameContainer.attachAsset('dropZone', {
anchorX: 0.5,
anchorY: 0.5,
x: dropPosition,
y: 1400,
alpha: 0.3
});
// Create UI elements
var scoreText = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
scoreText.y = 100;
var nextCharacterText = new Text2('Next: Level 1', {
size: 60,
fill: 0xFFFFFF
});
nextCharacterText.anchor.set(0.5, 0);
LK.gui.top.addChild(nextCharacterText);
nextCharacterText.y = 200;
// Game over line
var gameOverLine = new Container();
var lineGraphics = LK.getAsset('floor', {
anchorX: 0.5,
anchorY: 0.5,
width: 800,
height: 5
});
lineGraphics.tint = 0xFF0000;
lineGraphics.alpha = 0.5;
gameOverLine.addChild(lineGraphics);
gameOverLine.x = 1024;
gameOverLine.y = 1450;
gameContainer.addChild(gameOverLine);
// Check if there are any matching characters for the given level
function hasMatchingCharacters(level) {
var count = 0;
for (var i = 0; i < characters.length; i++) {
if (characters[i].level === level && !characters[i].merging) {
count++;
if (count >= 2) return true;
}
}
return false;
}
// Generate next character level (weighted towards lower levels)
function generateNextCharacter() {
var rand = Math.random();
if (rand < 0.35) return 1;
if (rand < 0.6) return 2;
if (rand < 0.75) return 3;
if (rand < 0.85) return 4;
if (rand < 0.92) return 5;
if (rand < 0.97) return 6;
return 7;
}
// Check if game is over - disabled for infinite gameplay
function checkGameOver() {
// Game over functionality removed - infinite game
return false;
}
// Drop character
function dropCharacter() {
if (dropCooldown > 0) return;
var character = new Character(nextCharacterLevel);
character.x = dropPosition;
character.y = 1300;
character.velocityY = 2;
characters.push(character);
gameContainer.addChild(character);
// Play drop sound
LK.getSound('drop').play();
// Generate next character
nextCharacterLevel = generateNextCharacter();
nextCharacterText.setText('Next: Level ' + nextCharacterLevel);
updatePreviewCharacter();
// Set cooldown
dropCooldown = 30; // 0.5 seconds at 60fps
}
// Handle mouse/touch input
game.move = function (x, y, obj) {
// Update drop position
dropPosition = Math.max(leftWall.x + leftWall.width / 2 + 60, Math.min(rightWall.x - rightWall.width / 2 - 60, x));
dropZone.x = dropPosition;
};
game.down = function (x, y, obj) {
// Update drop position and drop character
dropPosition = Math.max(leftWall.x + leftWall.width / 2 + 60, Math.min(rightWall.x - rightWall.width / 2 - 60, x));
dropZone.x = dropPosition;
dropCharacter();
};
// Main game loop
game.update = function () {
// Update cooldown
if (dropCooldown > 0) {
dropCooldown--;
}
// Update drop zone alpha based on cooldown
dropZone.alpha = dropCooldown > 0 ? 0.1 : 0.3;
// Clean up destroyed characters
for (var i = characters.length - 1; i >= 0; i--) {
if (characters[i].destroyed) {
characters.splice(i, 1);
}
}
};
// Create preview container for next character
var previewContainer = new Container();
previewContainer.x = 1800; // Top-right corner
previewContainer.y = 200;
LK.gui.addChild(previewContainer);
// Create preview character display
var previewCharacter = null;
// Function to update preview character
function updatePreviewCharacter() {
// Remove existing preview
if (previewCharacter) {
previewCharacter.destroy();
}
// Create new preview character
previewCharacter = previewContainer.attachAsset('character' + nextCharacterLevel, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
// Add preview label
var previewLabel = new Text2('Next', {
size: 40,
fill: 0xFFFFFF
});
previewLabel.anchor.set(0.5, 0.5);
previewLabel.y = -80;
previewContainer.addChild(previewLabel);
}
// Initialize first character level
nextCharacterLevel = generateNextCharacter();
nextCharacterText.setText('Next: Level ' + nextCharacterLevel);
updatePreviewCharacter();
make an ant. In-Game asset. High contrast. No shadows
make a bee. In-Game asset. High contrast. No shadows
make a butterfly. In-Game asset. High contrast. No shadows
make a bird. In-Game asset. High contrast. No shadows
create a cat. In-Game asset. High contrast. No shadows
Create a dog. In-Game asset. High contrast. No shadows
Create a tigre. In-Game asset. High contrast. No shadows
Create a oso. In-Game asset. High contrast. No shadows
make a hippopotamus. In-Game asset. High contrast. No shadows
make an elephant. In-Game asset. High contrast. No shadows
make a giraffe. In-Game asset. High contrast. No shadows
make a whale. In-Game asset. High contrast. No shadows