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