aboutsummaryrefslogtreecommitdiff
path: root/enemies.lua
diff options
context:
space:
mode:
Diffstat (limited to 'enemies.lua')
-rw-r--r--enemies.lua470
1 files changed, 234 insertions, 236 deletions
diff --git a/enemies.lua b/enemies.lua
index de28adb..0168e1c 100644
--- a/enemies.lua
+++ b/enemies.lua
@@ -1,20 +1,62 @@
enemies = {}
-basicenemysprites = {14, 30, 46, 62} --these are all possible 8x8 basic enemy sprites
-
---Basic, small 8x8 customizable enemy. Very reusable!
-
-function addbasicenemy(x, y, sprite, health, speed)
- local enemy = {}
- enemy.x = x
- enemy.y = y
- enemy.w = 8
- enemy.h = 8
- enemy.inv = -1
- enemy.sprite = sprite
- enemy.health = health
- enemy.shootcooldown = rnd(2)+1
- enemy.speed = speed
+--universal functions:
+function enemyshot(enemy)
+ --explode
+ explosion(enemy.x+rnd(enemy.w), enemy.y+rnd(enemy.h))
+ enemy.inv = 0.5
+ --and reduce health
+ enemy.health -= 1
+ if enemy.health > 0 then
+ sfx(16, 2)
+ end
+end
+
+function enemycollide(enemy, object) --f this enemy collides with something, do damage to both it and itself. also EXPLODE!!!
+ if enemy.x <= object.x+object.w and enemy.x+enemy.w >= object.x and enemy.y <= object.y +object.h and enemy.y+enemy.h >= object.y and object.inv < 0 then
+ object:shot()
+ explosion(enemy.x+4+rnd(enemy.w-4), enemy.y+4*rnd(enemy.h-4))
+ enemy.health -= 2
+ end
+end
+
+function enemydie(enemy, sound)
+ for i = 1, rnd(enemy.h)+6, 1 do
+ addcircle(enemy.x+rnd(enemy.w), enemy.y+rnd(enemy.h), rnd(4)-2, -rnd(2)-1, 1, 2, rnd({3, 11, 9}), -0.1)
+ end
+ if rnd(100) > 95 then
+ addpickup(enemy.x+rnd(enemy.w), enemy.y+rnd(enemy.h))
+ end
+ if shake < 3 then
+ shake = enemy.h/2
+ end
+ sfx(sound, 2)
+ del(enemies, enemy)
+end
+
+function enemymisc(enemy) --misc stuff every enemy needs
+ enemy.shootcooldown -= 1/60
+ enemy.inv -= 1/60
+ for i = 1, #players, 1 do
+ enemy.collide(enemy, players[i])
+ end
+ if enemy.x < -enemy.w then
+ del(enemies, enemy) -- delete enemy if off screen
+ end
+end
+
+function addbasicenemy(x, y, speed) --basic small weak enemy
+ local enemy = {
+ x = x,
+ y = y,
+ w = 8,
+ h = 8,
+ inv = -1,
+ sprite = rnd({14, 30, 46, 62}), --these are all possible 8x8 basic enemy sprites
+ health = 1,
+ shootcooldown = rnd(2)+1,
+ speed = speed
+ }
function enemy.draw(enemy)
local sprite = enemy.sprite
@@ -26,31 +68,13 @@ function addbasicenemy(x, y, sprite, health, speed)
end
end
- function enemy.shot(enemy)
- --explode
- explosion(enemy.x, enemy.y)
- enemy.inv = 0.5
- --and reduce health
- enemy.health -= 1
- if enemy.health > 0 then
- sfx(16, 2)
- end
- end
+ enemy.shot = enemyshot
- function enemy.collide(object) --f this enemy collides with something, do damage to both it and itself. also EXPLODE!!!
- if enemy.x+4 >= object.x and enemy.x+4 <= object.x+object.w and enemy.y+4 >= object.y and enemy.y+4 <= object.y+object.h and object.inv < 0 then
- object:shot()
- explosion(enemy.x+4, enemy.y+4)
- enemy.health -= 2
- end
- end
+ enemy.collide = enemycollide
function enemy.update()
enemy.x -= speed
enemy.y += sin(time()*speed)*speed
- enemy.shootcooldown -= 1/60
- enemy.inv -= 1/60
- foreach(players, enemy.collide)
if enemy.shootcooldown < 0 then
enemy.shootcooldown = 0.5 + rnd(1.5)
if enemy.x < 129 then
@@ -58,21 +82,9 @@ function addbasicenemy(x, y, sprite, health, speed)
sfx(15, 2) -- play shoot sound if on screen
end
end
- if enemy.x < -8 then
- del(enemies, enemy) -- delete enemy if off screen
- end
+ enemymisc(enemy)
if enemy.health <= 0 then -- die!!!!!
- for i = 1, rnd(6)+6, 1 do
- addcircle(enemy.x+rnd(8), enemy.y+rnd(8), rnd(4)-2, -rnd(2)-1, 1, 2, rnd({3, 11, 9}), -0.1)
- end
- if rnd(100) > 95 then
- addpickup(enemy.x, enemy.y)
- end
- if shake < 3 then
- shake = 2.5
- end
- sfx(17, 2)
- del(enemies, enemy)
+ enemydie(enemy,17)
end
end
@@ -82,23 +94,24 @@ end
--SHOOTER THAT SHOOTS BIG WALLS!!!!!!
function addwallshooter(x, shootup, health, speed, offset, bulletspeed)
- local enemy = {}
- enemy.x = x
- enemy.y = 119
- enemy.sprite = 60
- enemy.offset = offset or rnd()
+ local enemy = {
+ x = x,
+ y = 119,
+ sprite = 60,
+ offset = offset or rnd(),
+ w = 8,
+ h = 8,
+ inv = -1,
+ health = health,
+ shootcooldown = 0,
+ speed = speed,
+ shoottoggle = true,
+ bulletspeed = bulletspeed or 1,
+ }
if shootup then
enemy.y = 1
enemy.sprite = 44
end
- enemy.w = 8
- enemy.h = 8
- enemy.inv = -1
- enemy.health = health
- enemy.shootcooldown = 0
- enemy.speed = speed
- enemy.shoottoggle = true
- enemy.bulletspeed = bulletspeed or 1
function enemy.draw(enemy)
if enemy.inv < 0 or ceil(enemy.inv*10%2) == 1 then
@@ -106,28 +119,12 @@ function addwallshooter(x, shootup, health, speed, offset, bulletspeed)
end
end
- function enemy.shot(enemy)
- --explode
- explosion(enemy.x, enemy.y)
- --and reduce health
- enemy.health -= 1
- enemy.inv = 0.5
- sfx(16, 2)
- end
+ enemy.shot = enemyshot
- function enemy.collide(object)
- if enemy.x+4 >= object.x and enemy.x+4 <= object.x+object.w and enemy.y+4 >= object.y and enemy.y+4 <= object.y+object.h and object.inv < 0 then
- object:shot()
- explosion(enemy.x, enemy.y)
- enemy.health -= 2
- end
- end
+ enemy.collide = enemycollide
function enemy.update()
enemy.x -= speed
- enemy.shootcooldown -= 1/60
- enemy.inv -= 1/60
- foreach(players, enemy.collide)
if enemy.shootcooldown < 0 then
if (t()+enemy.offset)%1>0.5/enemy.bulletspeed then
if not enemy.shoottoggle then --implemented a toggle so that the sound effect for firing gets played only once.
@@ -144,21 +141,9 @@ function addwallshooter(x, shootup, health, speed, offset, bulletspeed)
enemy.shoottoggle = false
end
end
- if enemy.x < -8 then
- del(enemies, enemy) --if off screen, get deleted nerd
- end
+ enemymisc(enemy)
if enemy.health <= 0 then
- for i = 1, rnd(6)+6, 1 do
- addcircle(enemy.x+rnd(8), enemy.y+rnd(8), rnd(4)-2, -rnd(2)-1, 1, 2, rnd({3, 11, 9}), -0.1)
- end
- if rnd(100) > 95 then
- addpickup(enemy.x, enemy.y)
- end
- if shake < 3 then
- shake = 2.5
- end
- sfx(17, 2)
- del(enemies, enemy)
+ enemydie(enemy,17)
end
end
@@ -168,49 +153,33 @@ end
--Big ol fella that shoots CIRCLES of BULLETS!!!!!!
function addballshooter(x, y, health, speed)
- local enemy = {}
- enemy.x = x
- enemy.y = y
- enemy.offset = rnd()
- enemy.w = 8*3
- enemy.h = 8*2
- enemy.inv = -1
- enemy.health = health
- enemy.shootcooldown = 0
- enemy.speed = speed
+ local enemy = {
+ x = x,
+ y = y,
+ offset = rnd(),
+ w = 8*3,
+ h = 8*2,
+ inv = -1,
+ health = health,
+ shootcooldown = 0,
+ speed = speed
+ }
function enemy.draw(enemy)
if enemy.inv < 0 or ceil(enemy.inv*10%2) == 1 then
local sprite = 27
- local damaged = (enemy.health < 7)
- if damaged then sprite = 11 end
- spr(sprite, enemy.x, enemy.y, 3, 1, false, not damaged)
- spr(sprite, enemy.x, enemy.y+8, 3, 1, false, damaged)
+ if health < 7 then sprite = 11 end
+ spr(sprite, enemy.x, enemy.y, 3, 1, false, true)
+ spr(sprite, enemy.x, enemy.y+8, 3, 1)
end
end
- function enemy.shot(enemy)
- --explode
- explosion(enemy.x+rnd(32), enemy.y+rnd(32))
- --and reduce health
- enemy.health -= 1
- enemy.inv = 0.5
- sfx(16, 2)
- end
+ enemy.shot = enemyshot
- function enemy.collide(object)
- if enemy.x+4 >= object.x and enemy.x+4 <= object.x+object.w and enemy.y+4 >= object.y and enemy.y+4 <= object.y+object.h and object.inv < 0 then
- object:shot()
- explosion(enemy.x+4, enemy.y+4, 8*4, 8*2)
- enemy.health -= 3
- end
- end
+ enemy.collide = enemycollide
function enemy.update()
enemy.x -= speed
- enemy.shootcooldown -= 1/60
- enemy.inv -= 1/60
- foreach(players, enemy.collide)
if enemy.shootcooldown < 0 then
enemy.shootcooldown = 2
if enemy.x < 129 then
@@ -222,25 +191,12 @@ function addballshooter(x, y, health, speed)
sfx(19, 3) -- play shoot sound
end
end
- if enemy.x < -24 then
- del(enemies, enemy) --delete enemy if off screen
- end
+ enemymisc(enemy)
if enemy.health < 8 then --smokes when damaged!
addcircle(enemy.x+20+rnd(8), enemy.y+4+rnd(8), -0.5, -0.2, rnd(8), rnd(1)+0.7, 5, 0)
end
if enemy.health <= 0 then
- for i = 1, 24, 1 do
- addcircle(enemy.x+rnd(8), enemy.y+rnd(8), rnd(4)-2, -rnd(2)-1, 1, 2, rnd({3, 11, 9}), -0.1)
- end
- if rnd(100) > 70 then
- addpickup(enemy.x, enemy.y)
- end
- if shake < 3 then
- shake = 12
- end
- sfx(20, 3)
- explosion(enemy.x+4, enemy.y+4, 8*4, 8*2)
- del(enemies, enemy)
+ enemydie(enemy,20)
end
end
@@ -248,16 +204,17 @@ function addballshooter(x, y, health, speed)
end
function addtargetingenemy(x, y, health, speed)
- local enemy = {}
- enemy.x = x
- enemy.y = y
- enemy.w = 16
- enemy.h = 8
- enemy.inv = -1
- enemy.health = health
- enemy.shootcooldown = rnd(0.4)+0.2
- enemy.speed = speed
- enemy.bulletcounter = 0
+ local enemy = {
+ x = x,
+ y = y,
+ w = 16,
+ h = 8,
+ inv = -1,
+ health = health,
+ shootcooldown = rnd(0.4)+0.2,
+ speed = speed,
+ bulletcounter = 0
+ }
function enemy.draw(enemy)
if enemy.inv < 0 or ceil(enemy.inv*10%2) == 1 then
@@ -265,30 +222,12 @@ function addtargetingenemy(x, y, health, speed)
end
end
- function enemy.shot(enemy)
- --explode
- explosion(enemy.x, enemy.y)
- enemy.inv = 0.5
- --and reduce health
- enemy.health -= 1
- if enemy.health > 0 then
- sfx(16, 2)
- end
- end
+ enemy.shot = enemyshot
- function enemy.collide(object) --f this enemy collides with something, do damage to both it and itself. also EXPLODE!!!
- if enemy.x+4 >= object.x and enemy.x+4 <= object.x+object.w and enemy.y+4 >= object.y and enemy.y+4 <= object.y+object.h and object.inv < 0 then
- object:shot()
- explosion(enemy.x+4, enemy.y+4)
- enemy.health -= 2
- end
- end
+ enemy.collide = enemycollide
function enemy.update()
enemy.x -= speed
- enemy.shootcooldown -= 1/60
- enemy.inv -= 1/60
- foreach(players, enemy.collide)
if enemy.shootcooldown < 0 and currentwavetime%1.5>1.2 then
enemy.shootcooldown = 0.1
enemy.bulletcounter += 1
@@ -301,22 +240,9 @@ function addtargetingenemy(x, y, health, speed)
sfx(15, 2) -- play shoot sound if on screen
end
end
- if enemy.x < -16 then
- del(enemies, enemy) -- delete enemy if off screen
- end
+ enemymisc(enemy)
if enemy.health <= 0 then -- die!!!!!
- for i = 1, rnd(6)+6, 1 do
- addcircle(enemy.x+rnd(8), enemy.y+rnd(16), rnd(4)-2, -rnd(2)-1, 1, 2, rnd({3, 11, 9}), -0.1)
- end
- if rnd(100) > 85 then
- addpickup(enemy.x, enemy.y)
- end
- if shake < 3 then
- shake = 3.5
- end
- sfx(17, 2)
- explosion(enemy.x, enemy.y, 16, 8)
- del(enemies, enemy)
+ enemydie(enemy,17)
end
end
@@ -324,50 +250,35 @@ function addtargetingenemy(x, y, health, speed)
end
function addlasershooter(x, y, speed, stay)
- local enemy = {}
- enemy.x = x+128
- enemy.y = y
+ local enemy = {
+ x = x+128,
+ y = y,
+ w = 8*4,
+ h = 8*4,
+ speed = speed,
+ stay = stay,
+ inv = -1,
+ health = 36 * #players, -- double health if 2 player
+ lasertimer = 0,
+ firedlaser = false,
+ shootcooldown = 0,
+ moveoffset = 0,
+ sinspeed = 4
+ }
if stay then enemy.y = 64-20 end
- enemy.w = 8*4
- enemy.h = 8*4
- enemy.speed = speed
- enemy.stay = stay
- enemy.inv = -1
- enemy.health = 36
- enemy.lasertimer = 0
- enemy.firedlaser = false
- enemy.shootcooldown = 0
- enemy.moveoffset = 0
- enemy.sinspeed = 4
function enemy.draw(enemy)
if enemy.inv < 0 or ceil(enemy.inv*10%2) == 1 then
- local damaged = (enemy.health < 12)
local sprite = 64
- if damaged then sprite = 96 end
- spr(sprite,enemy.x+0,enemy.y+4,4,2, false, damaged)
- spr(sprite,enemy.x+0,enemy.y+20,4,2,false,not damaged)
+ if enemy.health < 12 then sprite = 96 end
+ spr(sprite,enemy.x+0,enemy.y+4,4,2)
+ spr(sprite,enemy.x+0,enemy.y+20,4,2,false,true)
end
end
- function enemy.shot(enemy)
- --explode
- explosion(enemy.x, enemy.y)
- enemy.inv = 0.5
- --and reduce health
- enemy.health -= 1
- if enemy.health > 0 then
- sfx(16, 2)
- end
- end
+ enemy.shot = enemyshot
- function enemy.collide(object) --f this enemy collides with something, do damage to both it and itself. also EXPLODE!!!
- if enemy.x+4 >= object.x and enemy.x+4 <= object.x+object.w and enemy.y+4 >= object.y and enemy.y+4 <= object.y+object.h and object.inv < 0 then
- object:shot()
- explosion(enemy.x+4, enemy.y+4)
- enemy.health -= 2
- end
- end
+ enemy.collide = enemycollide
function enemy.update()
if enemy.x > 90 or (not stay and enemy.lasertimer > 4) then --enemy lerps into place when first added, and if they leave they speed up
@@ -381,7 +292,6 @@ function addlasershooter(x, y, speed, stay)
if enemy.lasertimer > 4 and stay then
enemy.y = 64-20 + sin(enemy.moveoffset+enemy.lasertimer/enemy.sinspeed) * 40
- enemy.shootcooldown -= 1/60
if enemy.shootcooldown < 0 then
enemy.shootcooldown = 0.18
addbullet(enemy.x+6, enemy.y+20, -1, rnd(2)-1, true, 2) --shoooot!!!!!
@@ -394,6 +304,9 @@ function addlasershooter(x, y, speed, stay)
addlaser(enemy.x+6, enemy.y+20, 10)
enemy.moveoffset = rnd({0,0.5}) --add offset so not moving in same direction each time
enemy.sinspeed = rnd({4,4,4,4,4,4,4,4,4,4,4,4,1,8,2,2,2,2}) --add differing speeds to sin up and down randomly
+ if enemy.health < 15*#players then
+ enemy.sinspeed /= 2
+ end
end
enemy.firedlaser = true
enemy.lasertimer += 1/60
@@ -407,26 +320,111 @@ function addlasershooter(x, y, speed, stay)
addcircle(enemy.x+12+rnd(8), enemy.y+12+rnd(8), -0.5, -0.2, rnd(8), rnd(1)+0.7, 5, 0)
end
- enemy.inv -= 1/60
- foreach(players, enemy.collide)
-
- if enemy.x < -32 then
- del(enemies, enemy) -- delete enemy if off screen
- end
+ enemymisc(enemy)
if enemy.health <= 0 then -- die!!!!!
- explosion(enemy.x,enemy.y,32,32)
- for i = 1, 40, 1 do
- addcircle(enemy.x+rnd(32), enemy.y+rnd(32), sin(t()*2), -rnd(2)-1, 1, 2, rnd({3, 11, 9}), -0.1)
- end
+ enemydie(enemy,26)
addpickup(enemy.x+rnd(32), enemy.y+rnd(32), "health")
addpickup(enemy.x+rnd(32), enemy.y+rnd(32))
addpickup(enemy.x+rnd(32), enemy.y+rnd(32))
- if shake < 3 then
- shake = 6
+ end
+ end
+
+ add(enemies, enemy)
+end
+
+function addwallboss(x, y, length, speed, stay, move)
+ local enemy = {
+ stay = stay or false,
+ move = move or 1,
+ x = x,
+ y = y,
+ length = mid(4,length,16),
+ w = 24,
+ h = 8*length,
+ inv = -1,
+ health = 10*length*#players,
+ shootcooldown = 3,
+ speed = speed,
+ bulletfired = {},
+ }
+
+ for i = 1, length, 1 do
+ enemy.bulletfired[i] = 0
+ end
+
+ function enemy.draw(enemy)
+ local dmg = 0
+ if enemy.health < length * 4 * #players then
+ dmg = 16
+ end
+ if enemy.inv < 0 or ceil(enemy.inv*10%2) == 1 then
+ for i = 2, length-1, 1 do
+ spr(93+enemy.bulletfired[i]+dmg, enemy.x, -8+enemy.y+i*8)
+ if i < length-2 then
+ spr(79+((i%3)%2*16)+dmg*2, enemy.x+8, -8+enemy.y+i*8, 1, 1, false, (i%3 == 2))
+ end
+ end
+ spr(77+enemy.bulletfired[1]+dmg*2, enemy.x, enemy.y)
+ spr(77+enemy.bulletfired[1]+dmg*2, enemy.x, enemy.y+length*8-8, 1, 1, false, true)
+ spr(70+dmg,enemy.x+8,enemy.y,2,2)
+ spr(70+dmg*2,enemy.x+8,enemy.y+length*8-16,2,2,false,true)
+ spr(79+dmg,enemy.x+8,enemy.y+length*8-24,1,1)
+ end
+ end
+
+ enemy.shot = enemyshot
+
+ enemy.collide = enemycollide
+
+ function enemy.update()
+ if not enemy.stay then
+ enemy.x -= speed
+ else
+ enemy.x = enemy.x + 0.025 * (102 - enemy.x); --lerp if boss
+ enemy.move = flr((currentwavetime/5)%5) -- loops through moveset
+ end
+ if enemy.shootcooldown < 0 then
+ enemy.shootcooldown = 0.095
+ if enemy.x < 129 then
+
+ local function attack(i, move) -- these are all the conditions to shoot depending on what "move" this guys on
+ if move == 0 and (flr((t()*4)%length) == i or flr((-t()*4)%length) == i) and i%2 == 1 then --this one shoots lines in a pattern
+ return true
+ elseif move == 1 then -- this one targets the players and shoots some random ones
+ for p = 1, #players, 1 do
+ if flr(players[p].y/8) == i-1 and everysecondtimer < 0.7 then
+ return true
+ end
+ end
+ elseif move == 2 and i == ceil(rnd(length*1.3)) then -- this one is just random ones
+ return true
+ elseif move == 3 then --this one is that neat weaving pattern, shout out to don't get a virus fans!
+ if i > length/3 and i < length/3*2 then
+ if currentwavetime%1.5 < 0.15 then
+ return true
+ end
+ elseif currentwavetime%1.5 > 0.7 and currentwavetime%1.5 < 0.85 then
+ return true
+ end
+ elseif move == 5 and (i < length/3+sin(t()/3)*3 or i > length/3*2+sin(t()/3)*3 or ceil(rnd(length*7)) == i) then -- this one is a wavy bullet corridor
+ return true
+ end
+ end
+
+ for i = 1, length, 1 do
+ if attack(i, enemy.move) then
+ addbullet(enemy.x, -4+i*8, -1, 0, true, 2)
+ enemy.bulletfired[i] = 1
+ else
+ enemy.bulletfired[i] = 0
+ end
+ end
end
- sfx(26, 3)
- del(enemies, enemy)
+ end
+ enemymisc(enemy)
+ if enemy.health <= 0 then -- die!!!!!
+ enemydie(enemy,17)
end
end