/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ // LightOrb (Player) class var LightOrb = Container.expand(function () { var self = Container.call(this); var orb = self.attachAsset('lightOrb', { anchorX: 0.5, anchorY: 0.5 }); // For touch feedback self.flash = function () { tween(orb, { alpha: 0.6 }, { duration: 80, onFinish: function onFinish() { tween(orb, { alpha: 1 }, { duration: 120 }); } }); }; // No update needed; position is set by player return self; }); // PowerUp (Special Ability) class var PowerUp = Container.expand(function () { var self = Container.call(this); // Types: 'slow', 'shield', 'score' self.type = 'slow'; // Visuals: color by type var color = 0x00eaff; if (self.type === 'shield') color = 0x7fff00; if (self.type === 'score') color = 0xffd700; var asset = self.attachAsset('lightOrb', { anchorX: 0.5, anchorY: 0.5 }); asset.width = 90; asset.height = 90; asset.tint = color; // For state tracking self.lastIntersecting = false; // No update needed; position is static return self; }); // Shadow (Enemy) class var Shadow = Container.expand(function () { var self = Container.call(this); var shadow = self.attachAsset('shadow', { anchorX: 0.5, anchorY: 0.5 }); // Movement properties self.vx = 0; self.vy = 0; self.speed = 2; // Will be set on spawn // Shadow type: 'normal' or 'splitter' self.shadowType = 'normal'; // default // For state tracking self.lastIntersecting = false; // Called every tick self.update = function () { self.x += self.vx * self.speed; self.y += self.vy * self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181c24 }); /**** * Game Code ****/ // Game area // Light orb (player) // Shadow (enemy) // Score text will use Text2, no asset needed var GAME_W = 2048; var GAME_H = 2732; // Player (light orb) var lightOrb = new LightOrb(); lightOrb.x = GAME_W / 2; lightOrb.y = GAME_H * 0.75; game.addChild(lightOrb); // Shadows (enemies) var shadows = []; // PowerUps (special abilities) var powerUps = []; // PowerUp state var powerUpActive = false; var powerUpType = null; var powerUpTimer = 0; // Score var score = 0; var highScore = storage.highScore || 0; var scoreTxt = new Text2('0', { size: 120, fill: 0xFFFBE0 }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // High score text var highScoreTxt = new Text2('En Yüksek Skor: 0', { size: 54, fill: 0xFFFFFF }); // Place at bottom right, anchor to right edge highScoreTxt.anchor.set(1, 1); highScoreTxt.x = -40; // 40px from right edge highScoreTxt.y = -40; // 40px from bottom edge LK.gui.bottomRight.addChild(highScoreTxt); // Level system var level = 1; var levelTxt = new Text2('Seviye 1', { size: 80, fill: 0x7fff00 }); levelTxt.anchor.set(0.5, 0); levelTxt.y = 120; LK.gui.top.addChild(levelTxt); // Survival time var survivalTime = 0; // in seconds var survivalTick = 0; // for counting frames var timeTxt = new Text2('Süre: 0', { size: 80, fill: 0x00eaff }); timeTxt.anchor.set(0.5, 0); timeTxt.y = 220; LK.gui.top.addChild(timeTxt); // High survival time (persistent) var highSurvivalTime = storage.highSurvivalTime || 0; var highTimeTxt = new Text2('En Yüksek Süre: 0', { size: 54, fill: 0x00eaff }); highTimeTxt.anchor.set(1, 1); highTimeTxt.x = -40; highTimeTxt.y = -140; // stack above highScoreTxt LK.gui.bottomRight.addChild(highTimeTxt); // Level up logic var nextLevelScore = 15; // First level up at 15, then increases function checkLevelUp() { if (score >= nextLevelScore) { level++; levelTxt.setText('Seviye ' + level); // Animate level text: scale up and back for feedback tween(levelTxt, { scaleX: 1.4, scaleY: 1.4 }, { duration: 180, onFinish: function onFinish() { tween(levelTxt, { scaleX: 1, scaleY: 1 }, { duration: 180 }); } }); // Increase next level threshold (progressively harder) nextLevelScore += 18 + Math.floor(level * 2.5); // Require more points for next level // Level up feedback LK.effects.flashScreen(0x7fff00, 600); // Optionally: boost difficulty a bit more on level up increaseDifficulty(); } } // Difficulty var shadowSpeed = 1.3; // Lower base speed var shadowSpawnInterval = 180; // Slower spawn rate var minShadowSpawnInterval = 60; // Don't get too fast var shadowCount = 1; // Fewer shadows at start var maxShadowCount = 5; // Lower max shadow count // Dragging var dragging = false; // Helper: clamp position inside game area function clamp(val, min, max) { return Math.max(min, Math.min(max, val)); } // Helper: spawn a shadow at a random edge, moving in a random direction function spawnShadow() { var s = new Shadow(); // Random edge: 0=top, 1=bottom, 2=left, 3=right var edge = Math.floor(Math.random() * 4); var margin = 120; var x, y, angle; if (edge === 0) { // top x = margin + Math.random() * (GAME_W - 2 * margin); y = -90; angle = Math.PI / 4 + Math.random() * (Math.PI / 2); // 45-135 deg } else if (edge === 1) { // bottom x = margin + Math.random() * (GAME_W - 2 * margin); y = GAME_H + 90; angle = -Math.PI / 4 - Math.random() * (Math.PI / 2); // -45 to -135 deg } else if (edge === 2) { // left x = -90; y = margin + Math.random() * (GAME_H - 2 * margin); angle = -Math.PI / 4 + Math.random() * (Math.PI / 2); // -45 to 45 deg } else { // right x = GAME_W + 90; y = margin + Math.random() * (GAME_H - 2 * margin); angle = Math.PI * (1.25 + Math.random() * 0.5); // 225-315 deg } s.x = x; s.y = y; s.speed = shadowSpeed + Math.random() * 0.7; s.vx = Math.cos(angle); s.vy = Math.sin(angle); // Randomly assign splitter type (10% chance, but not if too many shadows) if (Math.random() < 0.10 && shadows.length < 6 && level > 1) { s.shadowType = 'splitter'; // Tint splitter shadow for visibility if (s.children && s.children[0]) { s.children[0].tint = 0x4e7fff; } } // Add to game and array game.addChild(s); shadows.push(s); } // Score update function updateScore(val) { score = val; scoreTxt.setText(score); if (score > highScore) { highScore = score; highScoreTxt.setText('En Yüksek Skor: ' + highScore); storage.highScore = highScore; } } // Difficulty ramp function increaseDifficulty() { if (shadowSpawnInterval > minShadowSpawnInterval) { shadowSpawnInterval -= 3; // Decrease spawn interval more slowly } if (shadowCount < maxShadowCount) { shadowCount += 1; } shadowSpeed += 0.09; // Increase speed more slowly } // Move handler (drag orb) function handleMove(x, y, obj) { if (dragging) { // Clamp to game area, avoid top left 100x100 var nx = clamp(x, 100 + lightOrb.width / 2, GAME_W - lightOrb.width / 2); var ny = clamp(y, lightOrb.height / 2, GAME_H - lightOrb.height / 2); lightOrb.x = nx; lightOrb.y = ny; } } game.move = handleMove; // Down handler (start drag) game.down = function (x, y, obj) { // Only start drag if touch is on orb var dx = x - lightOrb.x; var dy = y - lightOrb.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < lightOrb.width / 2 + 30) { dragging = true; lightOrb.flash(); handleMove(x, y, obj); } }; // Up handler (stop drag) game.up = function (x, y, obj) { dragging = false; }; // Shadow spawn timer var shadowTick = 0; // Main update loop game.update = function () { // Update survival time survivalTick++; if (survivalTick >= 60) { // update every 1s (60fps) survivalTime += 1; timeTxt.setText('Süre: ' + survivalTime); survivalTick = 0; // Pulse background color every 10 seconds survived if (survivalTime > 0 && survivalTime % 10 === 0) { var baseColor = 0x181c24; var pulseColor = 0x232a3a; game.setBackgroundColor(pulseColor); LK.setTimeout(function () { game.setBackgroundColor(baseColor); }, 400); } } // Spawn shadows shadowTick++; if (shadowTick >= shadowSpawnInterval) { shadowTick = 0; for (var i = 0; i < shadowCount; i++) { spawnShadow(); } } // PowerUp spawn: every 6-10 seconds, if none active or on field if (!powerUpActive && powerUps.length === 0 && Math.random() < 0.012) { var p = new PowerUp(); // Random type, now includes 'shrink' and 'repel' var types = ['slow', 'shield', 'score', 'shrink', 'repel']; p.type = types[Math.floor(Math.random() * types.length)]; // Color by type var color = 0x00eaff; if (p.type === 'shield') color = 0x7fff00; if (p.type === 'score') color = 0xffd700; if (p.type === 'shrink') color = 0xff66cc; if (p.type === 'repel') color = 0xff4400; p.children[0].tint = color; // Place randomly, not too close to edges or player var safe = false, px, py, tries = 0; while (!safe && tries < 20) { px = 200 + Math.random() * (GAME_W - 400); py = 200 + Math.random() * (GAME_H - 400); var dx = px - lightOrb.x, dy = py - lightOrb.y; if (Math.sqrt(dx * dx + dy * dy) > 300) safe = true; tries++; } p.x = px; p.y = py; game.addChild(p); powerUps.push(p); } // Update shadows for (var i = shadows.length - 1; i >= 0; i--) { var s = shadows[i]; s.update(); // Out of bounds: if shadow is far outside, remove and score if (s.x < -300 || s.x > GAME_W + 300 || s.y < -300 || s.y > GAME_H + 300) { // If this is a splitter shadow, split it before removing if (s.shadowType === 'splitter' && !s._hasSplit) { // Split into two smaller shadows for (var splitIdx = 0; splitIdx < 2; splitIdx++) { var newS = new Shadow(); newS.x = s.x; newS.y = s.y; // Give a random direction var angle = Math.random() * Math.PI * 2; newS.vx = Math.cos(angle); newS.vy = Math.sin(angle); newS.speed = shadowSpeed + 1.2 + Math.random() * 0.7; newS.width = s.width * 0.7; newS.height = s.height * 0.7; newS.shadowType = 'normal'; game.addChild(newS); shadows.push(newS); } s._hasSplit = true; } s.destroy(); shadows.splice(i, 1); // Score for successful dodge updateScore(score + 2); // Give 2 points per dodge checkLevelUp(); // Every 5 points, ramp up difficulty if (score > 0 && score % 5 === 0) { increaseDifficulty(); } continue; } // Collision with player var intersecting = s.intersects(lightOrb); // If invincible, flash orb and skip collision if (lightOrb._invincible && lightOrb._invincible > 0) { if (lightOrb._invincible % 8 === 0) { LK.effects.flashObject(lightOrb, 0xffffff, 120); } lightOrb._invincible--; s.lastIntersecting = intersecting; continue; } if (!s.lastIntersecting && intersecting) { // If shield powerup is active, destroy shadow and continue if (powerUpActive && powerUpType === 'shield') { // If this is a splitter shadow, split it before removing if (s.shadowType === 'splitter' && !s._hasSplit) { for (var splitIdx = 0; splitIdx < 2; splitIdx++) { var newS = new Shadow(); newS.x = s.x; newS.y = s.y; var angle = Math.random() * Math.PI * 2; newS.vx = Math.cos(angle); newS.vy = Math.sin(angle); newS.speed = shadowSpeed + 1.2 + Math.random() * 0.7; newS.width = s.width * 0.7; newS.height = s.height * 0.7; newS.shadowType = 'normal'; game.addChild(newS); shadows.push(newS); } s._hasSplit = true; } s.destroy(); shadows.splice(i, 1); continue; } // Flash screen, game over LK.effects.flashScreen(0xff2222, 900); // Update high survival time if needed if (survivalTime > highSurvivalTime) { highSurvivalTime = survivalTime; highTimeTxt.setText('En Yüksek Süre: ' + highSurvivalTime); storage.highSurvivalTime = highSurvivalTime; } LK.showGameOver(); return; } s.lastIntersecting = intersecting; } // PowerUp collection and effect for (var i = powerUps.length - 1; i >= 0; i--) { var p = powerUps[i]; var intersecting = p.intersects(lightOrb); if (!p.lastIntersecting && intersecting) { // Activate effect powerUpActive = true; powerUpType = p.type; powerUpTimer = 0; // Add invincibility for 0.7s after collecting any powerup lightOrb._invincible = 42; // 0.7s at 60fps // Visual feedback LK.effects.flashObject(lightOrb, p.children[0].tint, 600); // Repel: extra visual feedback if (p.type === 'repel') { LK.effects.flashScreen(0xff4400, 400); } // Score boost: instant if (p.type === 'score') { updateScore(score + 10); checkLevelUp(); powerUpActive = false; powerUpType = null; } // Shrink: shrink orb for 4 seconds if (p.type === 'shrink') { // Store original size if (!lightOrb._origW) { lightOrb._origW = lightOrb.width; lightOrb._origH = lightOrb.height; } lightOrb.width = lightOrb._origW * 0.55; lightOrb.height = lightOrb._origH * 0.55; } // Repel: instantly push all shadows away from player if (p.type === 'repel') { for (var j = 0; j < shadows.length; j++) { var s = shadows[j]; var dx = s.x - lightOrb.x; var dy = s.y - lightOrb.y; var dist = Math.sqrt(dx * dx + dy * dy) || 1; // Set direction away from orb, keep speed s.vx = dx / dist; s.vy = dy / dist; // Give a burst of speed s.speed = Math.max(shadowSpeed + 2.5, 4.5); } powerUpActive = false; powerUpType = null; } // Remove powerup from field p.destroy(); powerUps.splice(i, 1); continue; } p.lastIntersecting = intersecting; } // PowerUp timer/effect duration if (powerUpActive) { powerUpTimer++; // Shadow slow: 4 seconds if (powerUpType === 'slow') { // Visual feedback: pulse effect while slow is active if (powerUpTimer % 30 === 0) { LK.effects.flashObject(lightOrb, 0x00eaff, 200); } // Slow down all shadows for (var j = 0; j < shadows.length; j++) { shadows[j].speed = 0.7; } shadowSpeed = 0.7; if (powerUpTimer > 240) { powerUpActive = false; powerUpType = null; shadowSpeed = 2.2 + Math.floor(score / 5) * 0.18; // Restore all shadows to normal speed for (var j = 0; j < shadows.length; j++) { shadows[j].speed = shadowSpeed + Math.random() * 0.7; } } } // Shield: 4 seconds if (powerUpType === 'shield') { // Visual feedback: pulse effect while shield is active if (powerUpTimer % 30 === 0) { LK.effects.flashObject(lightOrb, 0x7fff00, 200); } if (powerUpTimer > 240) { powerUpActive = false; powerUpType = null; } } // Shrink: 4 seconds if (powerUpType === 'shrink') { // Visual feedback: pulse effect while shrink is active if (powerUpTimer % 30 === 0) { LK.effects.flashObject(lightOrb, 0xff66cc, 200); } if (powerUpTimer > 240) { powerUpActive = false; powerUpType = null; // Restore orb size if (lightOrb._origW) { lightOrb.width = lightOrb._origW; lightOrb.height = lightOrb._origH; } } } } else { // Reset shadowSpeed if not under slow powerup shadowSpeed = 2.2 + Math.floor(score / 5) * 0.18; for (var j = 0; j < shadows.length; j++) { shadows[j].speed = shadowSpeed + Math.random() * 0.7; } } }; // Initial score updateScore(0); level = 1; levelTxt.setText('Seviye 1'); nextLevelScore = 15; // Do not reset high score display or value on game start highScoreTxt.setText('En Yüksek Skor: ' + highScore); // Reset survival time survivalTime = 0; survivalTick = 0; timeTxt.setText('Süre: 0'); // Show high survival time at game start highTimeTxt.setText('En Yüksek Süre: ' + highSurvivalTime); ; ;
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// LightOrb (Player) class
var LightOrb = Container.expand(function () {
var self = Container.call(this);
var orb = self.attachAsset('lightOrb', {
anchorX: 0.5,
anchorY: 0.5
});
// For touch feedback
self.flash = function () {
tween(orb, {
alpha: 0.6
}, {
duration: 80,
onFinish: function onFinish() {
tween(orb, {
alpha: 1
}, {
duration: 120
});
}
});
};
// No update needed; position is set by player
return self;
});
// PowerUp (Special Ability) class
var PowerUp = Container.expand(function () {
var self = Container.call(this);
// Types: 'slow', 'shield', 'score'
self.type = 'slow';
// Visuals: color by type
var color = 0x00eaff;
if (self.type === 'shield') color = 0x7fff00;
if (self.type === 'score') color = 0xffd700;
var asset = self.attachAsset('lightOrb', {
anchorX: 0.5,
anchorY: 0.5
});
asset.width = 90;
asset.height = 90;
asset.tint = color;
// For state tracking
self.lastIntersecting = false;
// No update needed; position is static
return self;
});
// Shadow (Enemy) class
var Shadow = Container.expand(function () {
var self = Container.call(this);
var shadow = self.attachAsset('shadow', {
anchorX: 0.5,
anchorY: 0.5
});
// Movement properties
self.vx = 0;
self.vy = 0;
self.speed = 2; // Will be set on spawn
// Shadow type: 'normal' or 'splitter'
self.shadowType = 'normal'; // default
// For state tracking
self.lastIntersecting = false;
// Called every tick
self.update = function () {
self.x += self.vx * self.speed;
self.y += self.vy * self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181c24
});
/****
* Game Code
****/
// Game area
// Light orb (player)
// Shadow (enemy)
// Score text will use Text2, no asset needed
var GAME_W = 2048;
var GAME_H = 2732;
// Player (light orb)
var lightOrb = new LightOrb();
lightOrb.x = GAME_W / 2;
lightOrb.y = GAME_H * 0.75;
game.addChild(lightOrb);
// Shadows (enemies)
var shadows = [];
// PowerUps (special abilities)
var powerUps = [];
// PowerUp state
var powerUpActive = false;
var powerUpType = null;
var powerUpTimer = 0;
// Score
var score = 0;
var highScore = storage.highScore || 0;
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFBE0
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// High score text
var highScoreTxt = new Text2('En Yüksek Skor: 0', {
size: 54,
fill: 0xFFFFFF
});
// Place at bottom right, anchor to right edge
highScoreTxt.anchor.set(1, 1);
highScoreTxt.x = -40; // 40px from right edge
highScoreTxt.y = -40; // 40px from bottom edge
LK.gui.bottomRight.addChild(highScoreTxt);
// Level system
var level = 1;
var levelTxt = new Text2('Seviye 1', {
size: 80,
fill: 0x7fff00
});
levelTxt.anchor.set(0.5, 0);
levelTxt.y = 120;
LK.gui.top.addChild(levelTxt);
// Survival time
var survivalTime = 0; // in seconds
var survivalTick = 0; // for counting frames
var timeTxt = new Text2('Süre: 0', {
size: 80,
fill: 0x00eaff
});
timeTxt.anchor.set(0.5, 0);
timeTxt.y = 220;
LK.gui.top.addChild(timeTxt);
// High survival time (persistent)
var highSurvivalTime = storage.highSurvivalTime || 0;
var highTimeTxt = new Text2('En Yüksek Süre: 0', {
size: 54,
fill: 0x00eaff
});
highTimeTxt.anchor.set(1, 1);
highTimeTxt.x = -40;
highTimeTxt.y = -140; // stack above highScoreTxt
LK.gui.bottomRight.addChild(highTimeTxt);
// Level up logic
var nextLevelScore = 15; // First level up at 15, then increases
function checkLevelUp() {
if (score >= nextLevelScore) {
level++;
levelTxt.setText('Seviye ' + level);
// Animate level text: scale up and back for feedback
tween(levelTxt, {
scaleX: 1.4,
scaleY: 1.4
}, {
duration: 180,
onFinish: function onFinish() {
tween(levelTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 180
});
}
});
// Increase next level threshold (progressively harder)
nextLevelScore += 18 + Math.floor(level * 2.5); // Require more points for next level
// Level up feedback
LK.effects.flashScreen(0x7fff00, 600);
// Optionally: boost difficulty a bit more on level up
increaseDifficulty();
}
}
// Difficulty
var shadowSpeed = 1.3; // Lower base speed
var shadowSpawnInterval = 180; // Slower spawn rate
var minShadowSpawnInterval = 60; // Don't get too fast
var shadowCount = 1; // Fewer shadows at start
var maxShadowCount = 5; // Lower max shadow count
// Dragging
var dragging = false;
// Helper: clamp position inside game area
function clamp(val, min, max) {
return Math.max(min, Math.min(max, val));
}
// Helper: spawn a shadow at a random edge, moving in a random direction
function spawnShadow() {
var s = new Shadow();
// Random edge: 0=top, 1=bottom, 2=left, 3=right
var edge = Math.floor(Math.random() * 4);
var margin = 120;
var x, y, angle;
if (edge === 0) {
// top
x = margin + Math.random() * (GAME_W - 2 * margin);
y = -90;
angle = Math.PI / 4 + Math.random() * (Math.PI / 2); // 45-135 deg
} else if (edge === 1) {
// bottom
x = margin + Math.random() * (GAME_W - 2 * margin);
y = GAME_H + 90;
angle = -Math.PI / 4 - Math.random() * (Math.PI / 2); // -45 to -135 deg
} else if (edge === 2) {
// left
x = -90;
y = margin + Math.random() * (GAME_H - 2 * margin);
angle = -Math.PI / 4 + Math.random() * (Math.PI / 2); // -45 to 45 deg
} else {
// right
x = GAME_W + 90;
y = margin + Math.random() * (GAME_H - 2 * margin);
angle = Math.PI * (1.25 + Math.random() * 0.5); // 225-315 deg
}
s.x = x;
s.y = y;
s.speed = shadowSpeed + Math.random() * 0.7;
s.vx = Math.cos(angle);
s.vy = Math.sin(angle);
// Randomly assign splitter type (10% chance, but not if too many shadows)
if (Math.random() < 0.10 && shadows.length < 6 && level > 1) {
s.shadowType = 'splitter';
// Tint splitter shadow for visibility
if (s.children && s.children[0]) {
s.children[0].tint = 0x4e7fff;
}
}
// Add to game and array
game.addChild(s);
shadows.push(s);
}
// Score update
function updateScore(val) {
score = val;
scoreTxt.setText(score);
if (score > highScore) {
highScore = score;
highScoreTxt.setText('En Yüksek Skor: ' + highScore);
storage.highScore = highScore;
}
}
// Difficulty ramp
function increaseDifficulty() {
if (shadowSpawnInterval > minShadowSpawnInterval) {
shadowSpawnInterval -= 3; // Decrease spawn interval more slowly
}
if (shadowCount < maxShadowCount) {
shadowCount += 1;
}
shadowSpeed += 0.09; // Increase speed more slowly
}
// Move handler (drag orb)
function handleMove(x, y, obj) {
if (dragging) {
// Clamp to game area, avoid top left 100x100
var nx = clamp(x, 100 + lightOrb.width / 2, GAME_W - lightOrb.width / 2);
var ny = clamp(y, lightOrb.height / 2, GAME_H - lightOrb.height / 2);
lightOrb.x = nx;
lightOrb.y = ny;
}
}
game.move = handleMove;
// Down handler (start drag)
game.down = function (x, y, obj) {
// Only start drag if touch is on orb
var dx = x - lightOrb.x;
var dy = y - lightOrb.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < lightOrb.width / 2 + 30) {
dragging = true;
lightOrb.flash();
handleMove(x, y, obj);
}
};
// Up handler (stop drag)
game.up = function (x, y, obj) {
dragging = false;
};
// Shadow spawn timer
var shadowTick = 0;
// Main update loop
game.update = function () {
// Update survival time
survivalTick++;
if (survivalTick >= 60) {
// update every 1s (60fps)
survivalTime += 1;
timeTxt.setText('Süre: ' + survivalTime);
survivalTick = 0;
// Pulse background color every 10 seconds survived
if (survivalTime > 0 && survivalTime % 10 === 0) {
var baseColor = 0x181c24;
var pulseColor = 0x232a3a;
game.setBackgroundColor(pulseColor);
LK.setTimeout(function () {
game.setBackgroundColor(baseColor);
}, 400);
}
}
// Spawn shadows
shadowTick++;
if (shadowTick >= shadowSpawnInterval) {
shadowTick = 0;
for (var i = 0; i < shadowCount; i++) {
spawnShadow();
}
}
// PowerUp spawn: every 6-10 seconds, if none active or on field
if (!powerUpActive && powerUps.length === 0 && Math.random() < 0.012) {
var p = new PowerUp();
// Random type, now includes 'shrink' and 'repel'
var types = ['slow', 'shield', 'score', 'shrink', 'repel'];
p.type = types[Math.floor(Math.random() * types.length)];
// Color by type
var color = 0x00eaff;
if (p.type === 'shield') color = 0x7fff00;
if (p.type === 'score') color = 0xffd700;
if (p.type === 'shrink') color = 0xff66cc;
if (p.type === 'repel') color = 0xff4400;
p.children[0].tint = color;
// Place randomly, not too close to edges or player
var safe = false,
px,
py,
tries = 0;
while (!safe && tries < 20) {
px = 200 + Math.random() * (GAME_W - 400);
py = 200 + Math.random() * (GAME_H - 400);
var dx = px - lightOrb.x,
dy = py - lightOrb.y;
if (Math.sqrt(dx * dx + dy * dy) > 300) safe = true;
tries++;
}
p.x = px;
p.y = py;
game.addChild(p);
powerUps.push(p);
}
// Update shadows
for (var i = shadows.length - 1; i >= 0; i--) {
var s = shadows[i];
s.update();
// Out of bounds: if shadow is far outside, remove and score
if (s.x < -300 || s.x > GAME_W + 300 || s.y < -300 || s.y > GAME_H + 300) {
// If this is a splitter shadow, split it before removing
if (s.shadowType === 'splitter' && !s._hasSplit) {
// Split into two smaller shadows
for (var splitIdx = 0; splitIdx < 2; splitIdx++) {
var newS = new Shadow();
newS.x = s.x;
newS.y = s.y;
// Give a random direction
var angle = Math.random() * Math.PI * 2;
newS.vx = Math.cos(angle);
newS.vy = Math.sin(angle);
newS.speed = shadowSpeed + 1.2 + Math.random() * 0.7;
newS.width = s.width * 0.7;
newS.height = s.height * 0.7;
newS.shadowType = 'normal';
game.addChild(newS);
shadows.push(newS);
}
s._hasSplit = true;
}
s.destroy();
shadows.splice(i, 1);
// Score for successful dodge
updateScore(score + 2); // Give 2 points per dodge
checkLevelUp();
// Every 5 points, ramp up difficulty
if (score > 0 && score % 5 === 0) {
increaseDifficulty();
}
continue;
}
// Collision with player
var intersecting = s.intersects(lightOrb);
// If invincible, flash orb and skip collision
if (lightOrb._invincible && lightOrb._invincible > 0) {
if (lightOrb._invincible % 8 === 0) {
LK.effects.flashObject(lightOrb, 0xffffff, 120);
}
lightOrb._invincible--;
s.lastIntersecting = intersecting;
continue;
}
if (!s.lastIntersecting && intersecting) {
// If shield powerup is active, destroy shadow and continue
if (powerUpActive && powerUpType === 'shield') {
// If this is a splitter shadow, split it before removing
if (s.shadowType === 'splitter' && !s._hasSplit) {
for (var splitIdx = 0; splitIdx < 2; splitIdx++) {
var newS = new Shadow();
newS.x = s.x;
newS.y = s.y;
var angle = Math.random() * Math.PI * 2;
newS.vx = Math.cos(angle);
newS.vy = Math.sin(angle);
newS.speed = shadowSpeed + 1.2 + Math.random() * 0.7;
newS.width = s.width * 0.7;
newS.height = s.height * 0.7;
newS.shadowType = 'normal';
game.addChild(newS);
shadows.push(newS);
}
s._hasSplit = true;
}
s.destroy();
shadows.splice(i, 1);
continue;
}
// Flash screen, game over
LK.effects.flashScreen(0xff2222, 900);
// Update high survival time if needed
if (survivalTime > highSurvivalTime) {
highSurvivalTime = survivalTime;
highTimeTxt.setText('En Yüksek Süre: ' + highSurvivalTime);
storage.highSurvivalTime = highSurvivalTime;
}
LK.showGameOver();
return;
}
s.lastIntersecting = intersecting;
}
// PowerUp collection and effect
for (var i = powerUps.length - 1; i >= 0; i--) {
var p = powerUps[i];
var intersecting = p.intersects(lightOrb);
if (!p.lastIntersecting && intersecting) {
// Activate effect
powerUpActive = true;
powerUpType = p.type;
powerUpTimer = 0;
// Add invincibility for 0.7s after collecting any powerup
lightOrb._invincible = 42; // 0.7s at 60fps
// Visual feedback
LK.effects.flashObject(lightOrb, p.children[0].tint, 600);
// Repel: extra visual feedback
if (p.type === 'repel') {
LK.effects.flashScreen(0xff4400, 400);
}
// Score boost: instant
if (p.type === 'score') {
updateScore(score + 10);
checkLevelUp();
powerUpActive = false;
powerUpType = null;
}
// Shrink: shrink orb for 4 seconds
if (p.type === 'shrink') {
// Store original size
if (!lightOrb._origW) {
lightOrb._origW = lightOrb.width;
lightOrb._origH = lightOrb.height;
}
lightOrb.width = lightOrb._origW * 0.55;
lightOrb.height = lightOrb._origH * 0.55;
}
// Repel: instantly push all shadows away from player
if (p.type === 'repel') {
for (var j = 0; j < shadows.length; j++) {
var s = shadows[j];
var dx = s.x - lightOrb.x;
var dy = s.y - lightOrb.y;
var dist = Math.sqrt(dx * dx + dy * dy) || 1;
// Set direction away from orb, keep speed
s.vx = dx / dist;
s.vy = dy / dist;
// Give a burst of speed
s.speed = Math.max(shadowSpeed + 2.5, 4.5);
}
powerUpActive = false;
powerUpType = null;
}
// Remove powerup from field
p.destroy();
powerUps.splice(i, 1);
continue;
}
p.lastIntersecting = intersecting;
}
// PowerUp timer/effect duration
if (powerUpActive) {
powerUpTimer++;
// Shadow slow: 4 seconds
if (powerUpType === 'slow') {
// Visual feedback: pulse effect while slow is active
if (powerUpTimer % 30 === 0) {
LK.effects.flashObject(lightOrb, 0x00eaff, 200);
}
// Slow down all shadows
for (var j = 0; j < shadows.length; j++) {
shadows[j].speed = 0.7;
}
shadowSpeed = 0.7;
if (powerUpTimer > 240) {
powerUpActive = false;
powerUpType = null;
shadowSpeed = 2.2 + Math.floor(score / 5) * 0.18;
// Restore all shadows to normal speed
for (var j = 0; j < shadows.length; j++) {
shadows[j].speed = shadowSpeed + Math.random() * 0.7;
}
}
}
// Shield: 4 seconds
if (powerUpType === 'shield') {
// Visual feedback: pulse effect while shield is active
if (powerUpTimer % 30 === 0) {
LK.effects.flashObject(lightOrb, 0x7fff00, 200);
}
if (powerUpTimer > 240) {
powerUpActive = false;
powerUpType = null;
}
}
// Shrink: 4 seconds
if (powerUpType === 'shrink') {
// Visual feedback: pulse effect while shrink is active
if (powerUpTimer % 30 === 0) {
LK.effects.flashObject(lightOrb, 0xff66cc, 200);
}
if (powerUpTimer > 240) {
powerUpActive = false;
powerUpType = null;
// Restore orb size
if (lightOrb._origW) {
lightOrb.width = lightOrb._origW;
lightOrb.height = lightOrb._origH;
}
}
}
} else {
// Reset shadowSpeed if not under slow powerup
shadowSpeed = 2.2 + Math.floor(score / 5) * 0.18;
for (var j = 0; j < shadows.length; j++) {
shadows[j].speed = shadowSpeed + Math.random() * 0.7;
}
}
};
// Initial score
updateScore(0);
level = 1;
levelTxt.setText('Seviye 1');
nextLevelScore = 15;
// Do not reset high score display or value on game start
highScoreTxt.setText('En Yüksek Skor: ' + highScore);
// Reset survival time
survivalTime = 0;
survivalTick = 0;
timeTxt.setText('Süre: 0');
// Show high survival time at game start
highTimeTxt.setText('En Yüksek Süre: ' + highSurvivalTime);
;
;