123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- Goblin = class()
- function Goblin:init(x, y)
- self.x = x
- self.y = y
- self.state = 'idle'
- self.heardX = 0
- self.heardY = 0
- self.fightTarget = nil
- self.dead = false -- TODO: Should this be a state?
- self.killsPlayer = true
- end
- function Goblin:update(world)
- -- Goblins are EXTREMELY SMART and have two ranges of sensing the player:
- -- Within 8 units of distance, they HEAR a player, and walk closer...
- -- Within 5 units of distance, they SEE a player (or are sure of where they
- -- are) and become angered, setting the player as their agro-target.
- -- States:
- -- Idle - will hang around picking its nails.
- -- Suspicious - will walk to the last point it heard something.
- -- Goblins are lazy so it won't do much extra searching - once it gets
- -- to the place it heard the potential threat, it'll go back to idling
- -- there, figuring that it'll hear if the threat comes back.
- -- Fight - will walk towards the threat to eat it.
- -- The goblin will ALWAYS prioritize chasing over checking out something
- -- suspicious, so if it sees a player it'll go and chase them right away.
- if self.state == 'idle' or self.state == 'suspicious' then
- local seePlayer = self:findPlayer(world, 5)
- if seePlayer ~= nil then
- self.fightTarget = seePlayer
- self.state = 'fight'
- end
- end
- if self.state == 'fight' then
- if distanceBetweenPoints(self, self.fightTarget) > 8 then
- self.fightTarget = nil
- self.state = 'idle'
- else
- self:walkTowards(world, self.fightTarget.x, self.fightTarget.y)
- end
- end
- if self.state == 'idle' or self.state == 'suspicious' then
- local hearPlayer = self:findPlayer(world, 8)
- if hearPlayer ~= nil then
- self.heardX = hearPlayer.x
- self.heardY = hearPlayer.y
- self.state = 'suspicious'
- end
- end
- if self.state == 'suspicious' then
- -- If we bump into a wall, forget what we were doing and stop
- -- searching for the player.
- if not self:walkTowards(world, self.heardX, self.heardY) then
- self.heardX = 0
- self.heardY = 0
- self.state = 'idle'
- end
- end
- local hearPlayer = self:findPlayer(world, 8)
- local seePlayer = self:findPlayer(world, 5)
- if self.agroTarget == nil and seePlayer ~= nil then
- self.agroTarget = seePlayer
- end
- if self.pattern ~= nil then
- self.pattern:update(world)
- if self.pattern.done then
- self.pattern = nil
- end
- end
- self:testDead(world)
- end
- function Goblin:testDead(world)
- -- defined in player.lua, should be moved maybe
- if testColl(world.bullets, self.x, self.y) then
- self.dead = true
- end
- end
- function Goblin:findPlayer(world, distance)
- if distanceBetweenPoints(self, world.player) <= distance then
- return world.player
- else
- return nil
- end
- end
- function Goblin:walkTowards(world, x, y)
- -- Occasionally stumble!
- if love.math.random(1, 6) == 1 then
- return true -- true so we don't quit the suspicious state.
- end
- -- Go either horizontal or vertical, prioritizing the further distance or
- -- horizontal if they are equal. If we bump into a wall while moving hori-
- -- zontally, try moving vertically.
- local success = false
- function horizontal()
- return goToWithoutTouchingAnything(self, world,
- self.x + sign(x - self.x), self.y
- )
- end
- if math.abs(self.x - x) > math.abs(self.y - y) then
- success = horizontal()
- end
- if not success then
- success = goToWithoutTouchingAnything(self, world,
- self.x, self.y + sign(y - self.y)
- )
- end
- if not success then
- success = horizontal()
- end
- return success
- end
- function Goblin:draw(text)
- text[self.y][self.x] = {
- char = 'G',
- color = ({idle=COLOR.WHITE, suspicious=COLOR.YELLOW, fight=COLOR.RED})[self.state]
- }
- end
|