/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Hero = Container.expand(function (tier) {
var self = Container.call(this);
self.tier = tier || 1;
self.gridX = -1;
self.gridY = -1;
self.isDragging = false;
self.originalX = 0;
self.originalY = 0;
var heroAssets = ['heroTier1', 'heroTier2', 'heroTier3', 'heroTier4', 'heroTier5', 'heroTier6', 'heroTier7', 'heroTier8', 'heroTier9'];
var heroGraphics = self.attachAsset(heroAssets[self.tier - 1], {
anchorX: 0.5,
anchorY: 0.5
});
// Tier text removed - heroes now display without numbers
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
self.originalX = self.x;
self.originalY = self.y;
};
self.down = function (x, y, obj) {
if (!gameOver) {
self.isDragging = true;
draggedHero = self;
self.originalX = self.x;
self.originalY = self.y;
tween(self, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100
});
}
};
self.up = function (x, y, obj) {
if (self.isDragging) {
self.isDragging = false;
draggedHero = null;
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
// Check for merge
var targetGridX = Math.floor((self.x - GRID_START_X) / CELL_SIZE);
var targetGridY = Math.floor((self.y - GRID_START_Y) / CELL_SIZE);
if (targetGridX >= 0 && targetGridX < GRID_WIDTH && targetGridY >= 0 && targetGridY < GRID_HEIGHT) {
var targetHero = grid[targetGridY][targetGridX];
if (targetHero && targetHero !== self && targetHero.tier === self.tier) {
// Merge!
performMerge(self, targetHero);
return;
}
}
// Return to original position with bounce effect
tween(self, {
x: self.originalX,
y: self.originalY
}, {
duration: 300,
easing: tween.bounceOut
});
}
};
return self;
});
var Particle = Container.expand(function (x, y, color) {
var self = Container.call(this);
self.x = x;
self.y = y;
var particle = self.attachAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1
});
particle.tint = color;
self.velocity = {
x: (Math.random() - 0.5) * 20,
y: (Math.random() - 0.5) * 20 - 10
};
self.life = 1.0;
self.update = function () {
self.x += self.velocity.x;
self.y += self.velocity.y;
self.velocity.y += 0.5; // gravity
self.life -= 0.02;
particle.alpha = self.life;
if (self.life <= 0) {
self.destroy();
var index = particles.indexOf(self);
if (index > -1) particles.splice(index, 1);
}
};
return self;
});
var PowerUp = Container.expand(function (type) {
var self = Container.call(this);
self.type = type; // 'score', 'clear', 'bomb'
self.gridX = -1;
self.gridY = -1;
self.isUsed = false;
var colors = {
score: 0xFFD700,
clear: 0x00FF00,
bomb: 0xFF4444
};
var powerUpGraphics = self.attachAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
powerUpGraphics.tint = colors[type];
// Add pulsing animation
function pulse() {
tween(powerUpGraphics, {
scaleX: 0.9,
scaleY: 0.9,
alpha: 0.8
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(powerUpGraphics, {
scaleX: 0.8,
scaleY: 0.8,
alpha: 1.0
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: pulse
});
}
});
}
pulse();
// Power-up symbol
var symbol = new Text2(type === 'score' ? '$' : type === 'clear' ? '✓' : '💥', {
size: 60,
fill: 0xFFFFFF
});
symbol.anchor.set(0.5, 0.5);
self.addChild(symbol);
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
};
self.activate = function () {
if (self.isUsed) return;
self.isUsed = true;
if (self.type === 'score') {
LK.setScore(LK.getScore() + 500);
scoreText.setText('Score: ' + LK.getScore());
LK.effects.flashScreen(0xFFD700, 300);
} else if (self.type === 'clear') {
// Clear bottom row
for (var x = 0; x < GRID_WIDTH; x++) {
if (grid[GRID_HEIGHT - 1][x]) {
var hero = grid[GRID_HEIGHT - 1][x];
grid[GRID_HEIGHT - 1][x] = null;
hero.destroy();
var index = heroes.indexOf(hero);
if (index > -1) heroes.splice(index, 1);
}
}
LK.effects.flashScreen(0x00FF00, 300);
} else if (self.type === 'bomb') {
// Destroy 3x3 area around power-up
for (var dy = -1; dy <= 1; dy++) {
for (var dx = -1; dx <= 1; dx++) {
var targetX = self.gridX + dx;
var targetY = self.gridY + dy;
if (targetX >= 0 && targetX < GRID_WIDTH && targetY >= 0 && targetY < GRID_HEIGHT) {
if (grid[targetY][targetX] && grid[targetY][targetX] !== self) {
var hero = grid[targetY][targetX];
grid[targetY][targetX] = null;
hero.destroy();
var index = heroes.indexOf(hero);
if (index > -1) heroes.splice(index, 1);
}
}
}
}
LK.effects.flashScreen(0xFF4444, 300);
}
// Remove power-up from grid
grid[self.gridY][self.gridX] = null;
self.destroy();
var powerUpIndex = powerUps.indexOf(self);
if (powerUpIndex > -1) powerUps.splice(powerUpIndex, 1);
};
self.down = function () {
self.activate();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a1a
});
/****
* Game Code
****/
var GRID_WIDTH = 5;
var GRID_HEIGHT = 7;
var CELL_SIZE = 140;
var GRID_START_X = (2048 - GRID_WIDTH * CELL_SIZE) / 2;
var GRID_START_Y = 600;
var grid = [];
var heroes = [];
var draggedHero = null;
var gameOver = false;
var gameStarted = false;
var spawnTimer = 0;
var spawnInterval = 180; // 3 seconds at 60fps
var menuContainer = null;
var scoreText = null;
var particles = [];
var powerUps = [];
var powerUpSpawnChance = 0.05; // 5% chance to spawn power-up instead of hero
var comboCount = 0;
var comboTimer = 0;
var comboText = null;
var lastMergeTime = 0;
var kemaldevClickCount = 0;
function showMainMenu() {
// Start background music
LK.playMusic('backgroundMusic');
menuContainer = new Container();
menuContainer.alpha = 0;
game.addChild(menuContainer);
// Fade in menu
tween(menuContainer, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
// Dark urban background with gradient effect using multiple layers
var menuBg1 = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 15,
scaleY: 20
});
menuBg1.x = 2048 / 2;
menuBg1.y = 2732 / 2;
menuBg1.tint = 0x0a0a0a;
menuBg1.alpha = 1.0;
menuContainer.addChild(menuBg1);
// Add dark cyan overlay for GTA 2 aesthetic
var menuBg2 = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 15,
scaleY: 20
});
menuBg2.x = 2048 / 2;
menuBg2.y = 2732 / 2;
menuBg2.tint = 0x003333;
menuBg2.alpha = 0.6;
menuContainer.addChild(menuBg2);
// KEMALDEV Logo with neon cyan color
var logoText = new Text2('KEMALDEV', {
size: 220,
fill: 0x00FFFF
});
logoText.anchor.set(0.5, 0.5);
logoText.x = 2048 / 2;
logoText.y = 900;
menuContainer.addChild(logoText);
// Add click detection to KEMALDEV logo
logoText.down = function () {
kemaldevClickCount++;
// Visual feedback for click
tween(logoText, {
scaleX: 1.2,
scaleY: 1.2,
tint: 0xFFFFFF
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(logoText, {
scaleX: 1,
scaleY: 1,
tint: 0x00FFFF
}, {
duration: 100,
easing: tween.easeIn
});
}
});
// Check if clicked 2 times
if (kemaldevClickCount >= 2) {
// Increment win count in storage
storage.totalWins = (storage.totalWins || 0) + 1;
// Flash screen gold
LK.effects.flashScreen(0xFFD700, 1000);
// Show you win after short delay
LK.setTimeout(function () {
LK.showYouWin();
}, 500);
}
};
// Game title with neon green color
var gameTitle = new Text2('HERO FUSION ACADEMY', {
size: 120,
fill: 0x00FF00
});
gameTitle.anchor.set(0.5, 0.5);
gameTitle.x = 2048 / 2;
gameTitle.y = 1150;
menuContainer.addChild(gameTitle);
// Add neon glow pulsing animation to KEMALDEV logo
function pulseLogo() {
tween(logoText, {
tint: 0x66FFFF,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 1200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(logoText, {
tint: 0x00FFFF,
scaleX: 1,
scaleY: 1
}, {
duration: 1200,
easing: tween.easeInOut,
onFinish: pulseLogo
});
}
});
}
pulseLogo();
// Add neon glow pulsing animation to title
function pulseTitle() {
tween(gameTitle, {
tint: 0x66FF66,
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(gameTitle, {
tint: 0x00FF00,
scaleX: 1,
scaleY: 1
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: pulseTitle
});
}
});
}
pulseTitle();
// Subtitle with neon yellow
var subtitle = new Text2('MERGE IDENTICAL HEROES TO CREATE POWERFUL CHAMPIONS!', {
size: 70,
fill: 0xFFFF00
});
subtitle.anchor.set(0.5, 0.5);
subtitle.x = 2048 / 2;
subtitle.y = 1300;
menuContainer.addChild(subtitle);
// Online Leaderboard
var leaderboardTitle = new Text2('ONLINE LEADERBOARD', {
size: 80,
fill: 0x00FFFF
});
leaderboardTitle.anchor.set(0.5, 0.5);
leaderboardTitle.x = 2048 / 2;
leaderboardTitle.y = 1400;
menuContainer.addChild(leaderboardTitle);
// Simulated online scores (in a real implementation, this would come from a server)
var leaderboardData = [{
name: 'KEMALDEV',
score: 99999
}, {
name: 'PLAYER_X',
score: 85420
}, {
name: 'HERO_MASTER',
score: 72350
}, {
name: 'FUSION_KING',
score: 68900
}, {
name: 'ACE_GAMER',
score: 55670
}];
// Add current player's best score to leaderboard
var playerBestScore = storage.bestScore || 0;
if (playerBestScore > 0) {
leaderboardData.push({
name: 'YOU',
score: playerBestScore
});
// Sort by score descending
leaderboardData.sort(function (a, b) {
return b.score - a.score;
});
// Keep only top 5
leaderboardData = leaderboardData.slice(0, 5);
}
// Display leaderboard entries
var _loop = function _loop() {
entry = leaderboardData[i];
rankText = i + 1 + '. ' + entry.name + ': ' + entry.score;
entryColor = entry.name === 'YOU' ? 0xFFD700 : entry.name === 'KEMALDEV' ? 0xFF0000 : 0xFFFFFF;
leaderboardEntry = new Text2(rankText, {
size: 50,
fill: entryColor
});
leaderboardEntry.anchor.set(0.5, 0.5);
leaderboardEntry.x = 2048 / 2;
leaderboardEntry.y = 1450 + i * 60;
menuContainer.addChild(leaderboardEntry);
// Add pulsing effect to player's score
if (entry.name === 'YOU') {
var _pulsePlayerScore = function pulsePlayerScore(textObj) {
tween(textObj, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(textObj, {
scaleX: 1,
scaleY: 1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
_pulsePlayerScore(textObj);
}
});
}
});
};
_pulsePlayerScore(leaderboardEntry);
}
},
entry,
rankText,
entryColor,
leaderboardEntry;
for (var i = 0; i < leaderboardData.length; i++) {
_loop();
}
// Win count display with neon styling
var totalWins = storage.totalWins || 0;
var winCountText = new Text2('WINS: ' + totalWins, {
size: 80,
fill: 0xFF00FF
});
winCountText.anchor.set(0.5, 0.5);
winCountText.x = 2048 / 2;
winCountText.y = 1800;
menuContainer.addChild(winCountText);
// Add neon glow animation to win count
function pulseWinCount() {
tween(winCountText, {
tint: 0xFF66FF,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(winCountText, {
tint: 0xFF00FF,
scaleX: 1,
scaleY: 1
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: pulseWinCount
});
}
});
}
pulseWinCount();
// Start button with neon styling
var startButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 1.5
});
startButton.x = 2048 / 2;
startButton.y = 2000;
startButton.tint = 0x003333;
startButton.alpha = 0.9;
menuContainer.addChild(startButton);
// Button border effect
var buttonBorder = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4.2,
scaleY: 1.7
});
buttonBorder.x = 2048 / 2;
buttonBorder.y = 2000;
buttonBorder.tint = 0x00FFFF;
buttonBorder.alpha = 0.7;
menuContainer.addChild(buttonBorder);
menuContainer.addChild(startButton); // Re-add to put on top
var startButtonText = new Text2('>>> START GAME <<<', {
size: 90,
fill: 0x00FFFF
});
startButtonText.anchor.set(0.5, 0.5);
startButtonText.x = 2048 / 2;
startButtonText.y = 2000;
menuContainer.addChild(startButtonText);
// Button interaction with neon effects
startButton.down = function () {
tween(startButton, {
tint: 0x006666,
scaleX: 3.8,
scaleY: 1.4
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(startButton, {
tint: 0x003333,
scaleX: 4,
scaleY: 1.5
}, {
duration: 100,
easing: tween.easeIn
});
}
});
tween(startButtonText, {
tint: 0x66FFFF
}, {
duration: 100,
onFinish: function onFinish() {
tween(startButtonText, {
tint: 0x00FFFF
}, {
duration: 100
});
}
});
startGame();
};
}
function startGame() {
if (menuContainer) {
menuContainer.destroy();
menuContainer = null;
}
gameStarted = true;
initializeGame();
}
function initializeGame() {
// Initialize grid
for (var y = 0; y < GRID_HEIGHT; y++) {
grid[y] = [];
for (var x = 0; x < GRID_WIDTH; x++) {
grid[y][x] = null;
// Create grid cell visuals
var cell = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5
});
cell.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2;
cell.y = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
cell.alpha = 0.3;
game.addChild(cell);
}
}
// Score display
scoreText = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
// KEMALDEV Logo
var logoGameText = new Text2('KEMALDEV', {
size: 120,
fill: 0xFFD700
});
logoGameText.anchor.set(0.5, 0);
logoGameText.x = 2048 / 2;
logoGameText.y = 150;
game.addChild(logoGameText);
// Add click detection to KEMALDEV logo in game
logoGameText.down = function () {
kemaldevClickCount++;
// Visual feedback for click
tween(logoGameText, {
scaleX: 1.2,
scaleY: 1.2,
tint: 0xFFFFFF
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(logoGameText, {
scaleX: 1,
scaleY: 1,
tint: 0xFFD700
}, {
duration: 100,
easing: tween.easeIn
});
}
});
// Check if clicked 2 times
if (kemaldevClickCount >= 2) {
// Increment win count in storage
storage.totalWins = (storage.totalWins || 0) + 1;
// Flash screen gold
LK.effects.flashScreen(0xFFD700, 1000);
// Show you win after short delay
LK.setTimeout(function () {
LK.showYouWin();
}, 500);
}
};
// Title
var titleText = new Text2('Hero Fusion Academy', {
size: 100,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0);
titleText.x = 2048 / 2;
titleText.y = 280;
game.addChild(titleText);
// Instructions
var instructionText = new Text2('Drag matching heroes to merge them!', {
size: 60,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
instructionText.x = 2048 / 2;
instructionText.y = 400;
game.addChild(instructionText);
// Spawn initial heroes
spawnHero();
spawnHero();
}
function getEmptyCell() {
var emptyCells = [];
for (var y = 0; y < GRID_HEIGHT; y++) {
for (var x = 0; x < GRID_WIDTH; x++) {
if (grid[y][x] === null) {
emptyCells.push({
x: x,
y: y
});
}
}
}
return emptyCells.length > 0 ? emptyCells[Math.floor(Math.random() * emptyCells.length)] : null;
}
function spawnHero() {
var emptyCell = getEmptyCell();
if (emptyCell) {
// Small chance to spawn power-up instead of hero
if (Math.random() < powerUpSpawnChance && LK.getScore() > 500) {
var powerUpTypes = ['score', 'clear', 'bomb'];
var powerUpType = powerUpTypes[Math.floor(Math.random() * powerUpTypes.length)];
var powerUp = new PowerUp(powerUpType);
powerUp.setGridPosition(emptyCell.x, emptyCell.y);
grid[emptyCell.y][emptyCell.x] = powerUp;
powerUps.push(powerUp);
game.addChild(powerUp);
// Spawn animation with special effect
powerUp.scaleX = 0;
powerUp.scaleY = 0;
tween(powerUp, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 400,
easing: tween.bounceOut
});
LK.effects.flashScreen(0xFFD700, 200);
return;
}
var tier = Math.random() < 0.8 ? 1 : 2; // 80% chance for tier 1, 20% for tier 2
var hero = new Hero(tier);
hero.setGridPosition(emptyCell.x, emptyCell.y);
grid[emptyCell.y][emptyCell.x] = hero;
heroes.push(hero);
game.addChild(hero);
// Spawn animation with subtle screen shake
hero.scaleX = 0;
hero.scaleY = 0;
tween(hero, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.bounceOut
});
// Add screen shake effect
tween(game, {
x: 5
}, {
duration: 50,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(game, {
x: -5
}, {
duration: 50,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(game, {
x: 0
}, {
duration: 50,
easing: tween.easeOut
});
}
});
}
});
LK.getSound('spawn').play();
} else {
// Grid is full - game over
gameOver = true;
// Animate all heroes shrinking before game over
for (var i = 0; i < heroes.length; i++) {
tween(heroes[i], {
scaleX: 0.8,
scaleY: 0.8,
alpha: 0.5
}, {
duration: 800,
easing: tween.easeIn
});
}
// Update best score in storage before game over
var currentScore = LK.getScore();
if (!storage.bestScore || currentScore > storage.bestScore) {
storage.bestScore = currentScore;
}
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
function performMerge(hero1, hero2) {
if (hero1.tier >= 9) return; // Max tier reached
// Combo system
var currentTime = Date.now();
if (currentTime - lastMergeTime < 3000) {
// 3 seconds for combo
comboCount++;
} else {
comboCount = 1;
}
lastMergeTime = currentTime;
comboTimer = 180; // 3 seconds at 60fps
// Calculate score with combo multiplier
var baseScore = hero1.tier * 100;
var comboMultiplier = Math.min(comboCount, 10); // Max 10x multiplier
var scoreIncrease = baseScore * comboMultiplier;
LK.setScore(LK.getScore() + scoreIncrease);
scoreText.setText('Score: ' + LK.getScore());
// Show combo text
if (comboCount > 1) {
if (comboText) comboText.destroy();
comboText = new Text2('COMBO x' + comboCount + '!', {
size: 80,
fill: 0xFF4444
});
comboText.anchor.set(0.5, 0.5);
comboText.x = 2048 / 2;
comboText.y = 500;
comboText.alpha = 0;
game.addChild(comboText);
tween(comboText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2,
y: 450
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(comboText, {
alpha: 0,
y: 400
}, {
duration: 1000,
easing: tween.easeOut
});
}
});
}
// Remove both heroes from grid
grid[hero1.gridY][hero1.gridX] = null;
grid[hero2.gridY][hero2.gridX] = null;
// Create new hero with higher tier
var newHero = new Hero(hero1.tier + 1);
newHero.setGridPosition(hero2.gridX, hero2.gridY);
grid[hero2.gridY][hero2.gridX] = newHero;
heroes.push(newHero);
game.addChild(newHero);
// Merge animation
newHero.scaleX = 0;
newHero.scaleY = 0;
tween(newHero, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut
});
tween(newHero, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeIn
});
// Flash effect with color transition
LK.effects.flashObject(newHero, 0xFFFFFF, 500);
// Create particle explosion
var particleColors = [0xFFD700, 0xFF6B6B, 0x4ECDC4, 0x45B7D1, 0xF9CA24];
for (var i = 0; i < 8; i++) {
var particle = new Particle(newHero.x + (Math.random() - 0.5) * 40, newHero.y + (Math.random() - 0.5) * 40, particleColors[Math.floor(Math.random() * particleColors.length)]);
particles.push(particle);
game.addChild(particle);
}
// Add golden glow effect for high-tier merges
if (newHero.tier >= 4) {
tween(newHero, {
tint: 0xFFD700
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(newHero, {
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.easeIn
});
}
});
}
// Remove old heroes
hero1.destroy();
hero2.destroy();
// Remove from heroes array
var index1 = heroes.indexOf(hero1);
if (index1 > -1) heroes.splice(index1, 1);
var index2 = heroes.indexOf(hero2);
if (index2 > -1) heroes.splice(index2, 1);
LK.getSound('merge').play();
// Check for win condition (tier 9 hero created)
if (newHero.tier >= 9) {
// Increment win count in storage
storage.totalWins = (storage.totalWins || 0) + 1;
// Update best score in storage
var currentScore = LK.getScore();
if (!storage.bestScore || currentScore > storage.bestScore) {
storage.bestScore = currentScore;
}
// Add special rainbow effect for max tier hero
var rainbowCycle = function rainbowCycle() {
var colors = [0xFF0000, 0xFF8000, 0xFFFF00, 0x00FF00, 0x0080FF, 0x8000FF];
var colorIndex = 0;
function nextColor() {
tween(newHero, {
tint: colors[colorIndex]
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
colorIndex = (colorIndex + 1) % colors.length;
nextColor();
}
});
}
nextColor();
};
rainbowCycle();
LK.setTimeout(function () {
LK.showYouWin();
}, 1000);
}
}
game.move = function (x, y, obj) {
if (draggedHero && draggedHero.isDragging) {
draggedHero.x = x;
draggedHero.y = y;
}
};
game.update = function () {
if (gameStarted && !gameOver) {
spawnTimer++;
if (spawnTimer >= spawnInterval) {
spawnHero();
spawnTimer = 0;
// Gradually decrease spawn interval to increase difficulty
if (spawnInterval > 120) {
spawnInterval -= 2;
}
}
// Update combo timer
if (comboTimer > 0) {
comboTimer--;
if (comboTimer <= 0 && comboCount > 0) {
comboCount = 0;
if (comboText) {
tween(comboText, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
comboText.destroy();
comboText = null;
}
});
}
}
}
// Clean up destroyed particles (update is called automatically by LK)
for (var i = particles.length - 1; i >= 0; i--) {
if (!particles[i].parent) {
particles.splice(i, 1);
}
}
}
};
// Show KEMALDEV splash screen first, then main menu
showKemaldevSplash();
function showKemaldevSplash() {
var splashContainer = new Container();
splashContainer.alpha = 0;
game.addChild(splashContainer);
// Black background for splash
var splashBg = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 20,
scaleY: 25
});
splashBg.x = 2048 / 2;
splashBg.y = 2732 / 2;
splashBg.tint = 0x000000;
splashContainer.addChild(splashBg);
// Large KEMALDEV text positioned at the top
var kemaldevText = new Text2('KEMALDEV', {
size: 300,
fill: 0xFFD700
});
kemaldevText.anchor.set(0.5, 0.5);
kemaldevText.x = 2048 / 2;
kemaldevText.y = 800;
kemaldevText.alpha = 0;
kemaldevText.scaleX = 0.5;
kemaldevText.scaleY = 0.5;
splashContainer.addChild(kemaldevText);
// Add click detection to KEMALDEV logo in splash
kemaldevText.down = function () {
kemaldevClickCount++;
// Visual feedback for click
tween(kemaldevText, {
scaleX: 1.4,
scaleY: 1.4,
tint: 0xFFFFFF
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(kemaldevText, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xFFD700
}, {
duration: 100,
easing: tween.easeIn
});
}
});
// Check if clicked 2 times
if (kemaldevClickCount >= 2) {
// Increment win count in storage
storage.totalWins = (storage.totalWins || 0) + 1;
// Flash screen gold
LK.effects.flashScreen(0xFFD700, 1000);
// Show you win after short delay
LK.setTimeout(function () {
LK.showYouWin();
}, 500);
}
};
// Developer subtitle
var devText = new Text2('Game Developer', {
size: 120,
fill: 0xFFFFFF
});
devText.anchor.set(0.5, 0.5);
devText.x = 2048 / 2;
devText.y = 1200;
devText.alpha = 0;
splashContainer.addChild(devText);
// Fade in splash screen
tween(splashContainer, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Animate KEMALDEV text entrance with scale and fade
tween(kemaldevText, {
alpha: 1,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 1000,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Scale back to normal size
tween(kemaldevText, {
scaleX: 1,
scaleY: 1
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
// Fade in subtitle
tween(devText, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Add pulsing effect to logo
function pulseLogo() {
tween(kemaldevText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(kemaldevText, {
scaleX: 1,
scaleY: 1
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: pulseLogo
});
}
});
}
pulseLogo();
// Hold for a moment, then fade out and show menu
LK.setTimeout(function () {
tween(splashContainer, {
alpha: 0
}, {
duration: 800,
easing: tween.easeIn,
onFinish: function onFinish() {
splashContainer.destroy();
showMainMenu();
}
});
}, 2500);
}
});
}
});
}
});
}
});
} /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Hero = Container.expand(function (tier) {
var self = Container.call(this);
self.tier = tier || 1;
self.gridX = -1;
self.gridY = -1;
self.isDragging = false;
self.originalX = 0;
self.originalY = 0;
var heroAssets = ['heroTier1', 'heroTier2', 'heroTier3', 'heroTier4', 'heroTier5', 'heroTier6', 'heroTier7', 'heroTier8', 'heroTier9'];
var heroGraphics = self.attachAsset(heroAssets[self.tier - 1], {
anchorX: 0.5,
anchorY: 0.5
});
// Tier text removed - heroes now display without numbers
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
self.originalX = self.x;
self.originalY = self.y;
};
self.down = function (x, y, obj) {
if (!gameOver) {
self.isDragging = true;
draggedHero = self;
self.originalX = self.x;
self.originalY = self.y;
tween(self, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100
});
}
};
self.up = function (x, y, obj) {
if (self.isDragging) {
self.isDragging = false;
draggedHero = null;
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
// Check for merge
var targetGridX = Math.floor((self.x - GRID_START_X) / CELL_SIZE);
var targetGridY = Math.floor((self.y - GRID_START_Y) / CELL_SIZE);
if (targetGridX >= 0 && targetGridX < GRID_WIDTH && targetGridY >= 0 && targetGridY < GRID_HEIGHT) {
var targetHero = grid[targetGridY][targetGridX];
if (targetHero && targetHero !== self && targetHero.tier === self.tier) {
// Merge!
performMerge(self, targetHero);
return;
}
}
// Return to original position with bounce effect
tween(self, {
x: self.originalX,
y: self.originalY
}, {
duration: 300,
easing: tween.bounceOut
});
}
};
return self;
});
var Particle = Container.expand(function (x, y, color) {
var self = Container.call(this);
self.x = x;
self.y = y;
var particle = self.attachAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1
});
particle.tint = color;
self.velocity = {
x: (Math.random() - 0.5) * 20,
y: (Math.random() - 0.5) * 20 - 10
};
self.life = 1.0;
self.update = function () {
self.x += self.velocity.x;
self.y += self.velocity.y;
self.velocity.y += 0.5; // gravity
self.life -= 0.02;
particle.alpha = self.life;
if (self.life <= 0) {
self.destroy();
var index = particles.indexOf(self);
if (index > -1) particles.splice(index, 1);
}
};
return self;
});
var PowerUp = Container.expand(function (type) {
var self = Container.call(this);
self.type = type; // 'score', 'clear', 'bomb'
self.gridX = -1;
self.gridY = -1;
self.isUsed = false;
var colors = {
score: 0xFFD700,
clear: 0x00FF00,
bomb: 0xFF4444
};
var powerUpGraphics = self.attachAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
powerUpGraphics.tint = colors[type];
// Add pulsing animation
function pulse() {
tween(powerUpGraphics, {
scaleX: 0.9,
scaleY: 0.9,
alpha: 0.8
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(powerUpGraphics, {
scaleX: 0.8,
scaleY: 0.8,
alpha: 1.0
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: pulse
});
}
});
}
pulse();
// Power-up symbol
var symbol = new Text2(type === 'score' ? '$' : type === 'clear' ? '✓' : '💥', {
size: 60,
fill: 0xFFFFFF
});
symbol.anchor.set(0.5, 0.5);
self.addChild(symbol);
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
};
self.activate = function () {
if (self.isUsed) return;
self.isUsed = true;
if (self.type === 'score') {
LK.setScore(LK.getScore() + 500);
scoreText.setText('Score: ' + LK.getScore());
LK.effects.flashScreen(0xFFD700, 300);
} else if (self.type === 'clear') {
// Clear bottom row
for (var x = 0; x < GRID_WIDTH; x++) {
if (grid[GRID_HEIGHT - 1][x]) {
var hero = grid[GRID_HEIGHT - 1][x];
grid[GRID_HEIGHT - 1][x] = null;
hero.destroy();
var index = heroes.indexOf(hero);
if (index > -1) heroes.splice(index, 1);
}
}
LK.effects.flashScreen(0x00FF00, 300);
} else if (self.type === 'bomb') {
// Destroy 3x3 area around power-up
for (var dy = -1; dy <= 1; dy++) {
for (var dx = -1; dx <= 1; dx++) {
var targetX = self.gridX + dx;
var targetY = self.gridY + dy;
if (targetX >= 0 && targetX < GRID_WIDTH && targetY >= 0 && targetY < GRID_HEIGHT) {
if (grid[targetY][targetX] && grid[targetY][targetX] !== self) {
var hero = grid[targetY][targetX];
grid[targetY][targetX] = null;
hero.destroy();
var index = heroes.indexOf(hero);
if (index > -1) heroes.splice(index, 1);
}
}
}
}
LK.effects.flashScreen(0xFF4444, 300);
}
// Remove power-up from grid
grid[self.gridY][self.gridX] = null;
self.destroy();
var powerUpIndex = powerUps.indexOf(self);
if (powerUpIndex > -1) powerUps.splice(powerUpIndex, 1);
};
self.down = function () {
self.activate();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a1a
});
/****
* Game Code
****/
var GRID_WIDTH = 5;
var GRID_HEIGHT = 7;
var CELL_SIZE = 140;
var GRID_START_X = (2048 - GRID_WIDTH * CELL_SIZE) / 2;
var GRID_START_Y = 600;
var grid = [];
var heroes = [];
var draggedHero = null;
var gameOver = false;
var gameStarted = false;
var spawnTimer = 0;
var spawnInterval = 180; // 3 seconds at 60fps
var menuContainer = null;
var scoreText = null;
var particles = [];
var powerUps = [];
var powerUpSpawnChance = 0.05; // 5% chance to spawn power-up instead of hero
var comboCount = 0;
var comboTimer = 0;
var comboText = null;
var lastMergeTime = 0;
var kemaldevClickCount = 0;
function showMainMenu() {
// Start background music
LK.playMusic('backgroundMusic');
menuContainer = new Container();
menuContainer.alpha = 0;
game.addChild(menuContainer);
// Fade in menu
tween(menuContainer, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
// Dark urban background with gradient effect using multiple layers
var menuBg1 = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 15,
scaleY: 20
});
menuBg1.x = 2048 / 2;
menuBg1.y = 2732 / 2;
menuBg1.tint = 0x0a0a0a;
menuBg1.alpha = 1.0;
menuContainer.addChild(menuBg1);
// Add dark cyan overlay for GTA 2 aesthetic
var menuBg2 = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 15,
scaleY: 20
});
menuBg2.x = 2048 / 2;
menuBg2.y = 2732 / 2;
menuBg2.tint = 0x003333;
menuBg2.alpha = 0.6;
menuContainer.addChild(menuBg2);
// KEMALDEV Logo with neon cyan color
var logoText = new Text2('KEMALDEV', {
size: 220,
fill: 0x00FFFF
});
logoText.anchor.set(0.5, 0.5);
logoText.x = 2048 / 2;
logoText.y = 900;
menuContainer.addChild(logoText);
// Add click detection to KEMALDEV logo
logoText.down = function () {
kemaldevClickCount++;
// Visual feedback for click
tween(logoText, {
scaleX: 1.2,
scaleY: 1.2,
tint: 0xFFFFFF
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(logoText, {
scaleX: 1,
scaleY: 1,
tint: 0x00FFFF
}, {
duration: 100,
easing: tween.easeIn
});
}
});
// Check if clicked 2 times
if (kemaldevClickCount >= 2) {
// Increment win count in storage
storage.totalWins = (storage.totalWins || 0) + 1;
// Flash screen gold
LK.effects.flashScreen(0xFFD700, 1000);
// Show you win after short delay
LK.setTimeout(function () {
LK.showYouWin();
}, 500);
}
};
// Game title with neon green color
var gameTitle = new Text2('HERO FUSION ACADEMY', {
size: 120,
fill: 0x00FF00
});
gameTitle.anchor.set(0.5, 0.5);
gameTitle.x = 2048 / 2;
gameTitle.y = 1150;
menuContainer.addChild(gameTitle);
// Add neon glow pulsing animation to KEMALDEV logo
function pulseLogo() {
tween(logoText, {
tint: 0x66FFFF,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 1200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(logoText, {
tint: 0x00FFFF,
scaleX: 1,
scaleY: 1
}, {
duration: 1200,
easing: tween.easeInOut,
onFinish: pulseLogo
});
}
});
}
pulseLogo();
// Add neon glow pulsing animation to title
function pulseTitle() {
tween(gameTitle, {
tint: 0x66FF66,
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(gameTitle, {
tint: 0x00FF00,
scaleX: 1,
scaleY: 1
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: pulseTitle
});
}
});
}
pulseTitle();
// Subtitle with neon yellow
var subtitle = new Text2('MERGE IDENTICAL HEROES TO CREATE POWERFUL CHAMPIONS!', {
size: 70,
fill: 0xFFFF00
});
subtitle.anchor.set(0.5, 0.5);
subtitle.x = 2048 / 2;
subtitle.y = 1300;
menuContainer.addChild(subtitle);
// Online Leaderboard
var leaderboardTitle = new Text2('ONLINE LEADERBOARD', {
size: 80,
fill: 0x00FFFF
});
leaderboardTitle.anchor.set(0.5, 0.5);
leaderboardTitle.x = 2048 / 2;
leaderboardTitle.y = 1400;
menuContainer.addChild(leaderboardTitle);
// Simulated online scores (in a real implementation, this would come from a server)
var leaderboardData = [{
name: 'KEMALDEV',
score: 99999
}, {
name: 'PLAYER_X',
score: 85420
}, {
name: 'HERO_MASTER',
score: 72350
}, {
name: 'FUSION_KING',
score: 68900
}, {
name: 'ACE_GAMER',
score: 55670
}];
// Add current player's best score to leaderboard
var playerBestScore = storage.bestScore || 0;
if (playerBestScore > 0) {
leaderboardData.push({
name: 'YOU',
score: playerBestScore
});
// Sort by score descending
leaderboardData.sort(function (a, b) {
return b.score - a.score;
});
// Keep only top 5
leaderboardData = leaderboardData.slice(0, 5);
}
// Display leaderboard entries
var _loop = function _loop() {
entry = leaderboardData[i];
rankText = i + 1 + '. ' + entry.name + ': ' + entry.score;
entryColor = entry.name === 'YOU' ? 0xFFD700 : entry.name === 'KEMALDEV' ? 0xFF0000 : 0xFFFFFF;
leaderboardEntry = new Text2(rankText, {
size: 50,
fill: entryColor
});
leaderboardEntry.anchor.set(0.5, 0.5);
leaderboardEntry.x = 2048 / 2;
leaderboardEntry.y = 1450 + i * 60;
menuContainer.addChild(leaderboardEntry);
// Add pulsing effect to player's score
if (entry.name === 'YOU') {
var _pulsePlayerScore = function pulsePlayerScore(textObj) {
tween(textObj, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(textObj, {
scaleX: 1,
scaleY: 1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
_pulsePlayerScore(textObj);
}
});
}
});
};
_pulsePlayerScore(leaderboardEntry);
}
},
entry,
rankText,
entryColor,
leaderboardEntry;
for (var i = 0; i < leaderboardData.length; i++) {
_loop();
}
// Win count display with neon styling
var totalWins = storage.totalWins || 0;
var winCountText = new Text2('WINS: ' + totalWins, {
size: 80,
fill: 0xFF00FF
});
winCountText.anchor.set(0.5, 0.5);
winCountText.x = 2048 / 2;
winCountText.y = 1800;
menuContainer.addChild(winCountText);
// Add neon glow animation to win count
function pulseWinCount() {
tween(winCountText, {
tint: 0xFF66FF,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(winCountText, {
tint: 0xFF00FF,
scaleX: 1,
scaleY: 1
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: pulseWinCount
});
}
});
}
pulseWinCount();
// Start button with neon styling
var startButton = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 1.5
});
startButton.x = 2048 / 2;
startButton.y = 2000;
startButton.tint = 0x003333;
startButton.alpha = 0.9;
menuContainer.addChild(startButton);
// Button border effect
var buttonBorder = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4.2,
scaleY: 1.7
});
buttonBorder.x = 2048 / 2;
buttonBorder.y = 2000;
buttonBorder.tint = 0x00FFFF;
buttonBorder.alpha = 0.7;
menuContainer.addChild(buttonBorder);
menuContainer.addChild(startButton); // Re-add to put on top
var startButtonText = new Text2('>>> START GAME <<<', {
size: 90,
fill: 0x00FFFF
});
startButtonText.anchor.set(0.5, 0.5);
startButtonText.x = 2048 / 2;
startButtonText.y = 2000;
menuContainer.addChild(startButtonText);
// Button interaction with neon effects
startButton.down = function () {
tween(startButton, {
tint: 0x006666,
scaleX: 3.8,
scaleY: 1.4
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(startButton, {
tint: 0x003333,
scaleX: 4,
scaleY: 1.5
}, {
duration: 100,
easing: tween.easeIn
});
}
});
tween(startButtonText, {
tint: 0x66FFFF
}, {
duration: 100,
onFinish: function onFinish() {
tween(startButtonText, {
tint: 0x00FFFF
}, {
duration: 100
});
}
});
startGame();
};
}
function startGame() {
if (menuContainer) {
menuContainer.destroy();
menuContainer = null;
}
gameStarted = true;
initializeGame();
}
function initializeGame() {
// Initialize grid
for (var y = 0; y < GRID_HEIGHT; y++) {
grid[y] = [];
for (var x = 0; x < GRID_WIDTH; x++) {
grid[y][x] = null;
// Create grid cell visuals
var cell = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5
});
cell.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2;
cell.y = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
cell.alpha = 0.3;
game.addChild(cell);
}
}
// Score display
scoreText = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
// KEMALDEV Logo
var logoGameText = new Text2('KEMALDEV', {
size: 120,
fill: 0xFFD700
});
logoGameText.anchor.set(0.5, 0);
logoGameText.x = 2048 / 2;
logoGameText.y = 150;
game.addChild(logoGameText);
// Add click detection to KEMALDEV logo in game
logoGameText.down = function () {
kemaldevClickCount++;
// Visual feedback for click
tween(logoGameText, {
scaleX: 1.2,
scaleY: 1.2,
tint: 0xFFFFFF
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(logoGameText, {
scaleX: 1,
scaleY: 1,
tint: 0xFFD700
}, {
duration: 100,
easing: tween.easeIn
});
}
});
// Check if clicked 2 times
if (kemaldevClickCount >= 2) {
// Increment win count in storage
storage.totalWins = (storage.totalWins || 0) + 1;
// Flash screen gold
LK.effects.flashScreen(0xFFD700, 1000);
// Show you win after short delay
LK.setTimeout(function () {
LK.showYouWin();
}, 500);
}
};
// Title
var titleText = new Text2('Hero Fusion Academy', {
size: 100,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0);
titleText.x = 2048 / 2;
titleText.y = 280;
game.addChild(titleText);
// Instructions
var instructionText = new Text2('Drag matching heroes to merge them!', {
size: 60,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
instructionText.x = 2048 / 2;
instructionText.y = 400;
game.addChild(instructionText);
// Spawn initial heroes
spawnHero();
spawnHero();
}
function getEmptyCell() {
var emptyCells = [];
for (var y = 0; y < GRID_HEIGHT; y++) {
for (var x = 0; x < GRID_WIDTH; x++) {
if (grid[y][x] === null) {
emptyCells.push({
x: x,
y: y
});
}
}
}
return emptyCells.length > 0 ? emptyCells[Math.floor(Math.random() * emptyCells.length)] : null;
}
function spawnHero() {
var emptyCell = getEmptyCell();
if (emptyCell) {
// Small chance to spawn power-up instead of hero
if (Math.random() < powerUpSpawnChance && LK.getScore() > 500) {
var powerUpTypes = ['score', 'clear', 'bomb'];
var powerUpType = powerUpTypes[Math.floor(Math.random() * powerUpTypes.length)];
var powerUp = new PowerUp(powerUpType);
powerUp.setGridPosition(emptyCell.x, emptyCell.y);
grid[emptyCell.y][emptyCell.x] = powerUp;
powerUps.push(powerUp);
game.addChild(powerUp);
// Spawn animation with special effect
powerUp.scaleX = 0;
powerUp.scaleY = 0;
tween(powerUp, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 400,
easing: tween.bounceOut
});
LK.effects.flashScreen(0xFFD700, 200);
return;
}
var tier = Math.random() < 0.8 ? 1 : 2; // 80% chance for tier 1, 20% for tier 2
var hero = new Hero(tier);
hero.setGridPosition(emptyCell.x, emptyCell.y);
grid[emptyCell.y][emptyCell.x] = hero;
heroes.push(hero);
game.addChild(hero);
// Spawn animation with subtle screen shake
hero.scaleX = 0;
hero.scaleY = 0;
tween(hero, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.bounceOut
});
// Add screen shake effect
tween(game, {
x: 5
}, {
duration: 50,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(game, {
x: -5
}, {
duration: 50,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(game, {
x: 0
}, {
duration: 50,
easing: tween.easeOut
});
}
});
}
});
LK.getSound('spawn').play();
} else {
// Grid is full - game over
gameOver = true;
// Animate all heroes shrinking before game over
for (var i = 0; i < heroes.length; i++) {
tween(heroes[i], {
scaleX: 0.8,
scaleY: 0.8,
alpha: 0.5
}, {
duration: 800,
easing: tween.easeIn
});
}
// Update best score in storage before game over
var currentScore = LK.getScore();
if (!storage.bestScore || currentScore > storage.bestScore) {
storage.bestScore = currentScore;
}
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
function performMerge(hero1, hero2) {
if (hero1.tier >= 9) return; // Max tier reached
// Combo system
var currentTime = Date.now();
if (currentTime - lastMergeTime < 3000) {
// 3 seconds for combo
comboCount++;
} else {
comboCount = 1;
}
lastMergeTime = currentTime;
comboTimer = 180; // 3 seconds at 60fps
// Calculate score with combo multiplier
var baseScore = hero1.tier * 100;
var comboMultiplier = Math.min(comboCount, 10); // Max 10x multiplier
var scoreIncrease = baseScore * comboMultiplier;
LK.setScore(LK.getScore() + scoreIncrease);
scoreText.setText('Score: ' + LK.getScore());
// Show combo text
if (comboCount > 1) {
if (comboText) comboText.destroy();
comboText = new Text2('COMBO x' + comboCount + '!', {
size: 80,
fill: 0xFF4444
});
comboText.anchor.set(0.5, 0.5);
comboText.x = 2048 / 2;
comboText.y = 500;
comboText.alpha = 0;
game.addChild(comboText);
tween(comboText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2,
y: 450
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(comboText, {
alpha: 0,
y: 400
}, {
duration: 1000,
easing: tween.easeOut
});
}
});
}
// Remove both heroes from grid
grid[hero1.gridY][hero1.gridX] = null;
grid[hero2.gridY][hero2.gridX] = null;
// Create new hero with higher tier
var newHero = new Hero(hero1.tier + 1);
newHero.setGridPosition(hero2.gridX, hero2.gridY);
grid[hero2.gridY][hero2.gridX] = newHero;
heroes.push(newHero);
game.addChild(newHero);
// Merge animation
newHero.scaleX = 0;
newHero.scaleY = 0;
tween(newHero, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut
});
tween(newHero, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeIn
});
// Flash effect with color transition
LK.effects.flashObject(newHero, 0xFFFFFF, 500);
// Create particle explosion
var particleColors = [0xFFD700, 0xFF6B6B, 0x4ECDC4, 0x45B7D1, 0xF9CA24];
for (var i = 0; i < 8; i++) {
var particle = new Particle(newHero.x + (Math.random() - 0.5) * 40, newHero.y + (Math.random() - 0.5) * 40, particleColors[Math.floor(Math.random() * particleColors.length)]);
particles.push(particle);
game.addChild(particle);
}
// Add golden glow effect for high-tier merges
if (newHero.tier >= 4) {
tween(newHero, {
tint: 0xFFD700
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(newHero, {
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.easeIn
});
}
});
}
// Remove old heroes
hero1.destroy();
hero2.destroy();
// Remove from heroes array
var index1 = heroes.indexOf(hero1);
if (index1 > -1) heroes.splice(index1, 1);
var index2 = heroes.indexOf(hero2);
if (index2 > -1) heroes.splice(index2, 1);
LK.getSound('merge').play();
// Check for win condition (tier 9 hero created)
if (newHero.tier >= 9) {
// Increment win count in storage
storage.totalWins = (storage.totalWins || 0) + 1;
// Update best score in storage
var currentScore = LK.getScore();
if (!storage.bestScore || currentScore > storage.bestScore) {
storage.bestScore = currentScore;
}
// Add special rainbow effect for max tier hero
var rainbowCycle = function rainbowCycle() {
var colors = [0xFF0000, 0xFF8000, 0xFFFF00, 0x00FF00, 0x0080FF, 0x8000FF];
var colorIndex = 0;
function nextColor() {
tween(newHero, {
tint: colors[colorIndex]
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
colorIndex = (colorIndex + 1) % colors.length;
nextColor();
}
});
}
nextColor();
};
rainbowCycle();
LK.setTimeout(function () {
LK.showYouWin();
}, 1000);
}
}
game.move = function (x, y, obj) {
if (draggedHero && draggedHero.isDragging) {
draggedHero.x = x;
draggedHero.y = y;
}
};
game.update = function () {
if (gameStarted && !gameOver) {
spawnTimer++;
if (spawnTimer >= spawnInterval) {
spawnHero();
spawnTimer = 0;
// Gradually decrease spawn interval to increase difficulty
if (spawnInterval > 120) {
spawnInterval -= 2;
}
}
// Update combo timer
if (comboTimer > 0) {
comboTimer--;
if (comboTimer <= 0 && comboCount > 0) {
comboCount = 0;
if (comboText) {
tween(comboText, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
comboText.destroy();
comboText = null;
}
});
}
}
}
// Clean up destroyed particles (update is called automatically by LK)
for (var i = particles.length - 1; i >= 0; i--) {
if (!particles[i].parent) {
particles.splice(i, 1);
}
}
}
};
// Show KEMALDEV splash screen first, then main menu
showKemaldevSplash();
function showKemaldevSplash() {
var splashContainer = new Container();
splashContainer.alpha = 0;
game.addChild(splashContainer);
// Black background for splash
var splashBg = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 20,
scaleY: 25
});
splashBg.x = 2048 / 2;
splashBg.y = 2732 / 2;
splashBg.tint = 0x000000;
splashContainer.addChild(splashBg);
// Large KEMALDEV text positioned at the top
var kemaldevText = new Text2('KEMALDEV', {
size: 300,
fill: 0xFFD700
});
kemaldevText.anchor.set(0.5, 0.5);
kemaldevText.x = 2048 / 2;
kemaldevText.y = 800;
kemaldevText.alpha = 0;
kemaldevText.scaleX = 0.5;
kemaldevText.scaleY = 0.5;
splashContainer.addChild(kemaldevText);
// Add click detection to KEMALDEV logo in splash
kemaldevText.down = function () {
kemaldevClickCount++;
// Visual feedback for click
tween(kemaldevText, {
scaleX: 1.4,
scaleY: 1.4,
tint: 0xFFFFFF
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(kemaldevText, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xFFD700
}, {
duration: 100,
easing: tween.easeIn
});
}
});
// Check if clicked 2 times
if (kemaldevClickCount >= 2) {
// Increment win count in storage
storage.totalWins = (storage.totalWins || 0) + 1;
// Flash screen gold
LK.effects.flashScreen(0xFFD700, 1000);
// Show you win after short delay
LK.setTimeout(function () {
LK.showYouWin();
}, 500);
}
};
// Developer subtitle
var devText = new Text2('Game Developer', {
size: 120,
fill: 0xFFFFFF
});
devText.anchor.set(0.5, 0.5);
devText.x = 2048 / 2;
devText.y = 1200;
devText.alpha = 0;
splashContainer.addChild(devText);
// Fade in splash screen
tween(splashContainer, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Animate KEMALDEV text entrance with scale and fade
tween(kemaldevText, {
alpha: 1,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 1000,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Scale back to normal size
tween(kemaldevText, {
scaleX: 1,
scaleY: 1
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
// Fade in subtitle
tween(devText, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Add pulsing effect to logo
function pulseLogo() {
tween(kemaldevText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(kemaldevText, {
scaleX: 1,
scaleY: 1
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: pulseLogo
});
}
});
}
pulseLogo();
// Hold for a moment, then fade out and show menu
LK.setTimeout(function () {
tween(splashContainer, {
alpha: 0
}, {
duration: 800,
easing: tween.easeIn,
onFinish: function onFinish() {
splashContainer.destroy();
showMainMenu();
}
});
}, 2500);
}
});
}
});
}
});
}
});
}
pixel art Hulk. In-Game asset. 2d. High contrast. No shadows
attack on titan colossal titan pixel art. In-Game asset. 2d. High contrast. No shadows
KANEKİ PİXEL ART GHOUL. In-Game asset. 2d. High contrast. No shadows
PİXEL ART SİLVER SURFER. In-Game asset. 2d. High contrast. No shadows
Pixel art
pixel art red gurdian. In-Game asset. 2d. High contrast. No shadows
pixel art Hero. In-Game asset. 2d. High contrast. No shadows
PNG