/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Bullet: moves from player to horizon
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGfx = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.z = 0; // 0 = at player, 1 = at horizon
self.speed = 0.045;
self.alive = true;
self.type = 'bullet';
self.update = function () {
if (!self.alive) return;
self.z += self.speed;
var horizonY = 700;
var playerY = 2000;
var centerX = 1024;
self.x = centerX;
self.y = horizonY + (playerY - horizonY) * (1 - self.z);
var minScale = 0.18,
maxScale = 0.7;
var scale = minScale + (maxScale - minScale) * (1 - self.z);
self.scaleX = self.scaleY = scale;
bulletGfx.alpha = Math.min(1, 0.3 + 0.7 * (1 - self.z));
};
self.destroyBullet = function () {
self.alive = false;
self.visible = false;
self.destroy();
};
return self;
});
// Enemy approaches from horizon to player
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGfx = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.z = 0; // 0 = at player, 1 = at horizon
self.speed = 0.008 + Math.random() * 0.004; // z per tick
self.alive = true;
self.type = 'enemy';
// For collision, we use .z and .x
self.update = function () {
if (!self.alive) return;
self.z -= self.speed;
// Perspective: as z decreases, enemy appears larger and closer to center
var horizonY = 700;
var playerY = 2000;
var centerX = 1024;
// Lerp position
self.x = centerX;
self.y = horizonY + (playerY - horizonY) * (1 - self.z);
// Lerp scale
// Make the enemy look bigger visually, but keep collision logic unchanged by only scaling the graphics
var minScale = 0.45,
maxScale = 2.0;
var scale = minScale + (maxScale - minScale) * (1 - self.z);
enemyGfx.scaleX = enemyGfx.scaleY = scale;
self.scaleX = self.scaleY = 1; // Keep container scale at 1 for collision
// Fade in as it approaches
enemyGfx.alpha = Math.min(1, 0.3 + 0.7 * (1 - self.z));
};
self.destroyEnemy = function () {
self.alive = false;
self.visible = false;
self.destroy();
};
return self;
});
// Jump effect: quick effect at player
var JumpEffect = Container.expand(function () {
var self = Container.call(this);
var jumpGfx = self.attachAsset('jumpEffect', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = 1024;
self.y = 2000;
self.scaleX = 1.1;
self.scaleY = 1.1;
jumpGfx.alpha = 0.7;
tween(self, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 220,
easing: tween.cubicOut,
onFinish: function onFinish() {
self.destroy();
}
});
return self;
});
// Muzzle flash: quick effect at player
var MuzzleFlash = Container.expand(function () {
var self = Container.call(this);
var muzzleGfx = self.attachAsset('muzzle', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = 1024;
self.y = 1850;
self.scaleX = 1.2;
self.scaleY = 1.2;
muzzleGfx.alpha = 0.8;
// Fade out quickly
tween(self, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 180,
easing: tween.cubicOut,
onFinish: function onFinish() {
self.destroy();
}
});
return self;
});
// Obstacle approaches from horizon to player
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obsGfx = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.z = 0;
self.speed = 0.009 + Math.random() * 0.003;
self.alive = true;
self.type = 'obstacle';
// Random horizontal offset
self.offsetX = (Math.random() - 0.5) * 600;
self.update = function () {
if (!self.alive) return;
self.z -= self.speed;
var horizonY = 700;
var playerY = 2000;
var centerX = 1024;
self.x = centerX + self.offsetX * (1 - self.z);
self.y = horizonY + (playerY - horizonY) * (1 - self.z);
// Make the obstacle look bigger visually, but keep collision logic unchanged by only scaling the graphics
var minScale = 0.38,
maxScale = 2.0;
var scale = minScale + (maxScale - minScale) * (1 - self.z);
obsGfx.scaleX = obsGfx.scaleY = scale;
self.scaleX = self.scaleY = 1; // Keep container scale at 1 for collision
obsGfx.alpha = Math.min(1, 0.3 + 0.7 * (1 - self.z));
};
self.destroyObstacle = function () {
self.alive = false;
self.visible = false;
self.destroy();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181c22
});
/****
* Game Code
****/
// Enemies: green box, Obstacles: gray box, Bullet: yellow ellipse, Muzzle flash: orange ellipse, Jump effect: blue ellipse, Horizon: thin white box
// Play background music
LK.playMusic('bgmusic');
// Horizon line
var horizonLine = LK.getAsset('horizon', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 700
});
game.addChild(horizonLine);
// Crosshair (for visual feedback)
var crosshair = LK.getAsset('crosshair', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2550,
// moved up by 50
// moved to bottom of the screen
scaleX: (60 + 500) / 60 * 2.2,
scaleY: (60 + 500) / 60 * 2.2
});
crosshair.alpha = 1;
game.addChild(crosshair);
// Score text
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Two on-screen buttons: Blue (left), Green (right), small and at the bottom
// Add 'jump' and 'shoot' text labels to left and right sides of the screen
var jumpLabel = new Text2('jump', {
size: 110,
fill: "#fff"
});
jumpLabel.anchor.set(0.5, 1);
jumpLabel.x = 180;
jumpLabel.y = 2630 - 110; // just above the jump button
LK.gui.bottom.addChild(jumpLabel);
var shootLabel = new Text2('shoot', {
size: 110,
fill: "#fff"
});
shootLabel.anchor.set(0.5, 1);
shootLabel.x = 2048 - 180;
shootLabel.y = 2630 - 110; // just above the shoot button
LK.gui.bottom.addChild(shootLabel);
var btnJump = new Container();
var btnJumpBg = LK.getAsset('jumpEffect', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 1.1,
scaleY: 1.1,
color: 0x2196F3 // blue
});
btnJumpBg.alpha = 0.85;
btnJump.addChild(btnJumpBg);
btnJump.x = 180;
btnJump.y = 2630;
btnJump.width = btnJumpBg.width * btnJumpBg.scaleX;
btnJump.height = btnJumpBg.height * btnJumpBg.scaleY;
LK.gui.bottom.addChild(btnJump);
var btnShoot = new Container();
var btnShootBg = LK.getAsset('muzzle', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 1.1,
scaleY: 1.1,
color: 0x43A047 // green
});
btnShootBg.alpha = 0.85;
btnShoot.addChild(btnShootBg);
btnShoot.x = 2048 - 180;
btnShoot.y = 2630;
btnShoot.width = btnShootBg.width * btnShootBg.scaleX;
btnShoot.height = btnShootBg.height * btnShootBg.scaleY;
LK.gui.bottom.addChild(btnShoot);
// Button handlers (re-attach)
btnJump.down = function (x, y, obj) {
if (isJumping || gameOver) return;
isJumping = true;
jumpTicks = 0;
game.addChild(new JumpEffect());
LK.getSound('jump').play();
};
btnShoot.down = function (x, y, obj) {
if (gameOver) return;
shootBullet();
};
// Game state
var enemies = [];
var obstacles = [];
var bullets = [];
var isJumping = false;
var jumpTicks = 0;
var jumpDuration = 38; // ~0.6s
var spawnTick = 0;
var score = 0;
var gameOver = false;
// Helper: reset game state
function resetGame() {
for (var i = enemies.length - 1; i >= 0; i--) {
enemies[i].destroyEnemy();
}
for (var i = obstacles.length - 1; i >= 0; i--) {
obstacles[i].destroyObstacle();
}
for (var i = bullets.length - 1; i >= 0; i--) {
bullets[i].destroyBullet();
}
enemies = [];
obstacles = [];
bullets = [];
isJumping = false;
jumpTicks = 0;
spawnTick = 0;
score = 0;
gameOver = false;
scoreTxt.setText('0');
}
// Button handlers
btnJump.down = function (x, y, obj) {
if (isJumping || gameOver) return;
isJumping = true;
jumpTicks = 0;
game.addChild(new JumpEffect());
LK.getSound('jump').play();
};
btnShoot.down = function (x, y, obj) {
if (gameOver) return;
shootBullet();
};
// Also allow whole right/left screen tap for controls
game.down = function (x, y, obj) {
if (gameOver) return;
if (x < 1024) {
// Anywhere on left: jump
btnJump.down(x, y, obj);
} else if (x >= 1024) {
// Anywhere on right: shoot
btnShoot.down(x, y, obj);
}
};
// Shoot bullet
function shootBullet() {
var b = new Bullet();
b.z = 0;
bullets.push(b);
game.addChild(b);
game.addChild(new MuzzleFlash());
LK.getSound('shoot').play();
}
// Spawn enemy or obstacle
function spawnEntity() {
// 60% enemy, 40% obstacle
if (Math.random() < 0.6) {
var e = new Enemy();
e.z = 1;
enemies.push(e);
game.addChild(e);
} else {
var o = new Obstacle();
o.z = 1;
obstacles.push(o);
game.addChild(o);
}
}
// Main update loop
game.update = function () {
if (gameOver) return;
// Handle jump
if (isJumping) {
jumpTicks++;
// On first jump tick, animate crosshair up
if (jumpTicks === 1) {
// Move crosshair up by 180px (tweak as needed)
tween(crosshair, {
y: 2370
}, {
duration: 120,
easing: tween.cubicOut
});
}
// When jump ends, animate crosshair back to bottom
if (jumpTicks === jumpDuration) {
isJumping = false;
jumpTicks = 0;
tween(crosshair, {
y: 2550
}, {
duration: 120,
easing: tween.cubicIn
});
}
}
// Spawn logic: every 60-90 ticks
spawnTick++;
if (spawnTick > 60 + Math.random() * 30) {
spawnEntity();
spawnTick = 0;
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
e.update();
if (!e.alive) {
enemies.splice(i, 1);
continue;
}
// If enemy reaches player (z <= 0)
if (e.z <= 0.04) {
// If jumping, check if enemy was not shot (still alive)
if (isJumping) {
// If enemy is still alive, player loses (jumped over without shooting)
LK.getSound('hit').play();
LK.effects.flashScreen(0xff0000, 900);
gameOver = true;
LK.showGameOver();
return;
}
// Not jumping: game over
LK.getSound('hit').play();
LK.effects.flashScreen(0xff0000, 900);
gameOver = true;
LK.showGameOver();
return;
}
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var o = obstacles[i];
o.update();
if (!o.alive) {
obstacles.splice(i, 1);
continue;
}
// If obstacle reaches player (z <= 0.04)
if (o.z <= 0.04) {
if (isJumping) {
// Jumped over: score++
LK.getSound('dodge').play();
score++;
scoreTxt.setText(score + '');
o.destroyObstacle();
obstacles.splice(i, 1);
continue;
}
// Not jumping: game over
LK.getSound('hit').play();
LK.effects.flashScreen(0xff0000, 900);
gameOver = true;
LK.showGameOver();
return;
}
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var b = bullets[i];
b.update();
if (!b.alive) {
bullets.splice(i, 1);
continue;
}
// If bullet reaches horizon, remove
if (b.z >= 1) {
b.destroyBullet();
bullets.splice(i, 1);
continue;
}
// Check collision with enemies (z diff < 0.08, x diff < 120)
for (var j = enemies.length - 1; j >= 0; j--) {
var e = enemies[j];
if (!e.alive) continue;
if (Math.abs(b.z - e.z) < 0.08 && Math.abs(b.x - e.x) < 120) {
// Hit!
LK.effects.flashObject(e, 0xffff00, 200);
e.destroyEnemy();
enemies.splice(j, 1);
b.destroyBullet();
bullets.splice(i, 1);
score++;
scoreTxt.setText(score + '');
break;
}
}
}
};
// Reset game state on game over
LK.on('gameover', function () {
resetGame();
});
// Reset game state on win (not used, but for completeness)
LK.on('youwin', function () {
resetGame();
}); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Bullet: moves from player to horizon
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGfx = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.z = 0; // 0 = at player, 1 = at horizon
self.speed = 0.045;
self.alive = true;
self.type = 'bullet';
self.update = function () {
if (!self.alive) return;
self.z += self.speed;
var horizonY = 700;
var playerY = 2000;
var centerX = 1024;
self.x = centerX;
self.y = horizonY + (playerY - horizonY) * (1 - self.z);
var minScale = 0.18,
maxScale = 0.7;
var scale = minScale + (maxScale - minScale) * (1 - self.z);
self.scaleX = self.scaleY = scale;
bulletGfx.alpha = Math.min(1, 0.3 + 0.7 * (1 - self.z));
};
self.destroyBullet = function () {
self.alive = false;
self.visible = false;
self.destroy();
};
return self;
});
// Enemy approaches from horizon to player
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGfx = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.z = 0; // 0 = at player, 1 = at horizon
self.speed = 0.008 + Math.random() * 0.004; // z per tick
self.alive = true;
self.type = 'enemy';
// For collision, we use .z and .x
self.update = function () {
if (!self.alive) return;
self.z -= self.speed;
// Perspective: as z decreases, enemy appears larger and closer to center
var horizonY = 700;
var playerY = 2000;
var centerX = 1024;
// Lerp position
self.x = centerX;
self.y = horizonY + (playerY - horizonY) * (1 - self.z);
// Lerp scale
// Make the enemy look bigger visually, but keep collision logic unchanged by only scaling the graphics
var minScale = 0.45,
maxScale = 2.0;
var scale = minScale + (maxScale - minScale) * (1 - self.z);
enemyGfx.scaleX = enemyGfx.scaleY = scale;
self.scaleX = self.scaleY = 1; // Keep container scale at 1 for collision
// Fade in as it approaches
enemyGfx.alpha = Math.min(1, 0.3 + 0.7 * (1 - self.z));
};
self.destroyEnemy = function () {
self.alive = false;
self.visible = false;
self.destroy();
};
return self;
});
// Jump effect: quick effect at player
var JumpEffect = Container.expand(function () {
var self = Container.call(this);
var jumpGfx = self.attachAsset('jumpEffect', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = 1024;
self.y = 2000;
self.scaleX = 1.1;
self.scaleY = 1.1;
jumpGfx.alpha = 0.7;
tween(self, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 220,
easing: tween.cubicOut,
onFinish: function onFinish() {
self.destroy();
}
});
return self;
});
// Muzzle flash: quick effect at player
var MuzzleFlash = Container.expand(function () {
var self = Container.call(this);
var muzzleGfx = self.attachAsset('muzzle', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = 1024;
self.y = 1850;
self.scaleX = 1.2;
self.scaleY = 1.2;
muzzleGfx.alpha = 0.8;
// Fade out quickly
tween(self, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 180,
easing: tween.cubicOut,
onFinish: function onFinish() {
self.destroy();
}
});
return self;
});
// Obstacle approaches from horizon to player
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obsGfx = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.z = 0;
self.speed = 0.009 + Math.random() * 0.003;
self.alive = true;
self.type = 'obstacle';
// Random horizontal offset
self.offsetX = (Math.random() - 0.5) * 600;
self.update = function () {
if (!self.alive) return;
self.z -= self.speed;
var horizonY = 700;
var playerY = 2000;
var centerX = 1024;
self.x = centerX + self.offsetX * (1 - self.z);
self.y = horizonY + (playerY - horizonY) * (1 - self.z);
// Make the obstacle look bigger visually, but keep collision logic unchanged by only scaling the graphics
var minScale = 0.38,
maxScale = 2.0;
var scale = minScale + (maxScale - minScale) * (1 - self.z);
obsGfx.scaleX = obsGfx.scaleY = scale;
self.scaleX = self.scaleY = 1; // Keep container scale at 1 for collision
obsGfx.alpha = Math.min(1, 0.3 + 0.7 * (1 - self.z));
};
self.destroyObstacle = function () {
self.alive = false;
self.visible = false;
self.destroy();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181c22
});
/****
* Game Code
****/
// Enemies: green box, Obstacles: gray box, Bullet: yellow ellipse, Muzzle flash: orange ellipse, Jump effect: blue ellipse, Horizon: thin white box
// Play background music
LK.playMusic('bgmusic');
// Horizon line
var horizonLine = LK.getAsset('horizon', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 700
});
game.addChild(horizonLine);
// Crosshair (for visual feedback)
var crosshair = LK.getAsset('crosshair', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2550,
// moved up by 50
// moved to bottom of the screen
scaleX: (60 + 500) / 60 * 2.2,
scaleY: (60 + 500) / 60 * 2.2
});
crosshair.alpha = 1;
game.addChild(crosshair);
// Score text
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Two on-screen buttons: Blue (left), Green (right), small and at the bottom
// Add 'jump' and 'shoot' text labels to left and right sides of the screen
var jumpLabel = new Text2('jump', {
size: 110,
fill: "#fff"
});
jumpLabel.anchor.set(0.5, 1);
jumpLabel.x = 180;
jumpLabel.y = 2630 - 110; // just above the jump button
LK.gui.bottom.addChild(jumpLabel);
var shootLabel = new Text2('shoot', {
size: 110,
fill: "#fff"
});
shootLabel.anchor.set(0.5, 1);
shootLabel.x = 2048 - 180;
shootLabel.y = 2630 - 110; // just above the shoot button
LK.gui.bottom.addChild(shootLabel);
var btnJump = new Container();
var btnJumpBg = LK.getAsset('jumpEffect', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 1.1,
scaleY: 1.1,
color: 0x2196F3 // blue
});
btnJumpBg.alpha = 0.85;
btnJump.addChild(btnJumpBg);
btnJump.x = 180;
btnJump.y = 2630;
btnJump.width = btnJumpBg.width * btnJumpBg.scaleX;
btnJump.height = btnJumpBg.height * btnJumpBg.scaleY;
LK.gui.bottom.addChild(btnJump);
var btnShoot = new Container();
var btnShootBg = LK.getAsset('muzzle', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 1.1,
scaleY: 1.1,
color: 0x43A047 // green
});
btnShootBg.alpha = 0.85;
btnShoot.addChild(btnShootBg);
btnShoot.x = 2048 - 180;
btnShoot.y = 2630;
btnShoot.width = btnShootBg.width * btnShootBg.scaleX;
btnShoot.height = btnShootBg.height * btnShootBg.scaleY;
LK.gui.bottom.addChild(btnShoot);
// Button handlers (re-attach)
btnJump.down = function (x, y, obj) {
if (isJumping || gameOver) return;
isJumping = true;
jumpTicks = 0;
game.addChild(new JumpEffect());
LK.getSound('jump').play();
};
btnShoot.down = function (x, y, obj) {
if (gameOver) return;
shootBullet();
};
// Game state
var enemies = [];
var obstacles = [];
var bullets = [];
var isJumping = false;
var jumpTicks = 0;
var jumpDuration = 38; // ~0.6s
var spawnTick = 0;
var score = 0;
var gameOver = false;
// Helper: reset game state
function resetGame() {
for (var i = enemies.length - 1; i >= 0; i--) {
enemies[i].destroyEnemy();
}
for (var i = obstacles.length - 1; i >= 0; i--) {
obstacles[i].destroyObstacle();
}
for (var i = bullets.length - 1; i >= 0; i--) {
bullets[i].destroyBullet();
}
enemies = [];
obstacles = [];
bullets = [];
isJumping = false;
jumpTicks = 0;
spawnTick = 0;
score = 0;
gameOver = false;
scoreTxt.setText('0');
}
// Button handlers
btnJump.down = function (x, y, obj) {
if (isJumping || gameOver) return;
isJumping = true;
jumpTicks = 0;
game.addChild(new JumpEffect());
LK.getSound('jump').play();
};
btnShoot.down = function (x, y, obj) {
if (gameOver) return;
shootBullet();
};
// Also allow whole right/left screen tap for controls
game.down = function (x, y, obj) {
if (gameOver) return;
if (x < 1024) {
// Anywhere on left: jump
btnJump.down(x, y, obj);
} else if (x >= 1024) {
// Anywhere on right: shoot
btnShoot.down(x, y, obj);
}
};
// Shoot bullet
function shootBullet() {
var b = new Bullet();
b.z = 0;
bullets.push(b);
game.addChild(b);
game.addChild(new MuzzleFlash());
LK.getSound('shoot').play();
}
// Spawn enemy or obstacle
function spawnEntity() {
// 60% enemy, 40% obstacle
if (Math.random() < 0.6) {
var e = new Enemy();
e.z = 1;
enemies.push(e);
game.addChild(e);
} else {
var o = new Obstacle();
o.z = 1;
obstacles.push(o);
game.addChild(o);
}
}
// Main update loop
game.update = function () {
if (gameOver) return;
// Handle jump
if (isJumping) {
jumpTicks++;
// On first jump tick, animate crosshair up
if (jumpTicks === 1) {
// Move crosshair up by 180px (tweak as needed)
tween(crosshair, {
y: 2370
}, {
duration: 120,
easing: tween.cubicOut
});
}
// When jump ends, animate crosshair back to bottom
if (jumpTicks === jumpDuration) {
isJumping = false;
jumpTicks = 0;
tween(crosshair, {
y: 2550
}, {
duration: 120,
easing: tween.cubicIn
});
}
}
// Spawn logic: every 60-90 ticks
spawnTick++;
if (spawnTick > 60 + Math.random() * 30) {
spawnEntity();
spawnTick = 0;
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
e.update();
if (!e.alive) {
enemies.splice(i, 1);
continue;
}
// If enemy reaches player (z <= 0)
if (e.z <= 0.04) {
// If jumping, check if enemy was not shot (still alive)
if (isJumping) {
// If enemy is still alive, player loses (jumped over without shooting)
LK.getSound('hit').play();
LK.effects.flashScreen(0xff0000, 900);
gameOver = true;
LK.showGameOver();
return;
}
// Not jumping: game over
LK.getSound('hit').play();
LK.effects.flashScreen(0xff0000, 900);
gameOver = true;
LK.showGameOver();
return;
}
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var o = obstacles[i];
o.update();
if (!o.alive) {
obstacles.splice(i, 1);
continue;
}
// If obstacle reaches player (z <= 0.04)
if (o.z <= 0.04) {
if (isJumping) {
// Jumped over: score++
LK.getSound('dodge').play();
score++;
scoreTxt.setText(score + '');
o.destroyObstacle();
obstacles.splice(i, 1);
continue;
}
// Not jumping: game over
LK.getSound('hit').play();
LK.effects.flashScreen(0xff0000, 900);
gameOver = true;
LK.showGameOver();
return;
}
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var b = bullets[i];
b.update();
if (!b.alive) {
bullets.splice(i, 1);
continue;
}
// If bullet reaches horizon, remove
if (b.z >= 1) {
b.destroyBullet();
bullets.splice(i, 1);
continue;
}
// Check collision with enemies (z diff < 0.08, x diff < 120)
for (var j = enemies.length - 1; j >= 0; j--) {
var e = enemies[j];
if (!e.alive) continue;
if (Math.abs(b.z - e.z) < 0.08 && Math.abs(b.x - e.x) < 120) {
// Hit!
LK.effects.flashObject(e, 0xffff00, 200);
e.destroyEnemy();
enemies.splice(j, 1);
b.destroyBullet();
bullets.splice(i, 1);
score++;
scoreTxt.setText(score + '');
break;
}
}
}
};
// Reset game state on game over
LK.on('gameover', function () {
resetGame();
});
// Reset game state on win (not used, but for completeness)
LK.on('youwin', function () {
resetGame();
});
Make a pile of rocks with a grass patch in front of it and dirt scattered. In-Game asset. 2d. High contrast. No shadows
Bullet. In-Game asset. 2d. High contrast. No shadows
Bullet target. In-Game asset. 2d. High contrast. No shadows
A shotgun with a first person view of somebody holding it. In-Game asset. 2d. High contrast. No shadows