User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'update')' in or related to this line: 'obs.update();' Line Number: 719
User prompt
güzel şimdi son dokunuşlarıda yap son kez detaylandır
User prompt
Please fix the bug: 'TypeError: setTimeout is not a function' in or related to this line: 'setTimeout(function () {' Line Number: 600
User prompt
az daha yüskeğe zıpalsın
User prompt
şimdi bu oyunu olağanüstü en iyi hale getir onu detayını düşün seviye sistemi falan geometry dash gibi yap
User prompt
zemin ile arka planı bileşenlerden ayır
User prompt
zemin yeşil olsun
User prompt
arka planda yeşil olan yerleri mavi yap artık
User prompt
arka plan rengini mavi yap
User prompt
başlangıç ekranı yap
User prompt
arka planı mavi yap
User prompt
arka plan gökyüzü mavisi renginde olsun
User prompt
bulutlar belli olsun opaklığını 00 yap
User prompt
arka planı gökyüzü mavisi yap ve bulutlarında arkasında kalsın ve bulutların gölgesi olsun
User prompt
Please fix the bug: 'TypeError: tween.to is not a function' in or related to this line: 'tween.to(pop, {' Line Number: 288 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Uncaught TypeError: tween.to is not a function' in or related to this line: 'tween.to(self, {' Line Number: 59 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Uncaught TypeError: tween.to is not a function' in or related to this line: 'tween.to(obs, {' Line Number: 175 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Uncaught TypeError: tween.to is not a function' in or related to this line: 'tween.to(obs, {' Line Number: 175
User prompt
oyunu acayip güzelleştir herkes oynasın
User prompt
oyun çok hızlı akıyor zamanı daha güzel yap hızı
Code edit (1 edits merged)
Please save this source code
User prompt
Ninja Jump: Basit Engel Atlama
User prompt
basit engellerden atlayan ninja oyunu yap
Initial prompt
merhaba oyun yapcz
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Ninja class
var Ninja = Container.expand(function () {
var self = Container.call(this);
var ninjaAsset = self.attachAsset('ninja', {
anchorX: 0.5,
anchorY: 1
});
// Physics
self.vy = 0;
self.isJumping = false;
// Update method for gravity and jump
self.update = function () {
// Add jump trail effect
if (self.isJumping && Math.abs(self.vy) > 6 && Math.random() < 0.22) {
var trail = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.18 + Math.random() * 0.08,
scaleY: 0.10 + Math.random() * 0.05
});
trail.x = self.x + (Math.random() - 0.5) * 40;
trail.y = self.y + 60 + Math.random() * 10;
trail.alpha = 0.18 + Math.random() * 0.08;
trail.tint = 0x222222;
game.addChild(trail);
tween(trail, {
y: trail.y + 60 + Math.random() * 30,
alpha: 0,
scaleX: 0.01,
scaleY: 0.01
}, {
duration: 420 + Math.random() * 120,
easing: tween.linear,
onFinish: function onFinish() {
trail.destroy();
}
});
}
if (!self.isJumping) return;
self.y += self.vy;
self.vy += gravity;
// Land on ground
if (self.y >= groundY) {
self.y = groundY;
self.vy = 0;
if (self.isJumping) {
// Landing squash
tween(self, {
scaleY: 1.3,
scaleX: 0.8
}, {
duration: 60,
easing: tween.linear,
onFinish: function onFinish() {
tween(self, {
scaleY: 1,
scaleX: 1
}, {
duration: 120,
easing: tween.linear
});
}
});
// Landing dust burst
for (var i = 0; i < 7; i++) {
var dust = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.13 + Math.random() * 0.08,
scaleY: 0.09 + Math.random() * 0.06
});
dust.x = self.x + (Math.random() - 0.5) * 60;
dust.y = groundY + 10 + Math.random() * 8;
dust.alpha = 0.18 + Math.random() * 0.08;
dust.tint = 0x222222;
game.addChild(dust);
(function (dust, angle) {
var dist = 40 + Math.random() * 18;
var dx = Math.cos(angle) * dist;
var dy = Math.sin(angle) * dist * 0.3;
tween(dust, {
x: dust.x + dx,
y: dust.y - Math.abs(dy),
alpha: 0,
scaleX: 0.01,
scaleY: 0.01
}, {
duration: 420 + Math.random() * 120,
easing: tween.linear,
onFinish: function onFinish() {
dust.destroy();
}
});
})(dust, i / 7 * Math.PI * 2);
}
}
self.isJumping = false;
}
};
// Jump method
self.jump = function () {
if (!self.isJumping) {
self.vy = jumpVelocity;
self.isJumping = true;
// Jump squash/stretch effect
tween(self, {
scaleY: 0.7,
scaleX: 1.2
}, {
duration: 80,
easing: tween.linear,
onFinish: function onFinish() {
tween(self, {
scaleY: 1,
scaleX: 1
}, {
duration: 120,
easing: tween.linear
});
}
});
}
};
return self;
});
// Obstacle class
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obsAsset = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1
});
self.passed = false; // For scoring
self.type = "normal";
// Per-level obstacle tint
obsAsset.tint = levels[currentLevel].theme.obstacle;
// For advanced levels, add moving obstacles
if (currentLevel >= 2 && Math.random() < 0.3) {
self.type = "moving";
self.moveDir = Math.random() < 0.5 ? 1 : -1;
self.moveRange = 120 + Math.random() * 120;
self.baseY = groundY;
self.moveSpeed = 2.5 + Math.random() * 1.5;
}
// Update method for moving left
self.update = function () {
self.x -= obstacleSpeed;
// Advanced: moving obstacles (vertical)
if (self.type === "moving") {
self.y = self.baseY + Math.sin(LK.ticks * 0.06 * self.moveSpeed) * self.moveRange;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0000ff // blue
});
/****
* Game Code
****/
// Parallax background layers
var bgSky = LK.getAsset('bgSky', {
anchorX: 0,
anchorY: 0
});
bgSky.x = 0;
bgSky.y = 0;
game.addChild(bgSky);
// Add cloud shadows and clouds
var clouds = [];
var cloudShadows = [];
for (var i = 0; i < 4; i++) {
// Cloud shadow (drawn first, so it's behind the cloud)
var shadow = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3.2 + Math.random() * 2.2,
scaleY: 1.7 + Math.random() * 1.1
});
shadow.x = Math.random() * 2048;
shadow.y = 210 + Math.random() * 600;
shadow.alpha = 0.13 + Math.random() * 0.07;
shadow.tint = 0x7ec6e3; // bluish-grey shadow
cloudShadows.push(shadow);
game.addChild(shadow);
// Cloud (drawn after shadow, so it's in front)
var cloud = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: shadow.scaleX - 0.2,
scaleY: shadow.scaleY - 0.2
});
cloud.x = shadow.x + 30 + Math.random() * 20;
cloud.y = shadow.y - 20 - Math.random() * 10;
cloud.alpha = 1;
clouds.push(cloud);
game.addChild(cloud);
}
// --- Level System & Geometry Dash-like Features ---
// Level definitions
var levels = [{
name: "Başlangıç",
theme: {
sky: 0xb3e5fc,
ground: 0x43a047,
obstacle: 0x43a047
},
gravity: 3.2,
jumpVelocity: -72,
obstacleSpeed: 16,
obstacleMinGap: 700,
obstacleMaxGap: 1100,
length: 12,
// number of obstacles to finish
checkpoint: false
}, {
name: "Orman",
theme: {
sky: 0x8fd9a8,
ground: 0x2e7d32,
obstacle: 0x2e7d32
},
gravity: 3.5,
jumpVelocity: -74,
obstacleSpeed: 18,
obstacleMinGap: 650,
obstacleMaxGap: 1000,
length: 16,
checkpoint: true
}, {
name: "Gece",
theme: {
sky: 0x1a237e,
ground: 0x263238,
obstacle: 0x263238
},
gravity: 3.7,
jumpVelocity: -76,
obstacleSpeed: 20,
obstacleMinGap: 600,
obstacleMaxGap: 950,
length: 20,
checkpoint: true
}, {
name: "Buzul",
theme: {
sky: 0xe3f2fd,
ground: 0x90caf9,
obstacle: 0x90caf9
},
gravity: 3.9,
jumpVelocity: -78,
obstacleSpeed: 22,
obstacleMinGap: 570,
obstacleMaxGap: 900,
length: 24,
checkpoint: true
}, {
name: "Final",
theme: {
sky: 0x212121,
ground: 0xffd600,
obstacle: 0xffd600
},
gravity: 4.1,
jumpVelocity: -80,
obstacleSpeed: 24,
obstacleMinGap: 540,
obstacleMaxGap: 850,
length: 30,
checkpoint: false
}];
// Level state
var currentLevel = 0;
var obstaclesPassed = 0;
var checkpointData = null;
// Constants (will be set by level)
var groundY = 2400; // Y position of ground top
var gravity = levels[0].gravity;
var jumpVelocity = levels[0].jumpVelocity;
var obstacleSpeed = levels[0].obstacleSpeed;
var obstacleMinGap = levels[0].obstacleMinGap;
var obstacleMaxGap = levels[0].obstacleMaxGap;
// Game state
var ninja;
var ground;
var obstacles = [];
var score = 0;
var scoreTxt;
var gameStarted = false;
var lastObstacleX = 0;
// Level theme setter
function setLevelTheme(levelIdx) {
var theme = levels[levelIdx].theme;
// Level transition flash
LK.effects.flashScreen(theme.sky, 400);
bgSky.tint = theme.sky;
ground.tint = theme.ground;
// Optionally, obstacles can be tinted in their class update
}
// Level setter
function setLevel(levelIdx) {
currentLevel = levelIdx;
var lvl = levels[levelIdx];
gravity = lvl.gravity;
jumpVelocity = lvl.jumpVelocity;
obstacleSpeed = lvl.obstacleSpeed;
obstacleMinGap = lvl.obstacleMinGap;
obstacleMaxGap = lvl.obstacleMaxGap;
setLevelTheme(levelIdx);
obstaclesPassed = 0;
}
// Show level name at start
function showLevelName(levelIdx) {
var name = levels[levelIdx].name;
var levelText = new Text2("Seviye: " + name, {
size: 120,
fill: "#fff",
font: "Impact, Arial Black, Tahoma"
});
levelText.anchor.set(0.5, 0.5);
levelText.x = 2048 / 2;
levelText.y = 600;
levelText.alpha = 0.0;
game.addChild(levelText);
tween(levelText, {
alpha: 1
}, {
duration: 400,
easing: tween.linear,
onFinish: function onFinish() {
tween(levelText, {
alpha: 0
}, {
duration: 700,
delay: 900,
easing: tween.linear,
onFinish: function onFinish() {
levelText.destroy();
}
});
}
});
}
// Show checkpoint with animated effect and particles
function showCheckpoint() {
var cpText = new Text2("Checkpoint!", {
size: 100,
fill: 0xFFD600,
font: "Impact, Arial Black, Tahoma"
});
cpText.anchor.set(0.5, 0.5);
cpText.x = 2048 / 2;
cpText.y = 800;
cpText.alpha = 0.0;
cpText.scaleX = cpText.scaleY = 0.7;
game.addChild(cpText);
// Animate pop and fade
tween(cpText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 220,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(cpText, {
alpha: 0,
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 600,
delay: 700,
easing: tween.linear,
onFinish: function onFinish() {
cpText.destroy();
}
});
}
});
// Particle burst
for (var i = 0; i < 18; i++) {
var p = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.18 + Math.random() * 0.12,
scaleY: 0.18 + Math.random() * 0.12
});
p.x = cpText.x;
p.y = cpText.y;
p.alpha = 0.7;
p.tint = 0xFFD600;
game.addChild(p);
(function (p, angle) {
var dist = 120 + Math.random() * 60;
var dx = Math.cos(angle) * dist;
var dy = Math.sin(angle) * dist;
tween(p, {
x: p.x + dx,
y: p.y + dy,
alpha: 0,
scaleX: 0.01,
scaleY: 0.01
}, {
duration: 700 + Math.random() * 200,
easing: tween.linear,
onFinish: function onFinish() {
p.destroy();
}
});
})(p, i / 18 * Math.PI * 2);
}
}
// Save checkpoint data
function saveCheckpoint() {
checkpointData = {
level: currentLevel,
score: score,
obstaclesPassed: obstaclesPassed
};
}
// Restore checkpoint data
function restoreCheckpoint() {
if (!checkpointData) return;
setLevel(checkpointData.level);
score = checkpointData.score;
obstaclesPassed = checkpointData.obstaclesPassed;
scoreTxt.setText(score);
}
// Level complete with animated effect and particles
function showLevelComplete() {
var completeText = new Text2("Seviye Tamamlandı!", {
size: 120,
fill: 0xFFD600,
font: "Impact, Arial Black, Tahoma"
});
completeText.anchor.set(0.5, 0.5);
completeText.x = 2048 / 2;
completeText.y = 900;
completeText.alpha = 0.0;
completeText.scaleX = completeText.scaleY = 0.7;
game.addChild(completeText);
tween(completeText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(completeText, {
alpha: 0,
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 700,
delay: 900,
easing: tween.linear,
onFinish: function onFinish() {
completeText.destroy();
}
});
}
});
// Particle burst
for (var i = 0; i < 22; i++) {
var p = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.22 + Math.random() * 0.13,
scaleY: 0.22 + Math.random() * 0.13
});
p.x = completeText.x;
p.y = completeText.y;
p.alpha = 0.7;
p.tint = 0xFFD600;
game.addChild(p);
(function (p, angle) {
var dist = 160 + Math.random() * 80;
var dx = Math.cos(angle) * dist;
var dy = Math.sin(angle) * dist;
tween(p, {
x: p.x + dx,
y: p.y + dy,
alpha: 0,
scaleX: 0.01,
scaleY: 0.01
}, {
duration: 900 + Math.random() * 200,
easing: tween.linear,
onFinish: function onFinish() {
p.destroy();
}
});
})(p, i / 22 * Math.PI * 2);
}
}
// All levels complete with animated effect and particles
function showGameWin() {
var winText = new Text2("Tebrikler! Tüm seviyeler tamamlandı!", {
size: 100,
fill: 0xFFD600,
font: "Impact, Arial Black, Tahoma"
});
winText.anchor.set(0.5, 0.5);
winText.x = 2048 / 2;
winText.y = 900;
winText.alpha = 0.0;
winText.scaleX = winText.scaleY = 0.7;
game.addChild(winText);
tween(winText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(winText, {
alpha: 0,
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 1200,
delay: 1200,
easing: tween.linear,
onFinish: function onFinish() {
winText.destroy();
}
});
}
});
// Particle burst
for (var i = 0; i < 32; i++) {
var p = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.25 + Math.random() * 0.15,
scaleY: 0.25 + Math.random() * 0.15
});
p.x = winText.x;
p.y = winText.y;
p.alpha = 0.7;
p.tint = 0xFFD600;
game.addChild(p);
(function (p, angle) {
var dist = 220 + Math.random() * 100;
var dx = Math.cos(angle) * dist;
var dy = Math.sin(angle) * dist;
tween(p, {
x: p.x + dx,
y: p.y + dy,
alpha: 0,
scaleX: 0.01,
scaleY: 0.01
}, {
duration: 1200 + Math.random() * 300,
easing: tween.linear,
onFinish: function onFinish() {
p.destroy();
}
});
})(p, i / 32 * Math.PI * 2);
}
}
// Add ground shadow for depth
var groundShadow = LK.getAsset('centerCircle', {
anchorX: 0,
anchorY: 0.5,
scaleX: 22,
scaleY: 1.2
});
groundShadow.x = 0;
groundShadow.y = groundY + 60;
groundShadow.alpha = 0.10;
groundShadow.tint = 0x222222;
game.addChild(groundShadow);
// Add ground
ground = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0
});
ground.x = 0;
ground.y = groundY;
ground.tint = 0x43a047; // green
game.addChild(ground);
// Add ninja shadow
var ninjaShadow = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 0.4
});
ninjaShadow.x = 420;
ninjaShadow.y = groundY + 10;
ninjaShadow.alpha = 0.18;
game.addChild(ninjaShadow);
// Add ninja
ninja = new Ninja();
ninja.x = 420;
ninja.y = groundY;
game.addChild(ninja);
// Score text
scoreTxt = new Text2('0', {
size: 120,
fill: "#222"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Helper: spawn obstacle
function spawnObstacle() {
var obs = new Obstacle();
obs.x = 2048 + 100;
obs.y = groundY;
obs.scaleX = obs.scaleY = 0.2 + Math.random() * 0.2;
tween(obs, {
scaleX: 1,
scaleY: 1
}, {
duration: 220,
easing: tween.bounceOut
});
obstacles.push(obs);
game.addChild(obs);
lastObstacleX = obs.x;
}
// Helper: reset game state
function resetGame(levelIdx) {
// Remove obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].destroy();
}
obstacles = [];
// Set level (default to 0 if not provided)
if (typeof levelIdx === "undefined") levelIdx = 0;
setLevel(levelIdx);
// Reset ninja
ninja.x = 420;
ninja.y = groundY;
ninja.vy = 0;
ninja.isJumping = false;
// Reset score
score = 0;
scoreTxt.setText(score);
// Reset obstacle spawn
lastObstacleX = 0;
// Spawn first obstacle
spawnObstacle();
gameStarted = true;
showLevelName(levelIdx);
}
// Start game on first tap
game.down = function (x, y, obj) {
if (!gameStarted) {
resetGame();
ninja.jump();
return;
}
// Only jump if not already jumping
ninja.jump();
};
// Main update loop
game.update = function () {
if (!gameStarted) return;
// Parallax background movement
for (var i = 0; i < clouds.length; i++) {
// Move shadow first
cloudShadows[i].x -= 0.7 + i * 0.2;
// Move cloud in sync, but slightly offset for depth
clouds[i].x -= 0.7 + i * 0.2;
if (clouds[i].x < -400) {
// Reset shadow position
cloudShadows[i].x = 2048 + 200 * Math.random();
cloudShadows[i].y = 200 + Math.random() * 600;
// Reset cloud position, offset from shadow
clouds[i].x = cloudShadows[i].x + 30 + Math.random() * 20;
clouds[i].y = cloudShadows[i].y - 20 - Math.random() * 10;
}
}
// Update ninja
ninja.update();
ninjaShadow.x = ninja.x;
ninjaShadow.y = groundY + 10 + Math.min(80, Math.abs(ninja.y - groundY) * 0.12);
ninjaShadow.scaleX = 1.2 + Math.abs(ninja.y - groundY) * 0.001;
ninjaShadow.alpha = 0.18 - Math.abs(ninja.y - groundY) * 0.00012;
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
if (!obs || typeof obs.update !== "function") continue;
obs.update();
// Check for collision
if (ninja.intersects(obs)) {
// Camera shake
var shake = 0;
var shakeInterval = LK.setInterval(function () {
shake++;
game.x = (Math.random() - 0.5) * 30;
game.y = (Math.random() - 0.5) * 18;
if (shake > 10) {
game.x = 0;
game.y = 0;
LK.clearInterval(shakeInterval);
}
}, 16);
// Flash screen and game over
LK.effects.flashScreen(0xff0000, 800);
// If checkpoint exists, offer restart from checkpoint
if (levels[currentLevel].checkpoint && checkpointData && checkpointData.level === currentLevel) {
// Show checkpoint text and restore
showCheckpoint();
LK.setTimeout(function () {
restoreCheckpoint();
resetGame(currentLevel);
}, 1200);
} else {
LK.showGameOver();
gameStarted = false;
}
return;
}
// Scoring: passed obstacle
if (!obs.passed && obs.x + 60 < ninja.x) {
obs.passed = true;
score += 1;
scoreTxt.setText(score);
obstaclesPassed += 1;
// Floating score pop with bounce and color
var pop = new Text2("+1", {
size: 80,
fill: 0x43A047
});
pop.x = ninja.x;
pop.y = ninja.y - 180;
pop.anchor.set(0.5, 1);
pop.scaleX = pop.scaleY = 0.7;
pop.alpha = 0.0;
game.addChild(pop);
tween(pop, {
y: pop.y - 120,
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 180,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(pop, {
y: pop.y - 40,
alpha: 0,
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 520,
easing: tween.linear,
onFinish: function onFinish() {
pop.destroy();
}
});
}
});
// Confetti burst
for (var i = 0; i < 8; i++) {
var conf = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.09 + Math.random() * 0.06,
scaleY: 0.09 + Math.random() * 0.06
});
conf.x = ninja.x;
conf.y = ninja.y - 180;
conf.alpha = 0.7;
conf.tint = [0x43A047, 0xFFD600, 0x00bcd4, 0xff4081][Math.floor(Math.random() * 4)];
game.addChild(conf);
(function (conf, angle) {
var dist = 60 + Math.random() * 30;
var dx = Math.cos(angle) * dist;
var dy = Math.sin(angle) * dist;
tween(conf, {
x: conf.x + dx,
y: conf.y + dy,
alpha: 0,
scaleX: 0.01,
scaleY: 0.01
}, {
duration: 600 + Math.random() * 120,
easing: tween.linear,
onFinish: function onFinish() {
conf.destroy();
}
});
})(conf, i / 8 * Math.PI * 2);
}
// Checkpoint: save progress
if (levels[currentLevel].checkpoint && obstaclesPassed === Math.floor(levels[currentLevel].length / 2)) {
saveCheckpoint();
showCheckpoint();
}
// Level complete
if (obstaclesPassed >= levels[currentLevel].length) {
showLevelComplete();
// Next level or win
LK.setTimeout(function () {
if (currentLevel < levels.length - 1) {
resetGame(currentLevel + 1);
} else {
showGameWin();
LK.showYouWin();
}
}, 1500);
return;
}
}
// Remove off-screen obstacles
if (obs && obs.x < -200) {
obs.destroy();
obstacles.splice(i, 1);
}
}
// Spawn new obstacles
if (obstacles.length === 0 || 2048 - lastObstacleX > obstacleMinGap + Math.floor(Math.random() * (obstacleMaxGap - obstacleMinGap))) {
spawnObstacle();
}
};
// On game over, allow restart on tap
game.up = function (x, y, obj) {
if (!gameStarted) {
// Wait for LK.showGameOver to reset game
}
};
// Initial state: show "Tap to Start"
gameStarted = false;
scoreTxt.setText('0');
;
// --- Start Screen Overlay ---
var startOverlay = new Container();
var titleText = new Text2("Ninja Jump", {
size: 180,
fill: "#222",
font: "Impact, Arial Black, Tahoma"
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 900;
titleText.alpha = 0.0;
titleText.scaleX = titleText.scaleY = 0.7;
startOverlay.addChild(titleText);
var tapText = new Text2("Başlamak için dokun!", {
size: 100,
fill: "#222",
font: "Impact, Arial Black, Tahoma"
});
tapText.anchor.set(0.5, 0.5);
tapText.x = 2048 / 2;
tapText.y = 1200;
tapText.alpha = 0.0;
tapText.scaleX = tapText.scaleY = 0.7;
startOverlay.addChild(tapText);
game.addChild(startOverlay);
// Animate overlay in
tween(titleText, {
alpha: 1,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(titleText, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.linear
});
}
});
tween(tapText, {
alpha: 1,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 600,
delay: 200,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(tapText, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.linear
});
}
});
// Hide overlay on game start
var oldGameDown = game.down;
game.down = function (x, y, obj) {
if (!gameStarted) {
// Animate overlay out
if (startOverlay && startOverlay.parent) {
tween(titleText, {
alpha: 0,
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 300,
easing: tween.linear
});
tween(tapText, {
alpha: 0,
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 300,
easing: tween.linear,
onFinish: function onFinish() {
if (startOverlay && startOverlay.parent) {
startOverlay.parent.removeChild(startOverlay);
}
}
});
}
// If checkpoint exists, offer to restore
if (checkpointData && checkpointData.level !== undefined) {
restoreCheckpoint();
resetGame(checkpointData.level);
} else {
resetGame(0);
}
ninja.jump();
return;
}
// Only jump if not already jumping
ninja.jump();
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Ninja class
var Ninja = Container.expand(function () {
var self = Container.call(this);
var ninjaAsset = self.attachAsset('ninja', {
anchorX: 0.5,
anchorY: 1
});
// Physics
self.vy = 0;
self.isJumping = false;
// Update method for gravity and jump
self.update = function () {
// Add jump trail effect
if (self.isJumping && Math.abs(self.vy) > 6 && Math.random() < 0.22) {
var trail = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.18 + Math.random() * 0.08,
scaleY: 0.10 + Math.random() * 0.05
});
trail.x = self.x + (Math.random() - 0.5) * 40;
trail.y = self.y + 60 + Math.random() * 10;
trail.alpha = 0.18 + Math.random() * 0.08;
trail.tint = 0x222222;
game.addChild(trail);
tween(trail, {
y: trail.y + 60 + Math.random() * 30,
alpha: 0,
scaleX: 0.01,
scaleY: 0.01
}, {
duration: 420 + Math.random() * 120,
easing: tween.linear,
onFinish: function onFinish() {
trail.destroy();
}
});
}
if (!self.isJumping) return;
self.y += self.vy;
self.vy += gravity;
// Land on ground
if (self.y >= groundY) {
self.y = groundY;
self.vy = 0;
if (self.isJumping) {
// Landing squash
tween(self, {
scaleY: 1.3,
scaleX: 0.8
}, {
duration: 60,
easing: tween.linear,
onFinish: function onFinish() {
tween(self, {
scaleY: 1,
scaleX: 1
}, {
duration: 120,
easing: tween.linear
});
}
});
// Landing dust burst
for (var i = 0; i < 7; i++) {
var dust = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.13 + Math.random() * 0.08,
scaleY: 0.09 + Math.random() * 0.06
});
dust.x = self.x + (Math.random() - 0.5) * 60;
dust.y = groundY + 10 + Math.random() * 8;
dust.alpha = 0.18 + Math.random() * 0.08;
dust.tint = 0x222222;
game.addChild(dust);
(function (dust, angle) {
var dist = 40 + Math.random() * 18;
var dx = Math.cos(angle) * dist;
var dy = Math.sin(angle) * dist * 0.3;
tween(dust, {
x: dust.x + dx,
y: dust.y - Math.abs(dy),
alpha: 0,
scaleX: 0.01,
scaleY: 0.01
}, {
duration: 420 + Math.random() * 120,
easing: tween.linear,
onFinish: function onFinish() {
dust.destroy();
}
});
})(dust, i / 7 * Math.PI * 2);
}
}
self.isJumping = false;
}
};
// Jump method
self.jump = function () {
if (!self.isJumping) {
self.vy = jumpVelocity;
self.isJumping = true;
// Jump squash/stretch effect
tween(self, {
scaleY: 0.7,
scaleX: 1.2
}, {
duration: 80,
easing: tween.linear,
onFinish: function onFinish() {
tween(self, {
scaleY: 1,
scaleX: 1
}, {
duration: 120,
easing: tween.linear
});
}
});
}
};
return self;
});
// Obstacle class
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obsAsset = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1
});
self.passed = false; // For scoring
self.type = "normal";
// Per-level obstacle tint
obsAsset.tint = levels[currentLevel].theme.obstacle;
// For advanced levels, add moving obstacles
if (currentLevel >= 2 && Math.random() < 0.3) {
self.type = "moving";
self.moveDir = Math.random() < 0.5 ? 1 : -1;
self.moveRange = 120 + Math.random() * 120;
self.baseY = groundY;
self.moveSpeed = 2.5 + Math.random() * 1.5;
}
// Update method for moving left
self.update = function () {
self.x -= obstacleSpeed;
// Advanced: moving obstacles (vertical)
if (self.type === "moving") {
self.y = self.baseY + Math.sin(LK.ticks * 0.06 * self.moveSpeed) * self.moveRange;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0000ff // blue
});
/****
* Game Code
****/
// Parallax background layers
var bgSky = LK.getAsset('bgSky', {
anchorX: 0,
anchorY: 0
});
bgSky.x = 0;
bgSky.y = 0;
game.addChild(bgSky);
// Add cloud shadows and clouds
var clouds = [];
var cloudShadows = [];
for (var i = 0; i < 4; i++) {
// Cloud shadow (drawn first, so it's behind the cloud)
var shadow = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3.2 + Math.random() * 2.2,
scaleY: 1.7 + Math.random() * 1.1
});
shadow.x = Math.random() * 2048;
shadow.y = 210 + Math.random() * 600;
shadow.alpha = 0.13 + Math.random() * 0.07;
shadow.tint = 0x7ec6e3; // bluish-grey shadow
cloudShadows.push(shadow);
game.addChild(shadow);
// Cloud (drawn after shadow, so it's in front)
var cloud = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: shadow.scaleX - 0.2,
scaleY: shadow.scaleY - 0.2
});
cloud.x = shadow.x + 30 + Math.random() * 20;
cloud.y = shadow.y - 20 - Math.random() * 10;
cloud.alpha = 1;
clouds.push(cloud);
game.addChild(cloud);
}
// --- Level System & Geometry Dash-like Features ---
// Level definitions
var levels = [{
name: "Başlangıç",
theme: {
sky: 0xb3e5fc,
ground: 0x43a047,
obstacle: 0x43a047
},
gravity: 3.2,
jumpVelocity: -72,
obstacleSpeed: 16,
obstacleMinGap: 700,
obstacleMaxGap: 1100,
length: 12,
// number of obstacles to finish
checkpoint: false
}, {
name: "Orman",
theme: {
sky: 0x8fd9a8,
ground: 0x2e7d32,
obstacle: 0x2e7d32
},
gravity: 3.5,
jumpVelocity: -74,
obstacleSpeed: 18,
obstacleMinGap: 650,
obstacleMaxGap: 1000,
length: 16,
checkpoint: true
}, {
name: "Gece",
theme: {
sky: 0x1a237e,
ground: 0x263238,
obstacle: 0x263238
},
gravity: 3.7,
jumpVelocity: -76,
obstacleSpeed: 20,
obstacleMinGap: 600,
obstacleMaxGap: 950,
length: 20,
checkpoint: true
}, {
name: "Buzul",
theme: {
sky: 0xe3f2fd,
ground: 0x90caf9,
obstacle: 0x90caf9
},
gravity: 3.9,
jumpVelocity: -78,
obstacleSpeed: 22,
obstacleMinGap: 570,
obstacleMaxGap: 900,
length: 24,
checkpoint: true
}, {
name: "Final",
theme: {
sky: 0x212121,
ground: 0xffd600,
obstacle: 0xffd600
},
gravity: 4.1,
jumpVelocity: -80,
obstacleSpeed: 24,
obstacleMinGap: 540,
obstacleMaxGap: 850,
length: 30,
checkpoint: false
}];
// Level state
var currentLevel = 0;
var obstaclesPassed = 0;
var checkpointData = null;
// Constants (will be set by level)
var groundY = 2400; // Y position of ground top
var gravity = levels[0].gravity;
var jumpVelocity = levels[0].jumpVelocity;
var obstacleSpeed = levels[0].obstacleSpeed;
var obstacleMinGap = levels[0].obstacleMinGap;
var obstacleMaxGap = levels[0].obstacleMaxGap;
// Game state
var ninja;
var ground;
var obstacles = [];
var score = 0;
var scoreTxt;
var gameStarted = false;
var lastObstacleX = 0;
// Level theme setter
function setLevelTheme(levelIdx) {
var theme = levels[levelIdx].theme;
// Level transition flash
LK.effects.flashScreen(theme.sky, 400);
bgSky.tint = theme.sky;
ground.tint = theme.ground;
// Optionally, obstacles can be tinted in their class update
}
// Level setter
function setLevel(levelIdx) {
currentLevel = levelIdx;
var lvl = levels[levelIdx];
gravity = lvl.gravity;
jumpVelocity = lvl.jumpVelocity;
obstacleSpeed = lvl.obstacleSpeed;
obstacleMinGap = lvl.obstacleMinGap;
obstacleMaxGap = lvl.obstacleMaxGap;
setLevelTheme(levelIdx);
obstaclesPassed = 0;
}
// Show level name at start
function showLevelName(levelIdx) {
var name = levels[levelIdx].name;
var levelText = new Text2("Seviye: " + name, {
size: 120,
fill: "#fff",
font: "Impact, Arial Black, Tahoma"
});
levelText.anchor.set(0.5, 0.5);
levelText.x = 2048 / 2;
levelText.y = 600;
levelText.alpha = 0.0;
game.addChild(levelText);
tween(levelText, {
alpha: 1
}, {
duration: 400,
easing: tween.linear,
onFinish: function onFinish() {
tween(levelText, {
alpha: 0
}, {
duration: 700,
delay: 900,
easing: tween.linear,
onFinish: function onFinish() {
levelText.destroy();
}
});
}
});
}
// Show checkpoint with animated effect and particles
function showCheckpoint() {
var cpText = new Text2("Checkpoint!", {
size: 100,
fill: 0xFFD600,
font: "Impact, Arial Black, Tahoma"
});
cpText.anchor.set(0.5, 0.5);
cpText.x = 2048 / 2;
cpText.y = 800;
cpText.alpha = 0.0;
cpText.scaleX = cpText.scaleY = 0.7;
game.addChild(cpText);
// Animate pop and fade
tween(cpText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 220,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(cpText, {
alpha: 0,
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 600,
delay: 700,
easing: tween.linear,
onFinish: function onFinish() {
cpText.destroy();
}
});
}
});
// Particle burst
for (var i = 0; i < 18; i++) {
var p = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.18 + Math.random() * 0.12,
scaleY: 0.18 + Math.random() * 0.12
});
p.x = cpText.x;
p.y = cpText.y;
p.alpha = 0.7;
p.tint = 0xFFD600;
game.addChild(p);
(function (p, angle) {
var dist = 120 + Math.random() * 60;
var dx = Math.cos(angle) * dist;
var dy = Math.sin(angle) * dist;
tween(p, {
x: p.x + dx,
y: p.y + dy,
alpha: 0,
scaleX: 0.01,
scaleY: 0.01
}, {
duration: 700 + Math.random() * 200,
easing: tween.linear,
onFinish: function onFinish() {
p.destroy();
}
});
})(p, i / 18 * Math.PI * 2);
}
}
// Save checkpoint data
function saveCheckpoint() {
checkpointData = {
level: currentLevel,
score: score,
obstaclesPassed: obstaclesPassed
};
}
// Restore checkpoint data
function restoreCheckpoint() {
if (!checkpointData) return;
setLevel(checkpointData.level);
score = checkpointData.score;
obstaclesPassed = checkpointData.obstaclesPassed;
scoreTxt.setText(score);
}
// Level complete with animated effect and particles
function showLevelComplete() {
var completeText = new Text2("Seviye Tamamlandı!", {
size: 120,
fill: 0xFFD600,
font: "Impact, Arial Black, Tahoma"
});
completeText.anchor.set(0.5, 0.5);
completeText.x = 2048 / 2;
completeText.y = 900;
completeText.alpha = 0.0;
completeText.scaleX = completeText.scaleY = 0.7;
game.addChild(completeText);
tween(completeText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(completeText, {
alpha: 0,
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 700,
delay: 900,
easing: tween.linear,
onFinish: function onFinish() {
completeText.destroy();
}
});
}
});
// Particle burst
for (var i = 0; i < 22; i++) {
var p = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.22 + Math.random() * 0.13,
scaleY: 0.22 + Math.random() * 0.13
});
p.x = completeText.x;
p.y = completeText.y;
p.alpha = 0.7;
p.tint = 0xFFD600;
game.addChild(p);
(function (p, angle) {
var dist = 160 + Math.random() * 80;
var dx = Math.cos(angle) * dist;
var dy = Math.sin(angle) * dist;
tween(p, {
x: p.x + dx,
y: p.y + dy,
alpha: 0,
scaleX: 0.01,
scaleY: 0.01
}, {
duration: 900 + Math.random() * 200,
easing: tween.linear,
onFinish: function onFinish() {
p.destroy();
}
});
})(p, i / 22 * Math.PI * 2);
}
}
// All levels complete with animated effect and particles
function showGameWin() {
var winText = new Text2("Tebrikler! Tüm seviyeler tamamlandı!", {
size: 100,
fill: 0xFFD600,
font: "Impact, Arial Black, Tahoma"
});
winText.anchor.set(0.5, 0.5);
winText.x = 2048 / 2;
winText.y = 900;
winText.alpha = 0.0;
winText.scaleX = winText.scaleY = 0.7;
game.addChild(winText);
tween(winText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(winText, {
alpha: 0,
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 1200,
delay: 1200,
easing: tween.linear,
onFinish: function onFinish() {
winText.destroy();
}
});
}
});
// Particle burst
for (var i = 0; i < 32; i++) {
var p = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.25 + Math.random() * 0.15,
scaleY: 0.25 + Math.random() * 0.15
});
p.x = winText.x;
p.y = winText.y;
p.alpha = 0.7;
p.tint = 0xFFD600;
game.addChild(p);
(function (p, angle) {
var dist = 220 + Math.random() * 100;
var dx = Math.cos(angle) * dist;
var dy = Math.sin(angle) * dist;
tween(p, {
x: p.x + dx,
y: p.y + dy,
alpha: 0,
scaleX: 0.01,
scaleY: 0.01
}, {
duration: 1200 + Math.random() * 300,
easing: tween.linear,
onFinish: function onFinish() {
p.destroy();
}
});
})(p, i / 32 * Math.PI * 2);
}
}
// Add ground shadow for depth
var groundShadow = LK.getAsset('centerCircle', {
anchorX: 0,
anchorY: 0.5,
scaleX: 22,
scaleY: 1.2
});
groundShadow.x = 0;
groundShadow.y = groundY + 60;
groundShadow.alpha = 0.10;
groundShadow.tint = 0x222222;
game.addChild(groundShadow);
// Add ground
ground = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0
});
ground.x = 0;
ground.y = groundY;
ground.tint = 0x43a047; // green
game.addChild(ground);
// Add ninja shadow
var ninjaShadow = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 0.4
});
ninjaShadow.x = 420;
ninjaShadow.y = groundY + 10;
ninjaShadow.alpha = 0.18;
game.addChild(ninjaShadow);
// Add ninja
ninja = new Ninja();
ninja.x = 420;
ninja.y = groundY;
game.addChild(ninja);
// Score text
scoreTxt = new Text2('0', {
size: 120,
fill: "#222"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Helper: spawn obstacle
function spawnObstacle() {
var obs = new Obstacle();
obs.x = 2048 + 100;
obs.y = groundY;
obs.scaleX = obs.scaleY = 0.2 + Math.random() * 0.2;
tween(obs, {
scaleX: 1,
scaleY: 1
}, {
duration: 220,
easing: tween.bounceOut
});
obstacles.push(obs);
game.addChild(obs);
lastObstacleX = obs.x;
}
// Helper: reset game state
function resetGame(levelIdx) {
// Remove obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].destroy();
}
obstacles = [];
// Set level (default to 0 if not provided)
if (typeof levelIdx === "undefined") levelIdx = 0;
setLevel(levelIdx);
// Reset ninja
ninja.x = 420;
ninja.y = groundY;
ninja.vy = 0;
ninja.isJumping = false;
// Reset score
score = 0;
scoreTxt.setText(score);
// Reset obstacle spawn
lastObstacleX = 0;
// Spawn first obstacle
spawnObstacle();
gameStarted = true;
showLevelName(levelIdx);
}
// Start game on first tap
game.down = function (x, y, obj) {
if (!gameStarted) {
resetGame();
ninja.jump();
return;
}
// Only jump if not already jumping
ninja.jump();
};
// Main update loop
game.update = function () {
if (!gameStarted) return;
// Parallax background movement
for (var i = 0; i < clouds.length; i++) {
// Move shadow first
cloudShadows[i].x -= 0.7 + i * 0.2;
// Move cloud in sync, but slightly offset for depth
clouds[i].x -= 0.7 + i * 0.2;
if (clouds[i].x < -400) {
// Reset shadow position
cloudShadows[i].x = 2048 + 200 * Math.random();
cloudShadows[i].y = 200 + Math.random() * 600;
// Reset cloud position, offset from shadow
clouds[i].x = cloudShadows[i].x + 30 + Math.random() * 20;
clouds[i].y = cloudShadows[i].y - 20 - Math.random() * 10;
}
}
// Update ninja
ninja.update();
ninjaShadow.x = ninja.x;
ninjaShadow.y = groundY + 10 + Math.min(80, Math.abs(ninja.y - groundY) * 0.12);
ninjaShadow.scaleX = 1.2 + Math.abs(ninja.y - groundY) * 0.001;
ninjaShadow.alpha = 0.18 - Math.abs(ninja.y - groundY) * 0.00012;
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
if (!obs || typeof obs.update !== "function") continue;
obs.update();
// Check for collision
if (ninja.intersects(obs)) {
// Camera shake
var shake = 0;
var shakeInterval = LK.setInterval(function () {
shake++;
game.x = (Math.random() - 0.5) * 30;
game.y = (Math.random() - 0.5) * 18;
if (shake > 10) {
game.x = 0;
game.y = 0;
LK.clearInterval(shakeInterval);
}
}, 16);
// Flash screen and game over
LK.effects.flashScreen(0xff0000, 800);
// If checkpoint exists, offer restart from checkpoint
if (levels[currentLevel].checkpoint && checkpointData && checkpointData.level === currentLevel) {
// Show checkpoint text and restore
showCheckpoint();
LK.setTimeout(function () {
restoreCheckpoint();
resetGame(currentLevel);
}, 1200);
} else {
LK.showGameOver();
gameStarted = false;
}
return;
}
// Scoring: passed obstacle
if (!obs.passed && obs.x + 60 < ninja.x) {
obs.passed = true;
score += 1;
scoreTxt.setText(score);
obstaclesPassed += 1;
// Floating score pop with bounce and color
var pop = new Text2("+1", {
size: 80,
fill: 0x43A047
});
pop.x = ninja.x;
pop.y = ninja.y - 180;
pop.anchor.set(0.5, 1);
pop.scaleX = pop.scaleY = 0.7;
pop.alpha = 0.0;
game.addChild(pop);
tween(pop, {
y: pop.y - 120,
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 180,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(pop, {
y: pop.y - 40,
alpha: 0,
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 520,
easing: tween.linear,
onFinish: function onFinish() {
pop.destroy();
}
});
}
});
// Confetti burst
for (var i = 0; i < 8; i++) {
var conf = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.09 + Math.random() * 0.06,
scaleY: 0.09 + Math.random() * 0.06
});
conf.x = ninja.x;
conf.y = ninja.y - 180;
conf.alpha = 0.7;
conf.tint = [0x43A047, 0xFFD600, 0x00bcd4, 0xff4081][Math.floor(Math.random() * 4)];
game.addChild(conf);
(function (conf, angle) {
var dist = 60 + Math.random() * 30;
var dx = Math.cos(angle) * dist;
var dy = Math.sin(angle) * dist;
tween(conf, {
x: conf.x + dx,
y: conf.y + dy,
alpha: 0,
scaleX: 0.01,
scaleY: 0.01
}, {
duration: 600 + Math.random() * 120,
easing: tween.linear,
onFinish: function onFinish() {
conf.destroy();
}
});
})(conf, i / 8 * Math.PI * 2);
}
// Checkpoint: save progress
if (levels[currentLevel].checkpoint && obstaclesPassed === Math.floor(levels[currentLevel].length / 2)) {
saveCheckpoint();
showCheckpoint();
}
// Level complete
if (obstaclesPassed >= levels[currentLevel].length) {
showLevelComplete();
// Next level or win
LK.setTimeout(function () {
if (currentLevel < levels.length - 1) {
resetGame(currentLevel + 1);
} else {
showGameWin();
LK.showYouWin();
}
}, 1500);
return;
}
}
// Remove off-screen obstacles
if (obs && obs.x < -200) {
obs.destroy();
obstacles.splice(i, 1);
}
}
// Spawn new obstacles
if (obstacles.length === 0 || 2048 - lastObstacleX > obstacleMinGap + Math.floor(Math.random() * (obstacleMaxGap - obstacleMinGap))) {
spawnObstacle();
}
};
// On game over, allow restart on tap
game.up = function (x, y, obj) {
if (!gameStarted) {
// Wait for LK.showGameOver to reset game
}
};
// Initial state: show "Tap to Start"
gameStarted = false;
scoreTxt.setText('0');
;
// --- Start Screen Overlay ---
var startOverlay = new Container();
var titleText = new Text2("Ninja Jump", {
size: 180,
fill: "#222",
font: "Impact, Arial Black, Tahoma"
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 900;
titleText.alpha = 0.0;
titleText.scaleX = titleText.scaleY = 0.7;
startOverlay.addChild(titleText);
var tapText = new Text2("Başlamak için dokun!", {
size: 100,
fill: "#222",
font: "Impact, Arial Black, Tahoma"
});
tapText.anchor.set(0.5, 0.5);
tapText.x = 2048 / 2;
tapText.y = 1200;
tapText.alpha = 0.0;
tapText.scaleX = tapText.scaleY = 0.7;
startOverlay.addChild(tapText);
game.addChild(startOverlay);
// Animate overlay in
tween(titleText, {
alpha: 1,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(titleText, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.linear
});
}
});
tween(tapText, {
alpha: 1,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 600,
delay: 200,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(tapText, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.linear
});
}
});
// Hide overlay on game start
var oldGameDown = game.down;
game.down = function (x, y, obj) {
if (!gameStarted) {
// Animate overlay out
if (startOverlay && startOverlay.parent) {
tween(titleText, {
alpha: 0,
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 300,
easing: tween.linear
});
tween(tapText, {
alpha: 0,
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 300,
easing: tween.linear,
onFinish: function onFinish() {
if (startOverlay && startOverlay.parent) {
startOverlay.parent.removeChild(startOverlay);
}
}
});
}
// If checkpoint exists, offer to restore
if (checkpointData && checkpointData.level !== undefined) {
restoreCheckpoint();
resetGame(checkpointData.level);
} else {
resetGame(0);
}
ninja.jump();
return;
}
// Only jump if not already jumping
ninja.jump();
};