User prompt
When curving bullets set the rotation based on speedX and speedY
User prompt
When curving bullets, first define speedX and speedY variables before applying them to self.x and self.y
User prompt
Add 90 degrees to bullet rotation when curving
User prompt
When curving bullets rotate the bullet to show the direction it's flying in
User prompt
decrease the impact of bullet curve
User prompt
Decrease the impact of bullet curve
User prompt
Only curve bullets on the x axis
User prompt
When collecting a curve bullet powerup, add one to the hero curvebullet variable
User prompt
Change hero.curveBullet to an integer as well
User prompt
Inside the nearestEnemy.enemy check, also subtract self.speed from self.y
User prompt
Decrease the impact of bullet curving
User prompt
Make hero bullet curving an integer, where a larger integer allows the bullet to curve more aggressively towards the enemies
User prompt
parse the information if a bullet should curve into the bullet instance when creating it
User prompt
Make sure powerups have a curvebullet type
User prompt
Fix Bug: 'ReferenceError: Can't find variable: hero' in this line: 'if (hero.curveBullet && enemies.length > 0) {' Line Number: 52
User prompt
Parse the enemies array to hero bullet to make sure the curve code works
User prompt
Add a powerup that makes hero bullets curve towards the nearest enemy a bit
User prompt
Write what wave we are playing at the center of the screen for 2 seconds each time a wave starts
User prompt
set heroBullet to null after destroying it
User prompt
Make sure both heroBullet and enemy exist before doing the intersection check
User prompt
Use Verdana for the poweruplabel font
User prompt
Divide the shield alpha by two
User prompt
Make the hero shield alpha be based on how much shield health you have left
User prompt
When spawning enemy bullets, subtract the Math.PI / 2 rather than adding it
User prompt
Rotate the enemy bullets such that they face the direction they are flying
var Powerup = Container.expand(function (type) {
var self = Container.call(this);
self.type = type;
var powerupGraphics;
switch (type) {
case 'extraBullet':
powerupGraphics = XS.getAsset('extraBulletPowerup', 'Extra Bullet Powerup Graphics', 0.5, 0.5);
break;
case 'shield':
powerupGraphics = XS.getAsset('shieldPowerup', 'Shield Powerup Graphics', 0.5, 0.5);
break;
case 'speed':
powerupGraphics = XS.getAsset('speedPowerup', 'Speed Powerup Graphics', 0.5, 0.5);
break;
case 'health':
powerupGraphics = XS.getAsset('healthPowerup', 'Health Powerup Graphics', 0.5, 0.5);
break;
case 'missileSpeed':
powerupGraphics = XS.getAsset('missileSpeedPowerup', 'Missile Speed Powerup Graphics', 0.5, 0.5);
break;
default:
powerupGraphics = XS.getAsset('powerup', 'Powerup Graphics', 0.5, 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 = XS.getAsset('healthBar', 'Health Bar Graphics', .5, 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) {
var self = Container.call(this);
var bulletGraphics = XS.getAsset('heroBullet', 'Hero Bullet Graphics', 0.5, 0.5);
self.addChild(bulletGraphics);
self.speed = 0;
self.acceleration = 0.2;
self.move = function () {
self.speed += self.acceleration;
self.y -= self.speed;
};
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = XS.getAsset('enemyBullet', 'Enemy Bullet Graphics', 0.5, 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 = XS.getAsset('hero', 'Hero Spaceship', 0.5, 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 = XS.getAsset('shieldEffect', 'Shield Effect Graphics', 0.5, 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);
} else {
self.shieldBar.visible = false;
self.shieldEffect.visible = false;
self.shieldBar.updateHealth(0);
}
};
self.updateShield();
self.hitEffectCounter = 0;
self.shield = 0;
self.fireRate = 30;
self.bulletCount = 1;
self.acceleration = 1;
self.updateHitEffect = function () {
if (self.hitEffectCounter > 0) {
heroGraphics.tint = 0xff0000 + (0xffffff - 0xff0000) * (10 - self.hitEffectCounter) / 10;
self.hitEffectCounter--;
} else {
if (heroGraphics) {
heroGraphics.tint = 0xffffff;
}
}
};
});
var Enemy = Container.expand(function (currentWave) {
var self = Container.call(this);
var enemyGraphics = XS.getAsset('enemy', 'Enemy Spaceship', 0.5, 0.5);
self.addChild(enemyGraphics);
self.speed = 6;
self.health = 50 + 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.updateHitEffect = function () {
if (self.hitEffectCounter > 0) {
enemyGraphics.tint = 0xff0000 + (0xffffff - 0xff0000) * (10 - self.hitEffectCounter) / 10;
self.hitEffectCounter--;
} else {
enemyGraphics.tint = 0xffffff;
}
};
self.move = function () {
if (self.y < self.targetY) {
self.y += self.speed;
}
self.x += Math.sin((XS.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 = XS.getAsset('star', 'Star Graphics', 0.5, 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;
}
};
});
var Game = Container.expand(function () {
var self = Container.call(this);
var background = XS.getAsset('background', 'Background Graphics', 0.5, 1);
background.x = 2048 / 2;
background.y = 2732;
background.alpha = 0.4;
self.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);
self.addChild(star);
}
var hero = self.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"
});
scoreText.anchor.set(0.5, 0);
XS.gui.topCenter.addChild(scoreText);
var powerupLabel = new Text2('', {
size: 64,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
fill: "#ffffff"
});
powerupLabel.anchor.set(0.5, 0);
XS.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);
self.addChild(enemy);
}
allEnemiesKilled = false;
var powerupTypes = ['health', 'speed', 'shield'];
if (hero.bulletCount < 5) {
powerupTypes.push('extraBullet');
}
if (hero.fireRate > 5) {
powerupTypes.push('powerup');
}
powerupTypes.push('missileSpeed');
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);
self.addChild(powerup);
}
}
function fireHeroBullet() {
var angleStep = Math.PI / (hero.bulletCount + 1);
for (var i = 0; i < hero.bulletCount; i++) {
var bullet = new HeroBullet(hero.acceleration);
bullet.x = hero.x + Math.cos((i + 1) * angleStep) * 100;
bullet.y = hero.y - Math.sin((i + 1) * angleStep) * 100;
heroBullets.push(bullet);
self.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);
self.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.intersects(enemy)) {
heroBullet.destroy();
heroBullets.splice(hIndex, 1);
enemy.health -= 10;
enemy.healthBar.updateHealth(enemy.health);
enemy.hitEffectCounter = 10;
if (enemy.health <= 0) {
enemy.destroy();
enemies.splice(eIndex, 1);
score += 100;
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();
} else {
hero.health -= 10;
hero.healthBar.updateHealth(hero.health);
hero.hitEffectCounter = 10;
}
}
}
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;
}
powerupLabel.visible = true;
XS.setTimeout(function () {
powerupLabel.visible = false;
}, 3000);
}
}
}
var targetPosition = {
x: hero.x,
y: hero.y
};
stage.on('down', function (obj) {
targetPosition = obj.event.getLocalPosition(self);
});
stage.on('move', function (obj) {
targetPosition = obj.event.getLocalPosition(self);
});
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) {
XS.showGameOver();
}
if (XS.ticks % Math.floor(hero.fireRate) === 0) {
fireHeroBullet();
}
enemies.forEach(function (enemy, index) {
enemy.updateHitEffect();
if (XS.ticks % 90 === 0) {
fireEnemyBullet(enemy);
}
if (XS.ticks % 180 === 0 && index % 2 === 0) {
fireEnemyBullet(enemy);
}
});
hero.updateHitEffect();
}
XS.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.