summaryrefslogtreecommitdiff
path: root/objects/Enemy.lua
blob: 76371b25a89b5e727c9cd94007dac5b0deddac2e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
require "data.directions"

local Body = require "objects.Body"
local enemyData = require "data.enemyData"

local Enemy = {}
Enemy.__index = Enemy

local FrameTimer = require "utils.frameTimer"

function Enemy:new(name, location)
    local data = enemyData[name]
    local obj = {
        type = name,
        presetLocation = (type(location) == "string" and location) or nil,
        x = (type(location) == "table" and location.x) or nil,
        y = (type(location) == "table" and location.y) or nil,
        body = Body:new("circle",
            data.size or nil, nil,
            data.zoom or 1
        ),
        speed = data.speed or nil,
        health = data.health or nil,
        stunned = false,
        frameTimer = FrameTimer:new(config.frameRate,
            (data.sprite and data.sprite.totalFrames) or 1),
        movePattern = data.movePattern or nil,
    }

    setmetatable(obj, Enemy)

    return obj
end

function Enemy:isBlocked()

end

function Enemy:move(dt)
    if self.stunned and self.stunned > 0 then
        self.stunned = self.stunned - dt
        return false
    end
    if self.movePattern == "vertical" then
        self:moveVertical(G.player.x, dt)
    else self:moveTo(G.player.x, G.player.y, dt)
    end
end

function Enemy:moveTo(x, y, dt)
    local dv = self.speed * dt

    local function getDelta(axis, destination, direction)
        -- delta is either +1 or -1, represents the direction
        local delta = (self[axis] < destination and 1) or (self[axis] > destination and -1) or 0

        -- check if the movement is blocked, if so delta is 0, meaning no movement
        local isBlocked = utils.isBlocked(self.body, self.x, self.y, direction, axis, dv*delta)
        if isBlocked then delta = 0 end

        return delta
    end

    local dx = getDelta("x", x, Direction.RIGHT)    -- RIGHT and LEFT means the same for isBlocked()
    local dy = getDelta("y", y, Direction.DOWN)     -- the same for DOWN and UP

    self.x = self.x + dx * dv
    self.y = self.y + dy * dv
end

function Enemy:moveVertical(toX, dt)
    self:moveTo(toX, self.y, dt)
end

function Enemy:facing()
    local dx = self.x - G.player.x
    local dy = self.y - G.player.y
    local angle = math.atan2(dy, dx)

    local dir
    if angle >= -math.pi / 4 and angle < math.pi / 4 then
        dir = Direction.LEFT
    elseif angle >= math.pi / 4 and angle < 3 * math.pi / 4 then
        dir = Direction.UP
    elseif angle >= -3 * math.pi / 4 and angle < -math.pi / 4 then
        dir = Direction.DOWN
    else
        dir = Direction.RIGHT
    end

    return dir
end

function Enemy:getsAttacked(damage)
    self.health = self.health - damage
    if self:isDead() then
        self:die()
    end
end

function Enemy:isDead()
    return self.health <= 0
end

function Enemy:die()
    -- drop loots
    for i, item in ipairs(enemyData[self.type].drops) do
        local temp = math.random(10) / 10
        if temp <= item.chances then
            local offset = (i - 1) * 5
            loot.drop(self.x + offset, self.y + offset, item.type)
        end
    end
end

function Enemy:stun(duration)
    self.stunned = duration
end

return Enemy