/****
* Classes
****/
var Powerup = Container.expand(function (type) {
var self = Container.call(this);
self.type = type;
var powerupGraphics;
switch (type) {
case 'extraBullet':
powerupGraphics = LK.getAsset('extraBulletPowerup', {
anchorX: 0.5,
anchorY: 0.5
});
break;
case 'shield':
powerupGraphics = LK.getAsset('shieldPowerup', {
anchorX: 0.5,
anchorY: 0.5
});
break;
case 'speed':
powerupGraphics = LK.getAsset('speedPowerup', {
anchorX: 0.5,
anchorY: 0.5
});
break;
case 'health':
powerupGraphics = LK.getAsset('healthPowerup', {
anchorX: 0.5,
anchorY: 0.5
});
break;
case 'missileSpeed':
powerupGraphics = LK.getAsset('missileSpeedPowerup', {
anchorX: 0.5,
anchorY: 0.5
});
break;
case 'curveBullet':
powerupGraphics = LK.getAsset('curveBulletPowerup', {
anchorX: 0.5,
anchorY: 0.5
});
break;
case 'scoreMultiplier':
powerupGraphics = LK.getAsset('scoreMultiplierPowerup', {
anchorX: 0.5,
anchorY: 0.5
});
break;
default:
powerupGraphics = LK.getAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
break;
}
self.addChild(powerupGraphics);
self.speed = 3;
self.move = function () {
self.y += self.speed;
};
});
var HealthBar = Container.expand(function (maxHealth, color) {
var self = Container.call(this);
var barGraphics = LK.getAsset('healthBar', {
anchorX: 0.5,
anchorY: 1
});
barGraphics.tint = color;
self.addChild(barGraphics);
self.maxHealth = maxHealth;
self.currentHealth = maxHealth;
self.updateHealth = function (newHealth) {
self.currentHealth = newHealth;
barGraphics.scale.x = self.currentHealth / self.maxHealth;
};
self.intersectable = false;
});
var HeroBullet = Container.expand(function (acceleration, enemies, curveBullet) {
var self = Container.call(this);
var bulletGraphics = LK.getAsset('heroBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.addChild(bulletGraphics);
self.speed = 10;
self.acceleration = 0.2;
self.curveBullet = curveBullet || 0;
self.move = function () {
self.speed += self.acceleration;
var speedX = 0;
var speedY = -self.speed;
if (self.curveBullet > 0 && enemies.length > 0) {
var nearestEnemy = enemies.reduce(function (nearest, enemy) {
var dx = self.x - enemy.x;
var dy = self.y - enemy.y;
var distance = Math.sqrt(dx * dx + dy * dy);
return distance < nearest.distance ? {
enemy: enemy,
distance: distance
} : nearest;
}, {
enemy: null,
distance: Infinity
});
if (nearestEnemy.enemy) {
var angle = Math.atan2(nearestEnemy.enemy.y - self.y, nearestEnemy.enemy.x - self.x);
speedX = self.speed * Math.cos(angle) * self.curveBullet * 0.1;
speedY = -self.speed;
self.rotation = Math.atan2(speedY, speedX) + Math.PI / 2;
}
}
self.x += speedX;
self.y += speedY;
};
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = LK.getAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
bulletGraphics.rotation = Math.PI;
self.addChild(bulletGraphics);
self.speed = 5;
self.move = function () {
self.x += self.speedX;
self.y += self.speedY;
};
});
var Hero = Container.expand(function () {
var self = Container.call(this);
var heroGraphics = LK.getAsset('hero', {
anchorX: 0.5,
anchorY: 0.5
});
self.addChild(heroGraphics);
self.health = 100;
self.healthBar = self.addChild(new HealthBar(100, 0x00ff00));
self.healthBar.y = -heroGraphics.height / 2 - 50;
self.healthBar.updateHealth(self.health);
self.shieldBar = self.addChild(new HealthBar(10, 0x4682B4));
self.shieldBar.y = self.healthBar.y - 30;
self.shieldBar.visible = false;
self.shieldEffect = LK.getAsset('shieldEffect', {
anchorX: 0.5,
anchorY: 0.5
});
self.shieldEffect.visible = false;
self.shieldEffect.alpha = 0.5;
self.addChildAt(self.shieldEffect, 1);
self.updateShield = function () {
if (self.shield > 0) {
self.shieldBar.visible = true;
self.shieldEffect.visible = true;
self.shieldBar.updateHealth(self.shield);
self.shieldEffect.alpha = self.shield / 10 / 2;
} else {
self.shieldBar.visible = false;
self.shieldEffect.visible = false;
self.shieldBar.updateHealth(0);
}
};
self.updateShield();
self.hitEffectCounter = 0;
self.curveBullet = 0;
self.shield = 0;
self.fireRate = 30;
self.bulletCount = 1;
self.acceleration = 1;
self.scoreMultiplier = 1;
});
var Enemy = Container.expand(function (currentWave) {
var self = Container.call(this);
var enemyGraphics = LK.getAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.addChild(enemyGraphics);
self.speed = 6;
self.health = 30 + currentWave * 10;
self.targetY = Math.random() * (2732 / 3) + enemyGraphics.height;
self.sidewaysOffset = Math.random() * 60;
self.healthBar = self.addChild(new HealthBar(self.health, 0xff0000));
self.healthBar.y = -enemyGraphics.height / 2 - 50;
self.healthBar.updateHealth(self.health);
self.hitEffectCounter = 0;
self.tickOffset = Math.floor(Math.random() * 90);
self.move = function () {
if (self.y < self.targetY) {
self.y += self.speed;
}
self.x += Math.sin((LK.ticks + self.sidewaysOffset) / 30) * 5;
if (self.x < 0) {
self.x = 0;
}
if (self.x > 2048 - enemyGraphics.width) {
self.x = 2048 - enemyGraphics.width;
}
};
});
var StarField = Container.expand(function () {
var self = Container.call(this);
var starGraphics = LK.getAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
self.addChild(starGraphics);
self.speed = (Math.random() * 2 + 1) * 0.5;
self.alpha = self.speed / 2;
self.move = function () {
self.y += self.speed;
if (self.y > 2732) {
self.y = -100;
self.x = Math.random() * 2048;
self.speed = Math.random() * 2 + 1;
self.alpha = self.speed / 3;
}
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x170615
});
/****
* Game Code
****/
var background = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 1
});
background.x = 2048 / 2;
background.y = 2732;
background.alpha = 0.4;
game.addChild(background);
var starField = [];
for (var i = 0; i < 100; i++) {
var star = new StarField();
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
starField.push(star);
game.addChild(star);
}
var hero = game.addChild(new Hero());
hero.x = 1024;
hero.y = 2400;
var enemies = [];
var heroBullets = [];
var enemyBullets = [];
var powerups = [];
var score = 0;
var currentWave = 0;
var allEnemiesKilled = true;
var scoreText = new Text2('0', {
size: 100,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
fill: "#ffffff",
defaultFont: "'Arial', sans-serif"
});
scoreText.anchor.set(0.5, 0);
LK.gui.topCenter.addChild(scoreText);
var powerupLabel = new Text2('', {
size: 64,
font: "Verdana",
fill: "#ffffff"
});
powerupLabel.anchor.set(0.5, 0);
LK.gui.topCenter.addChild(powerupLabel);
powerupLabel.y = scoreText.height + 10;
powerupLabel.visible = false;
function spawnWave() {
for (var i = 0; i < 5; i++) {
var enemy = new Enemy(currentWave);
enemy.x = Math.random() * 2048;
enemy.y = -100 - i * 100;
enemies.push(enemy);
game.addChild(enemy);
}
allEnemiesKilled = false;
var powerupTypes = ['health', 'speed', 'shield'];
if (hero.bulletCount < 5) {
powerupTypes.push('extraBullet');
}
if (hero.fireRate > 20) {
powerupTypes.push('powerup');
}
powerupTypes.push('missileSpeed', 'curveBullet', 'scoreMultiplier');
for (var i = 0; i < 3; i++) {
var powerupType = powerupTypes[Math.floor(Math.random() * powerupTypes.length)];
var powerup = new Powerup(powerupType);
powerup.x = (i + 1) * 2048 / 4;
powerup.y = -100;
powerups.push(powerup);
game.addChild(powerup);
}
var waveText = new Text2('Wave ' + currentWave, {
size: 200,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
fill: "#ffffff"
});
waveText.anchor.set(0.5, 0.5);
waveText.x = 2048 / 2;
waveText.y = 2732 / 2;
game.addChild(waveText);
LK.setTimeout(function () {
waveText.destroy();
}, 2000);
}
function fireHeroBullet(enemies, curveBullet) {
var angleStep = Math.PI / (hero.bulletCount + 1);
for (var i = 0; i < hero.bulletCount; i++) {
var bullet = new HeroBullet(hero.acceleration, enemies, curveBullet);
bullet.x = hero.x + Math.cos((i + 1) * angleStep) * 100;
bullet.y = hero.y - Math.sin((i + 1) * angleStep) * 100;
heroBullets.push(bullet);
game.addChild(bullet);
}
}
function fireEnemyBullet(enemy) {
var bullet = new EnemyBullet();
bullet.x = enemy.x;
bullet.y = enemy.y + 50;
var angle = Math.atan2(hero.y - bullet.y, hero.x - bullet.x);
bullet.speedX = bullet.speed * Math.cos(angle);
bullet.speedY = bullet.speed * Math.sin(angle);
bullet.rotation = angle - Math.PI / 2;
enemyBullets.push(bullet);
game.addChild(bullet);
}
function updateGameObjects() {
enemies.forEach(function (enemy, index) {
enemy.move();
});
for (var index = heroBullets.length - 1; index >= 0; index--) {
var bullet = heroBullets[index];
bullet.move();
if (bullet.y < 0) {
bullet.destroy();
heroBullets.splice(index, 1);
}
}
for (var index = enemyBullets.length - 1; index >= 0; index--) {
var bullet = enemyBullets[index];
bullet.move();
if (bullet.y > 2732 || bullet.x < 0 || bullet.x > 2048) {
bullet.destroy();
enemyBullets.splice(index, 1);
}
}
for (var index = powerups.length - 1; index >= 0; index--) {
var powerup = powerups[index];
powerup.move();
if (powerup.y > 2732) {
powerup.destroy();
powerups.splice(index, 1);
}
}
}
function checkCollisions() {
for (var hIndex = heroBullets.length - 1; hIndex >= 0; hIndex--) {
var heroBullet = heroBullets[hIndex];
for (var eIndex = enemies.length - 1; eIndex >= 0; eIndex--) {
var enemy = enemies[eIndex];
if (heroBullet && enemy && heroBullet.intersects(enemy)) {
heroBullet.destroy();
heroBullets.splice(hIndex, 1);
heroBullet = null;
enemy.health -= 10;
enemy.healthBar.updateHealth(enemy.health);
enemy.hitEffectCounter = 10;
LK.effects.flashObject(enemy, 0xff0000, 1000);
if (enemy.health <= 0) {
enemy.destroy();
enemies.splice(eIndex, 1);
score += Math.floor(100 * hero.scoreMultiplier);
LK.setScore(score);
scoreText.setText(score);
if (enemies.length === 0) {
allEnemiesKilled = true;
}
}
}
}
}
for (var index = enemyBullets.length - 1; index >= 0; index--) {
var enemyBullet = enemyBullets[index];
if (enemyBullet.intersects(hero)) {
enemyBullet.destroy();
enemyBullets.splice(index, 1);
if (hero.shield > 0) {
hero.shield--;
hero.updateShield();
LK.effects.flashObject(hero.shieldEffect, 0xff0000, 1000);
} else {
hero.health -= 10;
hero.healthBar.updateHealth(hero.health);
hero.hitEffectCounter = 10;
LK.effects.flashObject(hero, 0xff0000, 1000);
}
}
}
for (var index = powerups.length - 1; index >= 0; index--) {
var powerup = powerups[index];
if (powerup && powerup.intersects(hero)) {
for (var i = powerups.length - 1; i >= 0; i--) {
powerups[i].destroy();
}
powerups = [];
switch (powerup.type) {
case 'powerup':
hero.fireRate = Math.max(5, hero.fireRate * 0.9);
powerupLabel.setText('+10% Rate of Fire');
break;
case 'health':
hero.health = 100;
hero.healthBar.updateHealth(hero.health);
powerupLabel.setText('Health restored');
break;
case 'speed':
hero.speed *= 1.1;
powerupLabel.setText('+10% Speed');
break;
case 'shield':
hero.shield = 10;
hero.updateShield();
powerupLabel.setText('Shield');
break;
case 'extraBullet':
hero.bulletCount++;
powerupLabel.setText('Extra Bullet');
break;
case 'missileSpeed':
hero.acceleration *= 1.1;
powerupLabel.setText('Missile Speed +10%');
break;
case 'curveBullet':
hero.curveBullet += 1;
powerupLabel.setText('Enhancing Bullet Homing');
break;
case 'scoreMultiplier':
hero.scoreMultiplier += 0.1;
powerupLabel.setText('Score Multiplier +10%');
break;
}
powerupLabel.visible = true;
LK.setTimeout(function () {
powerupLabel.visible = false;
}, 3000);
}
}
}
var targetPosition = {
x: hero.x,
y: hero.y
};
game.on('down', function (obj) {
targetPosition = obj.event.getLocalPosition(game);
});
game.on('move', function (obj) {
targetPosition = obj.event.getLocalPosition(game);
});
function moveHeroTowardsTarget() {
var dx = targetPosition.x - hero.x;
var dy = targetPosition.y - hero.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var maxSpeed = 15;
if (distance > maxSpeed) {
var angle = Math.atan2(dy, dx);
hero.x += maxSpeed * Math.cos(angle);
hero.y += maxSpeed * Math.sin(angle);
} else {
hero.x = targetPosition.x;
hero.y = targetPosition.y;
}
}
function handleTick() {
background.y += 0.5;
if (background.y >= background.height) {
background.y = 2732;
}
moveHeroTowardsTarget();
updateGameObjects();
checkCollisions();
starField.forEach(function (star) {
star.move();
});
if (allEnemiesKilled) {
currentWave++;
spawnWave();
}
if (hero.health <= 0) {
LK.showGameOver();
}
if (LK.ticks % Math.floor(hero.fireRate) === 0) {
fireHeroBullet(enemies, hero.curveBullet);
heroBullets.forEach(function (bullet) {
game.addChildAt(bullet, game.getChildIndex(hero));
});
}
enemies.forEach(function (enemy, index) {
if ((LK.ticks + enemy.tickOffset) % Math.max(60, 180 - currentWave * 5) === 0) {
fireEnemyBullet(enemy);
}
});
}
LK.on('tick', handleTick);
Round powerup. Shield icon Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
Extra missile powerup circle. Missile and plus sign. Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
Single space torpedo flying upwards Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
Background galaxy nebulas and galaxies Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast. --ar 1:10
Round powerup. Green health icon Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
Blue glowing powerup circle with s in center Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
Round powerup. Lightning icon pointing up. Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
Stylish hero spaceship facing upwards, with a single cannon in the center. Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
single alien enemy spaceship facing down, looking like space alien adopted to living in space. Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
Single enemy slime bullet, seen from above facing upwards. Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
Round powerup icon with bullseye Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
Clean plasma bubble Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.