summaryrefslogtreecommitdiff
path: root/dustParticle.lua
blob: 8e7edd48b122d871d044a27ab8ea551abe3f8c42 (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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
local DustParticle = {}
DustParticle.__index = DustParticle

local MAX_DUST = 30
local DRIFT_SPEED_MIN = 4
local DRIFT_SPEED_MAX = 12
local WOBBLE_AMP_MIN = 3
local WOBBLE_AMP_MAX = 8
local WOBBLE_FREQ_MIN = 0.8
local WOBBLE_FREQ_MAX = 2.5
local GLOW_FREQ_MIN = 1.5
local GLOW_FREQ_MAX = 4.0
local GLOW_RADIUS_MIN = 2
local GLOW_RADIUS_MAX = 5
local MARGIN = 16

local DUST_COLORS = {
    {1.0, 0.95, 0.75},
    {0.85, 0.9, 1.0},
    {1.0, 0.85, 0.6},
    {0.75, 0.85, 1.0},
}

function DustParticle.new(x, y)
    local self = setmetatable({}, DustParticle)
    self.x = x
    self.y = y

    local angle = math.random() * math.pi * 2
    local speed = DRIFT_SPEED_MIN + math.random() * (DRIFT_SPEED_MAX - DRIFT_SPEED_MIN)
    self.dx = math.cos(angle) * speed
    self.dy = math.sin(angle) * speed

    self.perpX = -math.sin(angle)
    self.perpY = math.cos(angle)

    self.wobbleAmp = WOBBLE_AMP_MIN + math.random() * (WOBBLE_AMP_MAX - WOBBLE_AMP_MIN)
    self.wobbleFreq = WOBBLE_FREQ_MIN + math.random() * (WOBBLE_FREQ_MAX - WOBBLE_FREQ_MIN)
    self.wobblePhase = math.random() * math.pi * 2

    self.glowFreq = GLOW_FREQ_MIN + math.random() * (GLOW_FREQ_MAX - GLOW_FREQ_MIN)
    self.glowPhase = math.random() * math.pi * 2

    self.baseAlpha = 0.15 + math.random() * 0.25
    self.color = DUST_COLORS[math.random(#DUST_COLORS)]
    self.time = 0
    return self
end

function DustParticle:update(dt)
    self.time = self.time + dt
    local wobble = math.sin(self.time * self.wobbleFreq + self.wobblePhase) * self.wobbleAmp
    self.x = self.x + (self.dx + self.perpX * wobble * 0.3) * dt
    self.y = self.y + (self.dy + self.perpY * wobble * 0.3) * dt
end

function DustParticle:draw()
    local glowT = math.sin(self.time * self.glowFreq + self.glowPhase)
    local glowRadius = GLOW_RADIUS_MIN + (GLOW_RADIUS_MAX - GLOW_RADIUS_MIN) * (glowT * 0.5 + 0.5)
    local alpha = self.baseAlpha * (0.6 + 0.4 * (glowT * 0.5 + 0.5))

    love.graphics.setBlendMode("add")
    love.graphics.setColor(self.color[1], self.color[2], self.color[3], alpha * 0.4)
    love.graphics.circle("fill", self.x, self.y, glowRadius)
    love.graphics.setColor(self.color[1], self.color[2], self.color[3], alpha)
    love.graphics.circle("fill", self.x, self.y, 1)
    love.graphics.setBlendMode("alpha")
    love.graphics.setColor(1, 1, 1, 1)
end

function DustParticle:isOutOfBounds(viewX, viewY, viewW, viewH)
    return self.x < viewX - MARGIN or self.x > viewX + viewW + MARGIN
        or self.y < viewY - MARGIN or self.y > viewY + viewH + MARGIN
end

local DustSystem = {}
DustSystem.__index = DustSystem

function DustSystem.new()
    local self = setmetatable({}, DustSystem)
    self.particles = {}
    self.spawned = false
    return self
end

function DustSystem:update(dt, camX, camY, camW, camH)
    if not self.spawned then
        for _ = 1, MAX_DUST do
            local x = camX + math.random() * camW
            local y = camY + math.random() * camH
            table.insert(self.particles, DustParticle.new(x, y))
        end
        self.spawned = true
    end

    for _, p in ipairs(self.particles) do
        p:update(dt)
    end

    for i = #self.particles, 1, -1 do
        local p = self.particles[i]
        if p:isOutOfBounds(camX, camY, camW, camH) then
            local edge = math.random(4)
            local x, y
            if edge == 1 then
                x = camX - MARGIN * 0.5
                y = camY + math.random() * camH
            elseif edge == 2 then
                x = camX + camW + MARGIN * 0.5
                y = camY + math.random() * camH
            elseif edge == 3 then
                x = camX + math.random() * camW
                y = camY - MARGIN * 0.5
            else
                x = camX + math.random() * camW
                y = camY + camH + MARGIN * 0.5
            end
            self.particles[i] = DustParticle.new(x, y)
        end
    end

    while #self.particles < MAX_DUST do
        local x = camX + math.random() * camW
        local y = camY + math.random() * camH
        table.insert(self.particles, DustParticle.new(x, y))
    end
end

function DustSystem:draw()
    for _, p in ipairs(self.particles) do
        p:draw()
    end
end

return DustSystem