| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- local colors = {"red", "green", "blue"} -- list of existing fireworks colors
- local instances = {} -- list of active fireworks instances
- local _tension = 0.9 -- emulation of air tension. More value leads to faster deceleration
- local _gravity = 980 -- gravity, measuring in mm/sq.s.
- local function start_fireworks(trail_id, bang_id, start_pos, speed, time, gravity, tension)
- go.set_position(start_pos, trail_id)
- particlefx.play(trail_id)
- local m = {
- update = function(self, dt)
- if self.time > 0 then
- local prev_pos = vmath.vector3(self.start_pos)
- self.start_pos.x = self.start_pos.x + self.speed.x*dt
- self.start_pos.y = self.start_pos.y + self.speed.y*dt
- local triangle = vmath.vector3(prev_pos.x - start_pos.x, prev_pos.y - start_pos.y, 0)
- local angle = math.atan2(triangle.y, triangle.x)
- self.speed.x = self.speed.x - self.speed.x * self.tension*dt
- self.speed.y = self.speed.y - self.speed.y * self.tension*dt - self.gravity*dt
- go.set_position(self.start_pos, self.trail)
- go.set_rotation(vmath.quat_rotation_z(angle+math.pi/2), self.trail)
- if self.time > 0 then
- go.set_scale(self.time, self.trail)
- end
- elseif self.time <= 0 and not self.is_stopped then
- self.is_stopped = true
- particlefx.stop(self.trail, { clear = true })
- go.set_position(self.start_pos, self.bang)
- particlefx.play(self.bang)
- elseif self.time <= -1.5 and self.bang then
- go.delete(self.bang)
- self.bang = nil
- end
- self.time = self.time - dt
- end,
- start_pos = start_pos,
- time = time,
- speed = speed,
- gravity = gravity or _gravity,
- tension = tension or _tension,
- trail = trail_id,
- bang = bang_id
- }
- return m
- end
- local function single_shot()
- if #instances > 5 then
- return
- end
- local color = colors[math.random(1, #colors)]
- local splat = factory.create("#"..color.."_splat_factory")
- local trail = factory.create("#"..color.."_trail_factory")
- local strength = 1000+math.random()*600 -- scalar value of speed
- local angle = (-0.2+math.random()*0.4)*math.pi -- angle beetween central vertical line and trail
-
- local pos = vmath.vector3(360-math.sin(angle)*350, 0, 0)
- local speed = vmath.vector3(strength*math.sin(angle), strength*math.cos(angle), 0)
- table.insert(instances,
- start_fireworks(trail, splat,
- pos, speed,
- 1.2+math.random()*0.5
- )
- )
- end
- function init(self)
- single_shot()
- timer.delay(3, true, single_shot)
- msg.post(".", "acquire_input_focus")
- end
- function update(self, dt)
- for i, val in ipairs(instances) do
- if not val.bang then
- table.remove(instances, i)
- else
- val:update(dt)
- end
- end
- end
- function on_input(self, action_id, action)
- if action_id == hash("mouse_button_left") and action.pressed then
- single_shot()
- end
- end
|