/**** * 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();
};