User prompt
Move wave information to bottom center
User prompt
Do not add one to wave count when updating text
User prompt
Move waveDisplay.setText to before we increment wave count
User prompt
Decrease wave text to 40px
User prompt
Add wave counter to top center, make font Tahoma and add drop shadow. Also center texg
User prompt
Write which wave we are at
User prompt
Make hero move 2x as fast
User prompt
Also move up the explosion by 150px when a hero bullet hit an enemy
User prompt
When a hero bullet explode, create the explosion 150px higher up
User prompt
Increase bomb damage radius from 50 to 100
User prompt
In spawnNextWave remove all enemy bullets and enemy bullet indicators
User prompt
Make hero shoot twice as fast
User prompt
In enemyBulletMove don't allow bullets to hit hero if allEnemiesKilled is true
User prompt
Set wave count to 2 on startup and make the first all to spawnEnemies be 1
User prompt
Spawn one enemy when the game starts, then 2 in next round 3 in the subsequent etc
User prompt
Make the distance where enemy bullets are destroyed 25
User prompt
In sortGameObjects at the bottom loop over all children, if a child is an instance of EnemyBulletIndicator set the child index to 1
User prompt
In EnemyBulletIndicator remove the code that sets alpha to .5
User prompt
set indicator alpha to percentCompleted in bullet move
User prompt
Change scale logic from 1 + 2 * percentCompleted to 3 - 2 * percentCompleted
User prompt
Scale bullet target such that it's large when bullet is just fired and small when it's about to hit the target
User prompt
In EnemyBullet move method, set scale of indicator such that it's 300% when bullet is just fired and 100% when bullet hits the target
User prompt
When firing an enemy bullet create an indicator that shows where the bullet is going to hit
User prompt
Add a new class in the game, which we will use later to indicate where an enemy bullet is going to hit
User prompt
Update bullet graphics y code to be bulletGraphics.y = -150* percentCompleted - 200 * Math.sin(Math.PI * percentCompleted);
var EnemyBulletIndicator = Container.expand(function () { var self = Container.call(this); var indicatorGraphics = self.createAsset('enemyBulletIndicator', 'Enemy Bullet Indicator', .5, .5); }); var EnemyBulletIndicator = Container.expand(function () { var self = Container.call(this); var indicatorGraphics = self.createAsset('enemyBulletIndicator', 'Enemy Bullet Indicator', .5, .5); indicatorGraphics.alpha = 0.5; }); var Obstacle = Container.expand(function () { var self = Container.call(this); var obstacleGraphics = self.createAsset('obstacle', 'Obstacle', .5, 1); obstacleGraphics.y += 50; }); var ExitDoor = Container.expand(function () { var self = Container.call(this); var backgroundElement = self.createAsset('backgroundElement1', 'Background Element 1', .5, .5); backgroundElement.y -= 760; var backgroundElement2 = self.createAsset('backgroundElement2', 'Background Element 2', .5, .5); backgroundElement2.y -= 760; backgroundElement2.blendMode = 1; var doorGraphics = self.createAsset('exitDoor', 'Exit Door', .5, 1); self.rotationSpeed1 = 0.005 * 0.25; self.rotationSpeed2 = 0.007 * 0.25; self.rotate = function () { backgroundElement.rotation += self.rotationSpeed1; backgroundElement2.rotation -= self.rotationSpeed2; }; }); var EnemySpawnIndicator = Container.expand(function () { var self = Container.call(this); var spawnIndicatorGraphics = self.createAsset('spawnIndicator', 'Enemy Spawn Indicator', .5, .5); spawnIndicatorGraphics.alpha = 0.5; }); var ExplosionParticle = Container.expand(function () { var self = Container.call(this); var particleGraphics = self.createAsset('particle', 'Explosion Particle', .5, .5); particleGraphics.blendMode = 1; self.dx = (Math.random() - 0.5) * 10; self.dy = (Math.random() - 0.5) * 7; self.move = function () { self.setPosition(self.x + self.dx, self.y + self.dy); self.alpha -= 0.02; particleGraphics.scale.set(particleGraphics.scale.x * 0.98, particleGraphics.scale.y * 0.98); self.dx *= 0.98; self.dy *= 0.98; if (self.alpha <= 0) { self.destroy(); } }; }); var HealthBar = Container.expand(function () { var self = Container.call(this); var healthBarGraphics = self.createAsset('healthBar', 'Health Bar', .5, 1); self.setTint = function (tint) { healthBarGraphics.tint = tint; }; self.setTint(0x00FF00); self.updateHealth = function (health) { self.scale.set(health / 100, 1); }; }); var TargetIndicator = Container.expand(function () { var self = Container.call(this); var targetGraphics = self.createAsset('target', 'Target Indicator', .5, .5); targetGraphics.alpha = 0.5; targetGraphics.y -= 30; }); var Player = Container.expand(function () { var self = Container.call(this); self.health = 100; self.findNearestEnemy = function (enemies) { var nearestEnemy = null; var nearestDistance = Infinity; for (var i = 0; i < enemies.length; i++) { var dx = enemies[i].x - self.x; var dy = enemies[i].y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < nearestDistance && !self.parent.lineIntersectsObstacle(self.x, self.y, enemies[i].x, enemies[i].y)) { nearestDistance = distance; nearestEnemy = enemies[i]; } } return nearestEnemy; }; var playerShadow = self.createAsset('playerShadow', 'Player shadow', .5, .8); playerShadow.alpha = 0.3; var playerAsset = self.createAsset('player', 'Player character', .5, 1); var healthBar = new HealthBar(); self.addChild(healthBar).y = -self.children[1].height; self.healthBar = healthBar; self.targetX = 2048 / 2; self.targetY = 2732 / 2; self.speed = 10; self.lastShot = 0; self.move = function (obstacles) { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > self.speed) { self.setPosition(self.x + dx / distance * self.speed, self.y + dy / distance * self.speed); for (var i = 0; i < obstacles.length; i++) { var dx = obstacles[i].x - self.x; var dy = obstacles[i].y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < obstacles[i].width / 2) { self.x -= dx / distance * 10; self.y -= dy / distance * 10; } } self.healthBar.updateHealth(self.health); return true; } self.healthBar.updateHealth(self.health); return false; }; self.setTarget = function (x, y) { self.targetX = x; self.targetY = y; }; self.shoot = function (enemies) { var nearestEnemy = self.findNearestEnemy(enemies); if (nearestEnemy) { var bullet = new PlayerBullet(); bullet.x = self.x; bullet.y = self.y; var dx = nearestEnemy.x - self.x; var dy = nearestEnemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); bullet.dx = dx / distance; bullet.dy = dy / distance; return bullet; } return null; }; self.flashRed = function () { XS.effects.flashObject(playerAsset, 0xFF0000, 1000); }; }); var Enemy = Container.expand(function () { var self = Container.call(this); self.throwProjectile = function (player) { if (!self.parent.lineIntersectsObstacle(self.x, self.y, player.x, player.y)) { var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); var projectile = new EnemyBullet(); projectile.x = self.x; projectile.y = self.y; projectile.originX = self.x; projectile.originY = self.y; projectile.targetX = player.x; projectile.targetY = player.y; projectile.dx = dx / distance; projectile.dy = dy / distance; return projectile; } return null; }; self.moveTowardsPlayer = function (player) { if (!self.parent.lineIntersectsObstacle(self.x, self.y, player.x, player.y)) { var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 800) { self.dx += dx / distance * 0.3; self.dy += dy / distance * 0.3; return true; } } return false; }; ; self.alpha = 0; self.lastProjectile = 0; self.dx = 0; self.dy = 0; self.health = 100; self.animateIn = function () { self.fadeInTicks = 50; }; var enemyShadow = self.createAsset('enemyShadow', 'Enemy shadow', .5, .8); enemyShadow.alpha = 0.3; var enemyGraphics = self.createAsset('enemy', 'Enemy character', .5, 1); var healthBar = new HealthBar(); healthBar.setTint(0xFF0000); healthBar.y = -enemyGraphics.height; self.addChild(healthBar); self.healthBar = healthBar; self.healthBar.updateHealth(self.health); self.move = function (obstacles, player) { var movedTowardsPlayer = true; if (self.fadeInTicks > 0) { self.alpha += 0.02; self.fadeInTicks--; } else { movedTowardsPlayer = self.moveTowardsPlayer(player); } self.setPosition(self.x + self.dx, self.y + self.dy); self.dx *= 0.80; self.dy *= 0.80; if (self.x < 150 || self.x > 2048 - 150 || self.y < 700 || self.y > 2732 - 150) { self.x = Math.max(Math.min(self.x, 2048 - 150), 150); self.y = Math.max(Math.min(self.y, 2732 - 150), 700); } for (var i = 0; i < obstacles.length; i++) { var dx = obstacles[i].x - self.x; var dy = obstacles[i].y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < obstacles[i].width / 2) { self.x -= dx / distance * 10; self.y -= dy / distance * 10; } } return movedTowardsPlayer; }; self.flashRed = function () { XS.effects.flashObject(enemyGraphics, 0xFF0000, 1000); }; }); var PlayerBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.createAsset('bullet', 'Bullet', .5, .5); bulletGraphics.y -= 150; bulletGraphics.blendMode = 1; self.dx = 0; self.dy = 0; self.move = function () { self.dx *= 1.02; self.dy *= 1.02; self.setPosition(self.x + self.dx * 4, self.y + self.dy * 4); if (self.x < 150 || self.x > 2048 - 150 || self.y < 700 || self.y > 2732 - 150) { return true; } return false; }; }); var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.createAsset('enemyBullet', 'Enemy Bullet', .5, .5); bulletGraphics.y -= 150; self.dx = 0; self.dy = 0; self.originX = 0; self.originY = 0; self.move = function () { self.setPosition(self.x + self.dx * 2.8, self.y + self.dy * 2.8); bulletGraphics.rotation += 0.1; var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); var totalDistance = Math.sqrt(Math.pow(self.targetX - self.originX, 2) + Math.pow(self.targetY - self.originY, 2)); var percentCompleted = distance / totalDistance; bulletGraphics.y = -150 * percentCompleted - 200 * Math.sin(Math.PI * percentCompleted); if (!self.indicator) { self.indicator = new EnemyBulletIndicator(); self.indicator.setPosition(self.targetX, self.targetY); self.parent.addChild(self.indicator); } var totalDistance = Math.sqrt(Math.pow(self.targetX - self.originX, 2) + Math.pow(self.targetY - self.originY, 2)); var percentCompleted = 1 - distance / totalDistance; self.indicator.scale.set(3 - 2 * percentCompleted, 3 - 2 * percentCompleted); self.indicator.alpha = percentCompleted; if (distance < 25 || self.x < 150 || self.x > 2048 - 150 || self.y < 700 || self.y > 2732 - 150) { self.indicator.destroy(); return true; } return false; }; }); var Background = Container.expand(function () { var self = Container.call(this); var backgroundGraphics = self.createAsset('background', 'Background', .5, .5); backgroundGraphics.x = 2048 / 2; backgroundGraphics.y = 2732 / 2 + 300; self.exitDoor = self.addChildAt(new ExitDoor(), 1); self.exitDoor.x = 2048 / 2; self.exitDoor.y = 2732 / 2 - 670 + 400; self.exitDoor.visible = false; }); var Game = Container.expand(function () { var self = Container.call(this); self.enemyBulletMove = function () { for (var i = enemyBullets.length - 1; i >= 0; i--) { if (enemyBullets[i] && enemyBullets[i].move()) { var dx = player.x - enemyBullets[i].x; var dy = player.y - enemyBullets[i].y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 100 && !self.allEnemiesKilled) { player.health -= 10; player.healthBar.updateHealth(player.health); player.flashRed(); if (player.health <= 0) { XS.showGameOver(); } } self.createExplosion(enemyBullets[i].x, enemyBullets[i].y); enemyBullets[i].destroy(); enemyBullets.splice(i, 1); } } }; self.lineIntersectsObstacle = function (x1, y1, x2, y2) { for (var i = 0; i < obstacles.length; i++) { var dx = obstacles[i].x - x1; var dy = obstacles[i].y - y1; var distance = Math.sqrt(dx * dx + dy * dy); var radius = obstacles[i].width * 0.7 / 2; if (distance < radius) { return true; } var t = ((x2 - x1) * (obstacles[i].x - x1) + (y2 - y1) * (obstacles[i].y - y1)) / (Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); t = Math.max(0, Math.min(1, t)); var nearestX = x1 + t * (x2 - x1); var nearestY = y1 + t * (y2 - y1); dx = obstacles[i].x - nearestX; dy = obstacles[i].y - nearestY; distance = Math.sqrt(dx * dx + dy * dy); if (distance <= radius) { return true; } } return false; }; self.allEnemiesKilled = false; self.waveCount = 2; self.setPlayerTarget = function (x, y) { x = Math.max(Math.min(x, 2048 - 150), 150); y = Math.max(Math.min(y, 2732 - 150), 700); player.setTarget(x, y); targetIndicator.setPosition(x, y); targetIndicator.visible = true; }; self.checkEnemies = function () { if (!self.allEnemiesKilled && enemies.length === 0 && spawnIndicators.length === 0) { background.exitDoor.visible = true; self.allEnemiesKilled = true; XS.effects.flashScreen(0xFFFFFF, 1000); self.setPlayerTarget(background.exitDoor.x, background.exitDoor.y - 300); } }; self.rotateBackground = function () { background.children[1].rotate(); }; self.particleMove = function () { for (var i = particles.length - 1; i >= 0; i--) { if (particles[i].alpha <= 0) { particles[i].destroy(); particles.splice(i, 1); } else { particles[i].move(); } } }; self.bulletMove = function () { for (var i = bullets.length - 1; i >= 0; i--) { if (bullets[i] && bullets[i].move()) { self.createExplosion(bullets[i].x, bullets[i].y - 150); bullets[i].destroy(); bullets.splice(i, 1); } else { bullets[i].move(); for (var j = 0; j < enemies.length; j++) { if (bullets[i].intersects(enemies[j])) { enemies[j].health -= 10; enemies[j].healthBar.updateHealth(enemies[j].health); enemies[j].flashRed(); if (enemies[j].health <= 0) { enemies[j].destroy(); enemies.splice(j, 1); } else { var angle = Math.atan2(bullets[i].dy, bullets[i].dx); enemies[j].x += Math.cos(angle) * 15; enemies[j].y += Math.sin(angle) * 15; enemies[j].dx = Math.cos(angle) * 10; enemies[j].dy = Math.sin(angle) * 10; } self.createExplosion(bullets[i].x, bullets[i].y - 150); bullets[i].destroy(); bullets.splice(i, 1); break; } } } } }; self.enemyTick = function () { for (var i = 0; i < enemies.length; i++) { var moved = enemies[i].move(obstacles, player); for (var j = i + 1; j < enemies.length; j++) { var dx = enemies[j].x - enemies[i].x; var dy = enemies[j].y - enemies[i].y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < enemies[i].width) { enemies[i].x -= dx / distance; enemies[i].y -= dy / distance; enemies[j].x += dx / distance; enemies[j].y += dy / distance; } } if (!moved && XS.ticks - enemies[i].lastProjectile >= 180) { enemies[i].lastProjectile = XS.ticks; var projectile = enemies[i].throwProjectile(player); if (projectile) { enemyBullets.push(projectile); self.addChild(projectile); } } } }; self.playerMove = function (obstacles) { player.move(obstacles); var dx = player.targetX - player.x; var dy = player.targetY - player.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < player.speed && XS.ticks - player.lastShot >= 30 && enemies.length > 0) { player.lastShot = XS.ticks; var bullet = player.shoot(enemies); if (bullet) { bullets.push(bullet); self.addChild(bullet); } } if (distance < player.speed) { targetIndicator.visible = false; if (self.allEnemiesKilled) { self.spawnNextWave(); } } }; var spawnIndicators = []; self.isTooClose = function (x, y) { for (var i = 0; i < spawnIndicators.length; i++) { var dx = spawnIndicators[i].x - x; var dy = spawnIndicators[i].y - y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 200) { return true; } } return false; }; self.spawnEnemies = function (count) { for (var i = 0; i < count; i++) { var x, y; do { x = Math.random() * (2048 - 300) + 150; y = Math.random() * (2732 - 850) + 700; } while (self.isTooClose(x, y) || self.lineIntersectsObstacle(x, y, x, y)); var spawnIndicator = self.addChild(new EnemySpawnIndicator()); spawnIndicator.setPosition(x, y); spawnIndicators.push(spawnIndicator); (function (spawnIndicator) { XS.setTimeout(function () { var enemy = self.addChild(new Enemy()); enemy.setPosition(spawnIndicator.x, spawnIndicator.y); enemies.push(enemy); spawnIndicator.destroy(); enemy.animateIn(); var index = spawnIndicators.indexOf(spawnIndicator); if (index > -1) { spawnIndicators.splice(index, 1); } }, 3000); })(spawnIndicator); } }; self.createExplosion = function (x, y) { for (var j = 0; j < 10; j++) { var particle = new ExplosionParticle(); particle.setPosition(x, y); particle.dx = (Math.random() - 0.5) * 10; particle.dy = (Math.random() - 0.5) * 7; self.addChild(particle); particles.push(particle); } }; var particles = []; self.sortGameObjects = function () { self.children.sort(function (a, b) { return a.y < b.y ? -1 : 1; }); for (var i = 0; i < self.children.length; i++) { if (self.children[i] instanceof EnemyBulletIndicator) { self.setChildIndex(self.children[i], 1); } } self.setChildIndex(targetIndicator, 1); }; var background = self.addChild(new Background()); var player = self.addChild(new Player()); player.setPosition(2048 / 2, 2732 - player.height); player.setTarget(player.x, player.y); var targetIndicator = self.addChild(new TargetIndicator()); targetIndicator.setPosition(player.x, player.y); var obstacles = []; var enemies = []; self.spawnEnemies(1); var obstacleSpacing = 2048 / 3; for (var i = 0; i < 2; i++) { var obstacle = self.addChild(new Obstacle()); obstacle.setPosition(obstacleSpacing * (i + 1), 2732 / 2 + 500); obstacles.push(obstacle); } var bullets = []; var enemyBullets = []; var waveDisplay = new Text2('Wave: 1', { size: 40, fill: '#ffffff', font: 'Tahoma', dropShadow: true, dropShadowColor: '#000000', dropShadowBlur: 4, dropShadowAngle: Math.PI / 6, dropShadowDistance: 6 }); waveDisplay.anchor.set(0.5, 0); XS.gui.topCenter.addChild(waveDisplay); XS.on('tick', function () { self.playerMove(obstacles); self.bulletMove(); self.enemyTick(); self.enemyBulletMove(); self.particleMove(); self.rotateBackground(); self.sortGameObjects(); self.checkEnemies(); }); self.spawnNextWave = function () { player.setPosition(2048 / 2, 2732 - player.height); player.setTarget(player.x, player.y); background.exitDoor.visible = false; self.allEnemiesKilled = false; waveDisplay.setText('Wave: ' + self.waveCount); self.spawnEnemies(self.waveCount++); XS.effects.flashScreen(0x000000, 1000); for (var i = enemyBullets.length - 1; i >= 0; i--) { enemyBullets[i].destroy(); enemyBullets.splice(i, 1); } for (var i = self.children.length - 1; i >= 0; i--) { if (self.children[i] instanceof EnemyBulletIndicator) { self.children[i].destroy(); self.children.splice(i, 1); } } }; stage.on('down', function (obj) { if (!self.allEnemiesKilled) { var pos = obj.event.getLocalPosition(self); self.setPlayerTarget(pos.x, pos.y); } }); });
===================================================================
--- original.js
+++ change.js
@@ -530,9 +530,9 @@
player.setPosition(2048 / 2, 2732 - player.height);
player.setTarget(player.x, player.y);
background.exitDoor.visible = false;
self.allEnemiesKilled = false;
- waveDisplay.setText('Wave: ' + (self.waveCount + 1));
+ waveDisplay.setText('Wave: ' + self.waveCount);
self.spawnEnemies(self.waveCount++);
XS.effects.flashScreen(0x000000, 1000);
for (var i = enemyBullets.length - 1; i >= 0; i--) {
enemyBullets[i].destroy();
giant wall Pixel art, 16 bit, isometric, SNES, top-down, no background, white background, low resolution, symmetrical
Single Short round Isometric dungeon column, simple, few stones, single column, no floor, dark room, Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
Multi color chaotic noise, primary colors Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
Round purple magic fireball. White core Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
enemy goblin , Pixel art, 16 bit, isometric, SNES, top-down, no background, white background, low resolution, symmetrical, seen from front. No staff.
Single fire particle Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
https://i.imgur.com/R3ZLguO.jpg Dungeon, Empty open floor, dark, fullscreen, Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. high detail. High contrast. --ar 2:3
single wizard, hooded Pixel art, 16 bit, isometric, SNES, top-down, no background, white background, low resolution, symmetrical, seen from front.
round bomb. fuse on fire Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
Multi color chaotic noise, primary colors. Rays from the center. Darker center Single Game Texture. In-Game asset. 2d. Pixelart. Low detail. High contrast.