/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Meme = Container.expand(function () {
var self = Container.call(this);
var memeGraphics = self.attachAsset('Meme', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.active = true;
self.scale = 1;
self.rotation = 0;
self.rotationSpeed = 0;
self.update = function () {
if (self.active) {
self.x += self.speed;
self.rotation += self.rotationSpeed;
// If meme goes off-screen, reset or deactivate
if (self.x < -100 || self.x > 2148) {
self.active = false;
}
}
};
self.reset = function (x, y, speed, scale, rotSpeed) {
self.x = x;
self.y = y;
self.speed = speed;
self.scale = scale || 1;
self.scaleX = self.scale;
self.scaleY = self.scale;
self.rotationSpeed = rotSpeed || 0;
self.active = true;
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.active = true;
self.update = function () {
if (self.active) {
self.x += self.speed;
// If obstacle goes off-screen, reset
if (self.x < -100 || self.x > 2148) {
self.active = false;
}
}
};
self.reset = function (x, y, speed) {
self.x = x;
self.y = y;
self.speed = speed;
self.active = true;
};
return self;
});
var Platform = Container.expand(function () {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.active = true;
self.update = function () {
if (self.active) {
self.x += self.speed;
// If platform goes off-screen, reset
if (self.x < -250 || self.x > 2298) {
self.active = false;
}
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('playerCircle', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocity = {
x: 0,
y: 0
};
self.isJumping = false;
self.isDraggable = false;
self.jump = function () {
if (!self.isJumping) {
self.velocity.y = -20;
self.isJumping = true;
LK.getSound('jump').play();
}
};
self.reset = function (x, y) {
self.x = x;
self.y = y;
self.velocity = {
x: 0,
y: 0
};
self.isJumping = false;
};
self.down = function (x, y, obj) {
if (self.isDraggable) {
draggedObject = self;
}
};
return self;
});
var ProgressBar = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('progressBar', {
anchorX: 0,
anchorY: 0.5
});
var fill = self.attachAsset('progressFill', {
anchorX: 0,
anchorY: 0.5
});
self.setProgress = function (percent) {
fill.width = Math.min(1800 * (percent / 100), 1800);
};
return self;
});
var Target = Container.expand(function () {
var self = Container.call(this);
var targetGraphics = self.attachAsset('target', {
anchorX: 0.5,
anchorY: 0.5
});
self.active = true;
self.pulse = function () {
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeIn
});
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x34495e
});
/****
* Game Code
****/
var GRAVITY = 0.8;
var GROUND_Y = 2400;
var gameState = "title"; // "title", "playing", "gameOver"
var currentLevel = 1;
var maxLevels = 5;
var levelDuration = 20000; // 20 seconds per level
var levelStartTime = 0;
var draggedObject = null;
var player;
var obstacles = [];
var platforms = [];
var targets = [];
var progressBar;
var scoreText;
var levelText;
var timerText;
var titleText;
var instructionText;
var gameOverText;
var countdownText;
var countdownValue = 3;
var levelDescriptions = ["Dodge the memes!", "Cross the platforms!", "Hit the targets!", "Stay in bounds!", "Survive them all!"];
// Initialize game UI
function initializeUI() {
// Progress bar
progressBar = new ProgressBar();
progressBar.x = 124;
progressBar.y = 100;
LK.gui.addChild(progressBar);
// Score
scoreText = new Text2("Score: 0", {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreText);
// Level
levelText = new Text2("Level: 1", {
size: 60,
fill: 0xFFFFFF
});
levelText.anchor.set(0, 0);
levelText.x = 124;
LK.gui.topLeft.addChild(levelText);
levelText.y = 150;
// Timer
timerText = new Text2("20", {
size: 60,
fill: 0xFFFFFF
});
timerText.anchor.set(0.5, 0);
LK.gui.top.addChild(timerText);
// Title
titleText = new Text2("MEME SURVIVAL\nCHALLENGE", {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.visible = true;
LK.gui.center.addChild(titleText);
// Instruction
instructionText = new Text2("Tap to Start", {
size: 60,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.y = 200;
instructionText.visible = true;
LK.gui.center.addChild(instructionText);
// Countdown
countdownText = new Text2("3", {
size: 200,
fill: 0xFFFFFF
});
countdownText.anchor.set(0.5, 0.5);
countdownText.visible = false;
LK.gui.center.addChild(countdownText);
// Level description
gameOverText = new Text2("", {
size: 60,
fill: 0xFFFFFF
});
gameOverText.anchor.set(0.5, 0.5);
gameOverText.y = 300;
gameOverText.visible = false;
LK.gui.center.addChild(gameOverText);
}
// Initialize player
function initializePlayer() {
player = new Player();
player.reset(1024, 1366);
game.addChild(player);
}
// Initialize obstacles based on level
function initializeLevel(level) {
// Clear any existing objects
clearLevel();
// Update UI
levelText.setText("Level: " + level);
gameOverText.setText(levelDescriptions[level - 1]);
gameOverText.visible = true;
// Set timer
levelStartTime = Date.now();
// Configure level
switch (level) {
case 1:
// Dodge memes level
setupDodgeLevel();
break;
case 2:
// Platform level
setupPlatformLevel();
break;
case 3:
// Target level
setupTargetLevel();
break;
case 4:
// Boundary level
setupBoundaryLevel();
break;
case 5:
// Final level - combination
setupFinalLevel();
break;
}
}
function setupDodgeLevel() {
player.isDraggable = true;
player.reset(1024, 1366);
// Create memes instead of obstacles
for (var i = 0; i < 15; i++) {
var meme = new Meme();
var scale = 0.8 + Math.random() * 1.5;
var rotSpeed = (Math.random() - 0.5) * 0.1;
var speed = -5 - Math.random() * 7;
// Alternate memes coming from left and right with varying patterns
if (i % 3 === 0) {
meme.reset(-100, 400 + Math.random() * 1700, Math.abs(speed), scale, rotSpeed);
} else if (i % 3 === 1) {
meme.reset(2300, 400 + Math.random() * 1700, speed, scale, rotSpeed);
} else {
// Extra memes that start at random positions and move diagonally
var startX = Math.random() > 0.5 ? -100 : 2300;
var diagSpeed = (startX < 1000 ? 1 : -1) * (3 + Math.random() * 5);
meme.reset(startX, 400 + Math.random() * 800, diagSpeed, scale * 0.8, rotSpeed * 2);
// Add diagonal movement
tween(meme, {
y: meme.y + 800 + Math.random() * 600
}, {
duration: 4000 + Math.random() * 2000,
easing: tween.easeInOut,
repeat: -1,
yoyo: true
});
}
obstacles.push(meme);
game.addChild(meme);
// Add different effects to memes based on their position
if (i % 5 === 0) {
// Pulsing effect
tween(meme, {
scaleX: scale * 1.3,
scaleY: scale * 1.3
}, {
duration: 800 + Math.random() * 500,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
} else if (i % 5 === 1) {
// Rotation boost effect
meme.rotationSpeed *= 3;
// Flash effect
tween(meme, {
alpha: 0.6
}, {
duration: 400 + Math.random() * 300,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
} else if (i % 5 === 2) {
// Wobble effect
var wobbleScale = scale * 0.9;
tween(meme, {
scaleX: wobbleScale * 1.4,
scaleY: wobbleScale * 0.8
}, {
duration: 300 + Math.random() * 200,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
}
}
}
function setupPlatformLevel() {
player.isDraggable = false;
player.reset(200, 1000);
// Create platforms
for (var i = 0; i < 8; i++) {
var platform = new Platform();
platform.x = 300 + i * 250;
platform.y = 1300 + Math.random() * 800;
platform.speed = 0;
platform.active = true;
platforms.push(platform);
game.addChild(platform);
}
// Add winning platform
var winPlatform = new Platform();
winPlatform.x = 2000;
winPlatform.y = 1500;
winPlatform.speed = 0;
winPlatform.active = true;
platforms.push(winPlatform);
game.addChild(winPlatform);
// Add floating memes that rise from below
for (var i = 0; i < 4; i++) {
var meme = new Meme();
var scale = 0.6 + Math.random() * 0.8;
var rotSpeed = (Math.random() - 0.5) * 0.05;
meme.reset(300 + Math.random() * 1500, 3000, 0, scale, rotSpeed);
obstacles.push(meme);
game.addChild(meme);
// Make memes rise from below at intervals
LK.setTimeout(function (m) {
return function () {
tween(m, {
y: -200
}, {
duration: 5000 + Math.random() * 3000,
easing: tween.easeIn
});
};
}(meme), 2000 + i * 3000);
}
}
function setupTargetLevel() {
player.isDraggable = true;
player.reset(1024, 1366);
// Create targets and memes
for (var i = 0; i < 5; i++) {
var target = new Target();
target.x = 300 + Math.random() * 1500;
target.y = 400 + Math.random() * 1700;
target.pulse();
targets.push(target);
game.addChild(target);
// Add a meme that circles around each target
var meme = new Meme();
var scale = 0.5 + Math.random() * 0.3;
meme.reset(target.x, target.y - 100, 0, scale, 0.02);
game.addChild(meme);
// Make meme orbit around the target
LK.setInterval(function (t, m) {
return function () {
var radius = 100 + Math.random() * 50;
var angle = Math.random() * Math.PI * 2;
tween(m, {
x: t.x + Math.cos(angle) * radius,
y: t.y + Math.sin(angle) * radius
}, {
duration: 1500,
easing: tween.easeInOut
});
};
}(target, meme), 1600);
}
}
function setupBoundaryLevel() {
player.isDraggable = true;
player.reset(1024, 1366);
// Create moving boundaries
var leftBoundary = LK.getAsset('boundary', {
anchorX: 0.5,
anchorY: 0.5
});
leftBoundary.x = 500;
leftBoundary.y = 1366;
game.addChild(leftBoundary);
var rightBoundary = LK.getAsset('boundary', {
anchorX: 0.5,
anchorY: 0.5
});
rightBoundary.x = 1548;
rightBoundary.y = 1366;
game.addChild(rightBoundary);
// Add floating memes as additional obstacles
for (var i = 0; i < 3; i++) {
var meme = new Meme();
var scale = 0.6 + Math.random() * 0.8;
var rotSpeed = (Math.random() - 0.5) * 0.1;
var posX = 600 + Math.random() * 848;
var posY = 400 + Math.random() * 1700;
meme.reset(posX, posY, 0, scale, rotSpeed);
obstacles.push(meme);
game.addChild(meme);
// Make memes float around
tween(meme, {
x: posX + (Math.random() - 0.5) * 300,
y: posY + (Math.random() - 0.5) * 300
}, {
duration: 2000 + Math.random() * 2000,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
}
// Add movement to boundaries
LK.setInterval(function () {
tween(leftBoundary, {
x: 300 + Math.random() * 400
}, {
duration: 1500,
easing: tween.easeInOut
});
tween(rightBoundary, {
x: 1348 + Math.random() * 400
}, {
duration: 1500,
easing: tween.easeInOut
});
}, 2000);
}
function setupFinalLevel() {
player.isDraggable = true;
player.reset(1024, 1366);
// Mix of obstacles, platforms and targets
// Create memes instead of obstacles
for (var i = 0; i < 8; i++) {
var meme = new Meme();
var scale = 0.8 + Math.random() * 1.5;
var rotSpeed = (Math.random() - 0.5) * 0.1;
var speed = -5 - Math.random() * 7;
// Create memes coming from both directions
if (i % 3 === 0) {
meme.reset(-100, 400 + Math.random() * 1700, Math.abs(speed), scale, rotSpeed);
} else {
meme.reset(2300, 400 + Math.random() * 1700, speed, scale, rotSpeed);
}
obstacles.push(meme);
game.addChild(meme);
// Add effects to memes
if (i % 2 === 0) {
tween(meme, {
scaleX: scale * 1.3,
scaleY: scale * 1.3
}, {
duration: 800 + Math.random() * 500,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
}
}
// Create platforms
for (var i = 0; i < 3; i++) {
var platform = new Platform();
platform.x = 300 + i * 600;
platform.y = 1300 + Math.random() * 800;
platform.speed = -2;
platform.active = true;
platforms.push(platform);
game.addChild(platform);
// Add a meme hovering above each platform
var platformMeme = new Meme();
var pScale = 0.6 + Math.random() * 0.4;
platformMeme.reset(platform.x, platform.y - 150, -2, pScale, 0.02);
obstacles.push(platformMeme);
game.addChild(platformMeme);
}
// Create targets
for (var i = 0; i < 3; i++) {
var target = new Target();
target.x = 300 + Math.random() * 1500;
target.y = 400 + Math.random() * 1700;
target.pulse();
targets.push(target);
game.addChild(target);
// Add a meme that circles around each target
var targetMeme = new Meme();
var tScale = 0.5 + Math.random() * 0.3;
targetMeme.reset(target.x, target.y - 100, 0, tScale, 0.03);
obstacles.push(targetMeme);
game.addChild(targetMeme);
// Make meme orbit around the target
LK.setInterval(function (t, m) {
return function () {
var radius = 120 + Math.random() * 40;
var angle = Math.random() * Math.PI * 2;
tween(m, {
x: t.x + Math.cos(angle) * radius,
y: t.y + Math.sin(angle) * radius
}, {
duration: 1200,
easing: tween.easeInOut
});
};
}(target, targetMeme), 1300);
}
}
function clearLevel() {
// Remove all obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].destroy();
}
obstacles = [];
// Remove all platforms
for (var i = 0; i < platforms.length; i++) {
platforms[i].destroy();
}
platforms = [];
// Remove all targets
for (var i = 0; i < targets.length; i++) {
targets[i].destroy();
}
targets = [];
}
function startGame() {
gameState = "countdown";
titleText.visible = false;
instructionText.visible = false;
countdownText.visible = true;
countdownValue = 3;
countdownText.setText(countdownValue.toString());
LK.getSound('countdown').play();
// Start countdown
var countdownTimer = LK.setInterval(function () {
countdownValue--;
if (countdownValue > 0) {
countdownText.setText(countdownValue.toString());
LK.getSound('countdown').play();
} else {
LK.clearInterval(countdownTimer);
countdownText.visible = false;
gameOverText.visible = false;
// Start actual game
gameState = "playing";
currentLevel = 1;
LK.setScore(0);
scoreText.setText("Score: 0");
initializeLevel(currentLevel);
// Play game music
LK.playMusic('gameMusic');
}
}, 1000);
}
function updateLevel() {
// Update timer
var timeLeft = Math.max(0, Math.floor((levelDuration - (Date.now() - levelStartTime)) / 1000));
timerText.setText(timeLeft.toString());
// Update progress bar
var progress = (Date.now() - levelStartTime) / levelDuration * 100;
progressBar.setProgress(progress);
// Check if level time is up
if (Date.now() - levelStartTime >= levelDuration) {
completeLevel();
}
// Level-specific logic
switch (currentLevel) {
case 1:
// Dodge level
updateDodgeLevel();
break;
case 2:
// Platform level
updatePlatformLevel();
break;
case 3:
// Target level
updateTargetLevel();
break;
case 4:
// Boundary level
updateBoundaryLevel();
break;
case 5:
// Final level
updateFinalLevel();
break;
}
}
function updateDodgeLevel() {
// Check collisions with obstacles
for (var i = 0; i < obstacles.length; i++) {
if (obstacles[i].active && player.intersects(obstacles[i])) {
// Player hit an obstacle
LK.getSound('fail').play();
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver();
return;
}
// Replace obstacles that went off-screen
if (!obstacles[i].active) {
var scale = 0.8 + Math.random() * 1.5;
var rotSpeed = (Math.random() - 0.5) * 0.1;
var speed = -5 - Math.random() * 7;
// Create more diverse meme patterns based on current game time
var pattern = Math.floor((Date.now() - levelStartTime) / 5000) % 4; // Changes pattern every 5 seconds
var patternRandom = (i + LK.ticks) % 5; // Adds more variety within patterns
// Different spawn patterns based on time and position
if (pattern === 0) {
// Classic side-to-side pattern
if (patternRandom < 2) {
obstacles[i].reset(-100, 400 + Math.random() * 1700, Math.abs(speed), scale, rotSpeed);
} else {
obstacles[i].reset(2300, 400 + Math.random() * 1700, speed, scale, rotSpeed);
}
} else if (pattern === 1) {
// Diagonal pattern
var startX = patternRandom < 2 ? -100 : 2300;
var diagSpeed = (startX < 1000 ? 1 : -1) * (3 + Math.random() * 4);
obstacles[i].reset(startX, 400 + Math.random() * 800, diagSpeed, scale * 0.9, rotSpeed * 1.5);
// Add diagonal movement
tween(obstacles[i], {
y: obstacles[i].y + 600 + Math.random() * 500
}, {
duration: 3000 + Math.random() * 2000,
easing: tween.easeInOut,
repeat: -1,
yoyo: true
});
} else if (pattern === 2) {
// Fast spinning memes
if (patternRandom < 3) {
obstacles[i].reset(-100, 600 + Math.random() * 1200, Math.abs(speed) * 1.2, scale * 0.7, rotSpeed * 3);
} else {
obstacles[i].reset(2300, 600 + Math.random() * 1200, speed * 1.2, scale * 0.7, rotSpeed * 3);
}
} else {
// Wave pattern
obstacles[i].reset(patternRandom < 2 ? -100 : 2300, 800 + Math.random() * 900, (patternRandom < 2 ? 1 : -1) * (4 + Math.random() * 3), scale, rotSpeed * 0.5);
// Add wavy motion
tween(obstacles[i], {
y: obstacles[i].y + (Math.random() > 0.5 ? 400 : -400)
}, {
duration: 1500 + Math.random() * 1000,
easing: tween.easeInOut,
repeat: -1,
yoyo: true
});
}
// Add varied visual effects
var effectType = Math.floor(Math.random() * 4);
if (effectType === 0) {
// Pulsing effect
tween(obstacles[i], {
scaleX: scale * 1.3,
scaleY: scale * 1.3
}, {
duration: 800 + Math.random() * 500,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
} else if (effectType === 1) {
// Wobble effect
tween(obstacles[i], {
scaleX: scale * 1.4,
scaleY: scale * 0.8
}, {
duration: 300 + Math.random() * 200,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
} else if (effectType === 2) {
// Flash effect
tween(obstacles[i], {
alpha: 0.6
}, {
duration: 400 + Math.random() * 300,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
}
}
}
// Add score over time
if (LK.ticks % 30 === 0) {
LK.setScore(LK.getScore() + 1);
scoreText.setText("Score: " + LK.getScore());
}
}
function updatePlatformLevel() {
// Apply gravity
player.velocity.y += GRAVITY;
player.y += player.velocity.y;
// Check if player is standing on a platform
var onPlatform = false;
for (var i = 0; i < platforms.length; i++) {
if (player.y + 60 >= platforms[i].y - 20 && player.y + 60 <= platforms[i].y + 20 && player.x >= platforms[i].x - 200 && player.x <= platforms[i].x + 200) {
player.y = platforms[i].y - 60;
player.velocity.y = 0;
player.isJumping = false;
onPlatform = true;
// Check if player reached the end platform
if (i === platforms.length - 1) {
completeLevel();
return;
}
}
}
// Check if player fell off
if (player.y > GROUND_Y) {
LK.getSound('fail').play();
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver();
return;
}
}
function updateTargetLevel() {
// Check collisions with targets
for (var i = targets.length - 1; i >= 0; i--) {
if (targets[i].active && player.intersects(targets[i])) {
// Player hit a target
LK.getSound('success').play();
targets[i].destroy();
targets.splice(i, 1);
// Add score
LK.setScore(LK.getScore() + 10);
scoreText.setText("Score: " + LK.getScore());
// Check if all targets are hit
if (targets.length === 0) {
completeLevel();
return;
}
}
}
}
function updateBoundaryLevel() {
// For this level, we check if player is out of bounds (using the existing child objects)
var children = game.children;
for (var i = 0; i < children.length; i++) {
// Find the boundary objects created in setupBoundaryLevel
if (children[i].width === 150 && children[i].height === 2732) {
if (player.intersects(children[i])) {
LK.getSound('fail').play();
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver();
return;
}
}
}
// Add score over time
if (LK.ticks % 30 === 0) {
LK.setScore(LK.getScore() + 1);
scoreText.setText("Score: " + LK.getScore());
}
}
function updateFinalLevel() {
// Mix of all previous levels' logic
// Check collisions with obstacles
for (var i = 0; i < obstacles.length; i++) {
if (obstacles[i].active && player.intersects(obstacles[i])) {
// Player hit an obstacle
LK.getSound('fail').play();
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver();
return;
}
// Replace obstacles that went off-screen
if (!obstacles[i].active) {
var scale = 0.8 + Math.random() * 1.5;
var rotSpeed = (Math.random() - 0.5) * 0.1;
var speed = -5 - Math.random() * 7;
// Varied meme patterns
if (i % 3 === 0) {
obstacles[i].reset(-100, 400 + Math.random() * 1700, Math.abs(speed), scale, rotSpeed);
} else {
obstacles[i].reset(2300, 400 + Math.random() * 1700, speed, scale, rotSpeed);
}
// Add effects to newly reset memes
if (Math.random() > 0.6) {
tween(obstacles[i], {
scaleX: scale * 1.3,
scaleY: scale * 1.3
}, {
duration: 800 + Math.random() * 500,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
}
}
}
// Check collisions with targets
for (var i = targets.length - 1; i >= 0; i--) {
if (targets[i].active && player.intersects(targets[i])) {
// Player hit a target
LK.getSound('success').play();
targets[i].destroy();
targets.splice(i, 1);
// Add score
LK.setScore(LK.getScore() + 10);
scoreText.setText("Score: " + LK.getScore());
// Spawn a celebratory meme
var celebMeme = new Meme();
var cScale = 0.7 + Math.random() * 0.5;
celebMeme.reset(player.x, player.y - 100, 0, cScale, 0.05);
obstacles.push(celebMeme);
game.addChild(celebMeme);
// Make it float up and fade out
tween(celebMeme, {
y: player.y - 300,
alpha: 0
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
celebMeme.active = false;
}
});
}
}
// Add score over time
if (LK.ticks % 30 === 0) {
LK.setScore(LK.getScore() + 1);
scoreText.setText("Score: " + LK.getScore());
}
// Check if all targets are hit
if (targets.length === 0) {
completeLevel();
return;
}
}
function completeLevel() {
LK.getSound('levelComplete').play();
currentLevel++;
// Check if all levels are complete
if (currentLevel > maxLevels) {
LK.showYouWin();
} else {
// Start next level
initializeLevel(currentLevel);
}
}
// Input handlers
game.down = function (x, y, obj) {
if (gameState === "title") {
startGame();
} else if (gameState === "playing") {
if (currentLevel === 2) {
// Jump for platform level
player.jump();
} else if (draggedObject === null && player.isDraggable) {
// Start dragging player
var localPoint = player.toLocal({
x: x,
y: y
});
if (Math.sqrt(localPoint.x * localPoint.x + localPoint.y * localPoint.y) < 60) {
draggedObject = player;
}
}
}
};
game.up = function (x, y, obj) {
draggedObject = null;
};
game.move = function (x, y, obj) {
if (draggedObject) {
draggedObject.x = x;
draggedObject.y = y;
}
};
// Initialize game
initializeUI();
initializePlayer();
// Game loop
game.update = function () {
if (gameState === "playing") {
updateLevel();
}
};
// Start with title screen
gameState = "title"; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Meme = Container.expand(function () {
var self = Container.call(this);
var memeGraphics = self.attachAsset('Meme', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.active = true;
self.scale = 1;
self.rotation = 0;
self.rotationSpeed = 0;
self.update = function () {
if (self.active) {
self.x += self.speed;
self.rotation += self.rotationSpeed;
// If meme goes off-screen, reset or deactivate
if (self.x < -100 || self.x > 2148) {
self.active = false;
}
}
};
self.reset = function (x, y, speed, scale, rotSpeed) {
self.x = x;
self.y = y;
self.speed = speed;
self.scale = scale || 1;
self.scaleX = self.scale;
self.scaleY = self.scale;
self.rotationSpeed = rotSpeed || 0;
self.active = true;
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.active = true;
self.update = function () {
if (self.active) {
self.x += self.speed;
// If obstacle goes off-screen, reset
if (self.x < -100 || self.x > 2148) {
self.active = false;
}
}
};
self.reset = function (x, y, speed) {
self.x = x;
self.y = y;
self.speed = speed;
self.active = true;
};
return self;
});
var Platform = Container.expand(function () {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.active = true;
self.update = function () {
if (self.active) {
self.x += self.speed;
// If platform goes off-screen, reset
if (self.x < -250 || self.x > 2298) {
self.active = false;
}
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('playerCircle', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocity = {
x: 0,
y: 0
};
self.isJumping = false;
self.isDraggable = false;
self.jump = function () {
if (!self.isJumping) {
self.velocity.y = -20;
self.isJumping = true;
LK.getSound('jump').play();
}
};
self.reset = function (x, y) {
self.x = x;
self.y = y;
self.velocity = {
x: 0,
y: 0
};
self.isJumping = false;
};
self.down = function (x, y, obj) {
if (self.isDraggable) {
draggedObject = self;
}
};
return self;
});
var ProgressBar = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('progressBar', {
anchorX: 0,
anchorY: 0.5
});
var fill = self.attachAsset('progressFill', {
anchorX: 0,
anchorY: 0.5
});
self.setProgress = function (percent) {
fill.width = Math.min(1800 * (percent / 100), 1800);
};
return self;
});
var Target = Container.expand(function () {
var self = Container.call(this);
var targetGraphics = self.attachAsset('target', {
anchorX: 0.5,
anchorY: 0.5
});
self.active = true;
self.pulse = function () {
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeIn
});
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x34495e
});
/****
* Game Code
****/
var GRAVITY = 0.8;
var GROUND_Y = 2400;
var gameState = "title"; // "title", "playing", "gameOver"
var currentLevel = 1;
var maxLevels = 5;
var levelDuration = 20000; // 20 seconds per level
var levelStartTime = 0;
var draggedObject = null;
var player;
var obstacles = [];
var platforms = [];
var targets = [];
var progressBar;
var scoreText;
var levelText;
var timerText;
var titleText;
var instructionText;
var gameOverText;
var countdownText;
var countdownValue = 3;
var levelDescriptions = ["Dodge the memes!", "Cross the platforms!", "Hit the targets!", "Stay in bounds!", "Survive them all!"];
// Initialize game UI
function initializeUI() {
// Progress bar
progressBar = new ProgressBar();
progressBar.x = 124;
progressBar.y = 100;
LK.gui.addChild(progressBar);
// Score
scoreText = new Text2("Score: 0", {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreText);
// Level
levelText = new Text2("Level: 1", {
size: 60,
fill: 0xFFFFFF
});
levelText.anchor.set(0, 0);
levelText.x = 124;
LK.gui.topLeft.addChild(levelText);
levelText.y = 150;
// Timer
timerText = new Text2("20", {
size: 60,
fill: 0xFFFFFF
});
timerText.anchor.set(0.5, 0);
LK.gui.top.addChild(timerText);
// Title
titleText = new Text2("MEME SURVIVAL\nCHALLENGE", {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.visible = true;
LK.gui.center.addChild(titleText);
// Instruction
instructionText = new Text2("Tap to Start", {
size: 60,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.y = 200;
instructionText.visible = true;
LK.gui.center.addChild(instructionText);
// Countdown
countdownText = new Text2("3", {
size: 200,
fill: 0xFFFFFF
});
countdownText.anchor.set(0.5, 0.5);
countdownText.visible = false;
LK.gui.center.addChild(countdownText);
// Level description
gameOverText = new Text2("", {
size: 60,
fill: 0xFFFFFF
});
gameOverText.anchor.set(0.5, 0.5);
gameOverText.y = 300;
gameOverText.visible = false;
LK.gui.center.addChild(gameOverText);
}
// Initialize player
function initializePlayer() {
player = new Player();
player.reset(1024, 1366);
game.addChild(player);
}
// Initialize obstacles based on level
function initializeLevel(level) {
// Clear any existing objects
clearLevel();
// Update UI
levelText.setText("Level: " + level);
gameOverText.setText(levelDescriptions[level - 1]);
gameOverText.visible = true;
// Set timer
levelStartTime = Date.now();
// Configure level
switch (level) {
case 1:
// Dodge memes level
setupDodgeLevel();
break;
case 2:
// Platform level
setupPlatformLevel();
break;
case 3:
// Target level
setupTargetLevel();
break;
case 4:
// Boundary level
setupBoundaryLevel();
break;
case 5:
// Final level - combination
setupFinalLevel();
break;
}
}
function setupDodgeLevel() {
player.isDraggable = true;
player.reset(1024, 1366);
// Create memes instead of obstacles
for (var i = 0; i < 15; i++) {
var meme = new Meme();
var scale = 0.8 + Math.random() * 1.5;
var rotSpeed = (Math.random() - 0.5) * 0.1;
var speed = -5 - Math.random() * 7;
// Alternate memes coming from left and right with varying patterns
if (i % 3 === 0) {
meme.reset(-100, 400 + Math.random() * 1700, Math.abs(speed), scale, rotSpeed);
} else if (i % 3 === 1) {
meme.reset(2300, 400 + Math.random() * 1700, speed, scale, rotSpeed);
} else {
// Extra memes that start at random positions and move diagonally
var startX = Math.random() > 0.5 ? -100 : 2300;
var diagSpeed = (startX < 1000 ? 1 : -1) * (3 + Math.random() * 5);
meme.reset(startX, 400 + Math.random() * 800, diagSpeed, scale * 0.8, rotSpeed * 2);
// Add diagonal movement
tween(meme, {
y: meme.y + 800 + Math.random() * 600
}, {
duration: 4000 + Math.random() * 2000,
easing: tween.easeInOut,
repeat: -1,
yoyo: true
});
}
obstacles.push(meme);
game.addChild(meme);
// Add different effects to memes based on their position
if (i % 5 === 0) {
// Pulsing effect
tween(meme, {
scaleX: scale * 1.3,
scaleY: scale * 1.3
}, {
duration: 800 + Math.random() * 500,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
} else if (i % 5 === 1) {
// Rotation boost effect
meme.rotationSpeed *= 3;
// Flash effect
tween(meme, {
alpha: 0.6
}, {
duration: 400 + Math.random() * 300,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
} else if (i % 5 === 2) {
// Wobble effect
var wobbleScale = scale * 0.9;
tween(meme, {
scaleX: wobbleScale * 1.4,
scaleY: wobbleScale * 0.8
}, {
duration: 300 + Math.random() * 200,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
}
}
}
function setupPlatformLevel() {
player.isDraggable = false;
player.reset(200, 1000);
// Create platforms
for (var i = 0; i < 8; i++) {
var platform = new Platform();
platform.x = 300 + i * 250;
platform.y = 1300 + Math.random() * 800;
platform.speed = 0;
platform.active = true;
platforms.push(platform);
game.addChild(platform);
}
// Add winning platform
var winPlatform = new Platform();
winPlatform.x = 2000;
winPlatform.y = 1500;
winPlatform.speed = 0;
winPlatform.active = true;
platforms.push(winPlatform);
game.addChild(winPlatform);
// Add floating memes that rise from below
for (var i = 0; i < 4; i++) {
var meme = new Meme();
var scale = 0.6 + Math.random() * 0.8;
var rotSpeed = (Math.random() - 0.5) * 0.05;
meme.reset(300 + Math.random() * 1500, 3000, 0, scale, rotSpeed);
obstacles.push(meme);
game.addChild(meme);
// Make memes rise from below at intervals
LK.setTimeout(function (m) {
return function () {
tween(m, {
y: -200
}, {
duration: 5000 + Math.random() * 3000,
easing: tween.easeIn
});
};
}(meme), 2000 + i * 3000);
}
}
function setupTargetLevel() {
player.isDraggable = true;
player.reset(1024, 1366);
// Create targets and memes
for (var i = 0; i < 5; i++) {
var target = new Target();
target.x = 300 + Math.random() * 1500;
target.y = 400 + Math.random() * 1700;
target.pulse();
targets.push(target);
game.addChild(target);
// Add a meme that circles around each target
var meme = new Meme();
var scale = 0.5 + Math.random() * 0.3;
meme.reset(target.x, target.y - 100, 0, scale, 0.02);
game.addChild(meme);
// Make meme orbit around the target
LK.setInterval(function (t, m) {
return function () {
var radius = 100 + Math.random() * 50;
var angle = Math.random() * Math.PI * 2;
tween(m, {
x: t.x + Math.cos(angle) * radius,
y: t.y + Math.sin(angle) * radius
}, {
duration: 1500,
easing: tween.easeInOut
});
};
}(target, meme), 1600);
}
}
function setupBoundaryLevel() {
player.isDraggable = true;
player.reset(1024, 1366);
// Create moving boundaries
var leftBoundary = LK.getAsset('boundary', {
anchorX: 0.5,
anchorY: 0.5
});
leftBoundary.x = 500;
leftBoundary.y = 1366;
game.addChild(leftBoundary);
var rightBoundary = LK.getAsset('boundary', {
anchorX: 0.5,
anchorY: 0.5
});
rightBoundary.x = 1548;
rightBoundary.y = 1366;
game.addChild(rightBoundary);
// Add floating memes as additional obstacles
for (var i = 0; i < 3; i++) {
var meme = new Meme();
var scale = 0.6 + Math.random() * 0.8;
var rotSpeed = (Math.random() - 0.5) * 0.1;
var posX = 600 + Math.random() * 848;
var posY = 400 + Math.random() * 1700;
meme.reset(posX, posY, 0, scale, rotSpeed);
obstacles.push(meme);
game.addChild(meme);
// Make memes float around
tween(meme, {
x: posX + (Math.random() - 0.5) * 300,
y: posY + (Math.random() - 0.5) * 300
}, {
duration: 2000 + Math.random() * 2000,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
}
// Add movement to boundaries
LK.setInterval(function () {
tween(leftBoundary, {
x: 300 + Math.random() * 400
}, {
duration: 1500,
easing: tween.easeInOut
});
tween(rightBoundary, {
x: 1348 + Math.random() * 400
}, {
duration: 1500,
easing: tween.easeInOut
});
}, 2000);
}
function setupFinalLevel() {
player.isDraggable = true;
player.reset(1024, 1366);
// Mix of obstacles, platforms and targets
// Create memes instead of obstacles
for (var i = 0; i < 8; i++) {
var meme = new Meme();
var scale = 0.8 + Math.random() * 1.5;
var rotSpeed = (Math.random() - 0.5) * 0.1;
var speed = -5 - Math.random() * 7;
// Create memes coming from both directions
if (i % 3 === 0) {
meme.reset(-100, 400 + Math.random() * 1700, Math.abs(speed), scale, rotSpeed);
} else {
meme.reset(2300, 400 + Math.random() * 1700, speed, scale, rotSpeed);
}
obstacles.push(meme);
game.addChild(meme);
// Add effects to memes
if (i % 2 === 0) {
tween(meme, {
scaleX: scale * 1.3,
scaleY: scale * 1.3
}, {
duration: 800 + Math.random() * 500,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
}
}
// Create platforms
for (var i = 0; i < 3; i++) {
var platform = new Platform();
platform.x = 300 + i * 600;
platform.y = 1300 + Math.random() * 800;
platform.speed = -2;
platform.active = true;
platforms.push(platform);
game.addChild(platform);
// Add a meme hovering above each platform
var platformMeme = new Meme();
var pScale = 0.6 + Math.random() * 0.4;
platformMeme.reset(platform.x, platform.y - 150, -2, pScale, 0.02);
obstacles.push(platformMeme);
game.addChild(platformMeme);
}
// Create targets
for (var i = 0; i < 3; i++) {
var target = new Target();
target.x = 300 + Math.random() * 1500;
target.y = 400 + Math.random() * 1700;
target.pulse();
targets.push(target);
game.addChild(target);
// Add a meme that circles around each target
var targetMeme = new Meme();
var tScale = 0.5 + Math.random() * 0.3;
targetMeme.reset(target.x, target.y - 100, 0, tScale, 0.03);
obstacles.push(targetMeme);
game.addChild(targetMeme);
// Make meme orbit around the target
LK.setInterval(function (t, m) {
return function () {
var radius = 120 + Math.random() * 40;
var angle = Math.random() * Math.PI * 2;
tween(m, {
x: t.x + Math.cos(angle) * radius,
y: t.y + Math.sin(angle) * radius
}, {
duration: 1200,
easing: tween.easeInOut
});
};
}(target, targetMeme), 1300);
}
}
function clearLevel() {
// Remove all obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].destroy();
}
obstacles = [];
// Remove all platforms
for (var i = 0; i < platforms.length; i++) {
platforms[i].destroy();
}
platforms = [];
// Remove all targets
for (var i = 0; i < targets.length; i++) {
targets[i].destroy();
}
targets = [];
}
function startGame() {
gameState = "countdown";
titleText.visible = false;
instructionText.visible = false;
countdownText.visible = true;
countdownValue = 3;
countdownText.setText(countdownValue.toString());
LK.getSound('countdown').play();
// Start countdown
var countdownTimer = LK.setInterval(function () {
countdownValue--;
if (countdownValue > 0) {
countdownText.setText(countdownValue.toString());
LK.getSound('countdown').play();
} else {
LK.clearInterval(countdownTimer);
countdownText.visible = false;
gameOverText.visible = false;
// Start actual game
gameState = "playing";
currentLevel = 1;
LK.setScore(0);
scoreText.setText("Score: 0");
initializeLevel(currentLevel);
// Play game music
LK.playMusic('gameMusic');
}
}, 1000);
}
function updateLevel() {
// Update timer
var timeLeft = Math.max(0, Math.floor((levelDuration - (Date.now() - levelStartTime)) / 1000));
timerText.setText(timeLeft.toString());
// Update progress bar
var progress = (Date.now() - levelStartTime) / levelDuration * 100;
progressBar.setProgress(progress);
// Check if level time is up
if (Date.now() - levelStartTime >= levelDuration) {
completeLevel();
}
// Level-specific logic
switch (currentLevel) {
case 1:
// Dodge level
updateDodgeLevel();
break;
case 2:
// Platform level
updatePlatformLevel();
break;
case 3:
// Target level
updateTargetLevel();
break;
case 4:
// Boundary level
updateBoundaryLevel();
break;
case 5:
// Final level
updateFinalLevel();
break;
}
}
function updateDodgeLevel() {
// Check collisions with obstacles
for (var i = 0; i < obstacles.length; i++) {
if (obstacles[i].active && player.intersects(obstacles[i])) {
// Player hit an obstacle
LK.getSound('fail').play();
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver();
return;
}
// Replace obstacles that went off-screen
if (!obstacles[i].active) {
var scale = 0.8 + Math.random() * 1.5;
var rotSpeed = (Math.random() - 0.5) * 0.1;
var speed = -5 - Math.random() * 7;
// Create more diverse meme patterns based on current game time
var pattern = Math.floor((Date.now() - levelStartTime) / 5000) % 4; // Changes pattern every 5 seconds
var patternRandom = (i + LK.ticks) % 5; // Adds more variety within patterns
// Different spawn patterns based on time and position
if (pattern === 0) {
// Classic side-to-side pattern
if (patternRandom < 2) {
obstacles[i].reset(-100, 400 + Math.random() * 1700, Math.abs(speed), scale, rotSpeed);
} else {
obstacles[i].reset(2300, 400 + Math.random() * 1700, speed, scale, rotSpeed);
}
} else if (pattern === 1) {
// Diagonal pattern
var startX = patternRandom < 2 ? -100 : 2300;
var diagSpeed = (startX < 1000 ? 1 : -1) * (3 + Math.random() * 4);
obstacles[i].reset(startX, 400 + Math.random() * 800, diagSpeed, scale * 0.9, rotSpeed * 1.5);
// Add diagonal movement
tween(obstacles[i], {
y: obstacles[i].y + 600 + Math.random() * 500
}, {
duration: 3000 + Math.random() * 2000,
easing: tween.easeInOut,
repeat: -1,
yoyo: true
});
} else if (pattern === 2) {
// Fast spinning memes
if (patternRandom < 3) {
obstacles[i].reset(-100, 600 + Math.random() * 1200, Math.abs(speed) * 1.2, scale * 0.7, rotSpeed * 3);
} else {
obstacles[i].reset(2300, 600 + Math.random() * 1200, speed * 1.2, scale * 0.7, rotSpeed * 3);
}
} else {
// Wave pattern
obstacles[i].reset(patternRandom < 2 ? -100 : 2300, 800 + Math.random() * 900, (patternRandom < 2 ? 1 : -1) * (4 + Math.random() * 3), scale, rotSpeed * 0.5);
// Add wavy motion
tween(obstacles[i], {
y: obstacles[i].y + (Math.random() > 0.5 ? 400 : -400)
}, {
duration: 1500 + Math.random() * 1000,
easing: tween.easeInOut,
repeat: -1,
yoyo: true
});
}
// Add varied visual effects
var effectType = Math.floor(Math.random() * 4);
if (effectType === 0) {
// Pulsing effect
tween(obstacles[i], {
scaleX: scale * 1.3,
scaleY: scale * 1.3
}, {
duration: 800 + Math.random() * 500,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
} else if (effectType === 1) {
// Wobble effect
tween(obstacles[i], {
scaleX: scale * 1.4,
scaleY: scale * 0.8
}, {
duration: 300 + Math.random() * 200,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
} else if (effectType === 2) {
// Flash effect
tween(obstacles[i], {
alpha: 0.6
}, {
duration: 400 + Math.random() * 300,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
}
}
}
// Add score over time
if (LK.ticks % 30 === 0) {
LK.setScore(LK.getScore() + 1);
scoreText.setText("Score: " + LK.getScore());
}
}
function updatePlatformLevel() {
// Apply gravity
player.velocity.y += GRAVITY;
player.y += player.velocity.y;
// Check if player is standing on a platform
var onPlatform = false;
for (var i = 0; i < platforms.length; i++) {
if (player.y + 60 >= platforms[i].y - 20 && player.y + 60 <= platforms[i].y + 20 && player.x >= platforms[i].x - 200 && player.x <= platforms[i].x + 200) {
player.y = platforms[i].y - 60;
player.velocity.y = 0;
player.isJumping = false;
onPlatform = true;
// Check if player reached the end platform
if (i === platforms.length - 1) {
completeLevel();
return;
}
}
}
// Check if player fell off
if (player.y > GROUND_Y) {
LK.getSound('fail').play();
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver();
return;
}
}
function updateTargetLevel() {
// Check collisions with targets
for (var i = targets.length - 1; i >= 0; i--) {
if (targets[i].active && player.intersects(targets[i])) {
// Player hit a target
LK.getSound('success').play();
targets[i].destroy();
targets.splice(i, 1);
// Add score
LK.setScore(LK.getScore() + 10);
scoreText.setText("Score: " + LK.getScore());
// Check if all targets are hit
if (targets.length === 0) {
completeLevel();
return;
}
}
}
}
function updateBoundaryLevel() {
// For this level, we check if player is out of bounds (using the existing child objects)
var children = game.children;
for (var i = 0; i < children.length; i++) {
// Find the boundary objects created in setupBoundaryLevel
if (children[i].width === 150 && children[i].height === 2732) {
if (player.intersects(children[i])) {
LK.getSound('fail').play();
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver();
return;
}
}
}
// Add score over time
if (LK.ticks % 30 === 0) {
LK.setScore(LK.getScore() + 1);
scoreText.setText("Score: " + LK.getScore());
}
}
function updateFinalLevel() {
// Mix of all previous levels' logic
// Check collisions with obstacles
for (var i = 0; i < obstacles.length; i++) {
if (obstacles[i].active && player.intersects(obstacles[i])) {
// Player hit an obstacle
LK.getSound('fail').play();
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver();
return;
}
// Replace obstacles that went off-screen
if (!obstacles[i].active) {
var scale = 0.8 + Math.random() * 1.5;
var rotSpeed = (Math.random() - 0.5) * 0.1;
var speed = -5 - Math.random() * 7;
// Varied meme patterns
if (i % 3 === 0) {
obstacles[i].reset(-100, 400 + Math.random() * 1700, Math.abs(speed), scale, rotSpeed);
} else {
obstacles[i].reset(2300, 400 + Math.random() * 1700, speed, scale, rotSpeed);
}
// Add effects to newly reset memes
if (Math.random() > 0.6) {
tween(obstacles[i], {
scaleX: scale * 1.3,
scaleY: scale * 1.3
}, {
duration: 800 + Math.random() * 500,
easing: tween.easeInOut,
yoyo: true,
repeat: -1
});
}
}
}
// Check collisions with targets
for (var i = targets.length - 1; i >= 0; i--) {
if (targets[i].active && player.intersects(targets[i])) {
// Player hit a target
LK.getSound('success').play();
targets[i].destroy();
targets.splice(i, 1);
// Add score
LK.setScore(LK.getScore() + 10);
scoreText.setText("Score: " + LK.getScore());
// Spawn a celebratory meme
var celebMeme = new Meme();
var cScale = 0.7 + Math.random() * 0.5;
celebMeme.reset(player.x, player.y - 100, 0, cScale, 0.05);
obstacles.push(celebMeme);
game.addChild(celebMeme);
// Make it float up and fade out
tween(celebMeme, {
y: player.y - 300,
alpha: 0
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
celebMeme.active = false;
}
});
}
}
// Add score over time
if (LK.ticks % 30 === 0) {
LK.setScore(LK.getScore() + 1);
scoreText.setText("Score: " + LK.getScore());
}
// Check if all targets are hit
if (targets.length === 0) {
completeLevel();
return;
}
}
function completeLevel() {
LK.getSound('levelComplete').play();
currentLevel++;
// Check if all levels are complete
if (currentLevel > maxLevels) {
LK.showYouWin();
} else {
// Start next level
initializeLevel(currentLevel);
}
}
// Input handlers
game.down = function (x, y, obj) {
if (gameState === "title") {
startGame();
} else if (gameState === "playing") {
if (currentLevel === 2) {
// Jump for platform level
player.jump();
} else if (draggedObject === null && player.isDraggable) {
// Start dragging player
var localPoint = player.toLocal({
x: x,
y: y
});
if (Math.sqrt(localPoint.x * localPoint.x + localPoint.y * localPoint.y) < 60) {
draggedObject = player;
}
}
}
};
game.up = function (x, y, obj) {
draggedObject = null;
};
game.move = function (x, y, obj) {
if (draggedObject) {
draggedObject.x = x;
draggedObject.y = y;
}
};
// Initialize game
initializeUI();
initializePlayer();
// Game loop
game.update = function () {
if (gameState === "playing") {
updateLevel();
}
};
// Start with title screen
gameState = "title";