User prompt
createExplosion when removing enemy bullets
User prompt
In enemyBulletMove flash the hero read if hero is hit, if player health is below zero call gameover
User prompt
In enemyBulletMove when the bullet is destroyed, test if the bullet is less than 50px from the hero, if so, deal damage to the hero
User prompt
remove the else case from enemyBulletMove
User prompt
delete enemyBullets[i].move(); from the else clause in enemyBulletMove
User prompt
Remove the player intersection code for enemy bullets
User prompt
Bullet graphics should be calculated as -150 - 200 * Math.sin(Math.PI * percentCompleted);
User prompt
In EnemyBullet move calculate how many % of the total flight path the bullet has completed. And use it to offset bulletGraphics in an arch, with the top of the arch at 50% of the total flight time
User prompt
On enemy bullet when firing the bullet, track where the bullet originated from on enemy bullet
User prompt
Update enemy move method such that bullets are removed if they are close to the target, not just if they are exactly at the target
User prompt
Destroy enemy bullets if they reach targetX and targetY
User prompt
When firing enemy bullets, set a target for the bullet which is where the hero was when the bullet was fired
User prompt
Rotate bulletGraphics as enemy bullets fly trough the air
User prompt
Increase the pause between how often enemies throw rocks by 3x
User prompt
Enemy bullets should not have blend mode set
User prompt
Make enemy bullets use a separate asset and make them 70% as fast
User prompt
Call flash red on hero when the hero is hit
User prompt
Use a variable for the player asset in hero, and use that to flash red
User prompt
Add a flash red method to the player class that flashes the 'player' asset red
User prompt
set particleGraphics blendMode = 1
User prompt
in enemy move set movedTowardsPlayer to true initially
User prompt
in enemy tick track if move returned false, if so allow projectiles to be fired
User prompt
Make sure enemy move is only called once in enemyTick
User prompt
In enemyTick only allow projectiles to be fired for an enemy if move returned false
User prompt
Remove the projectile fire code from the tick function
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 = 5; 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 - 200 * Math.sin(Math.PI * percentCompleted); if (distance < 50 || self.x < 150 || self.x > 2048 - 150 || self.y < 700 || self.y > 2732 - 150) { 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()) { 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.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); 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); 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 >= 60 && 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; }); 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(5); 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 = []; 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; self.spawnEnemies(5); XS.effects.flashScreen(0x000000, 1000); }; stage.on('down', function (obj) { if (!self.allEnemiesKilled) { var pos = obj.event.getLocalPosition(self); self.setPlayerTarget(pos.x, pos.y); } }); });
===================================================================
--- original.js
+++ change.js
@@ -265,9 +265,9 @@
for (var i = enemyBullets.length - 1; i >= 0; i--) {
if (enemyBullets[i] && enemyBullets[i].move()) {
enemyBullets[i].destroy();
enemyBullets.splice(i, 1);
- } else {}
+ }
}
};
self.lineIntersectsObstacle = function (x1, y1, x2, y2) {
for (var i = 0; i < obstacles.length; i++) {
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.