-
Notifications
You must be signed in to change notification settings - Fork 0
/
flammable.lua
158 lines (128 loc) · 5 KB
/
flammable.lua
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
physics = require "physics"
math = require "math"
table = require "table"
utils = require "utils"
module(..., package.seeall)
--all flammable objects
flammable_list = {}
--the superclass for all flammable objects
flammable = {}
--takes an image and converts it to a flammable physics object
--if object_shape is defined, it is used as the shape of the physics
--object; otherwise, the object will be defined as a circle or rectangle
--depending on whether circular is specified
function flammable:new(image, extra_physics_params)
instance = {body=image}
instance.body.flammable = instance
--determine the physics parameters, using default values unless the
--values are overwritten by extra_physics_params
local physics_params = {density = 3, friction = 5, bounce = 0}
if extra_physics_params ~= nil then
for k, v in pairs(extra_physics_params) do
physics_params[k] = v
end
end
--convert the image to a physics object
physics.addBody(instance.body, "dynamic", physics_params)
instance.body.linearDamping = 3
instance.body.angularDamping = 3
--current_heat increases by heat_increase_rate units per second
--if this is touching a burning object; when current_heat
--passes flash_point, this object starts to burn
instance.current_heat = 0
instance.heat_increase_rate = 20
instance.flash_point = 20
--once an object catches on fire, its temperature increases until
--it reaches burn_temperature
instance.burn_temperature = 25
--when this object is on fire, it burns up and eventually is removed
--health represents how long it has left, and min_burn_rate/max_burn_rate
--represent how slowly/quickly it can burn (if it is just barely at
--the flash point, it will burn at min_burn_rate, whereas if it is
--hotter, it will burn at up to max_burn_rate)
instance.health = 80
instance.min_burn_rate = 2
instance.max_burn_rate = 5
--if this object gains heat but not enough to catch fire, it will
--start to cool off after this many seconds away from heat sources
instance.cool_off_delay = 2
instance.time_away_from_heat = 0
instance.nearby_objects = {}
setmetatable(instance, {__index = flammable})
instance.body:addEventListener("collision", instance)
table.insert(flammable_list, instance)
return instance
end
--this will be called whenever a flammable object collides with
--or stops touching another object
function flammable:collision(event)
local other = event.other
--ignore objects that aren't flammable
if other.flammable == nil then
return
end
--other.flammable is actually a reference to the flammable data
--structure associated with that body
if(event.phase == "began") then
table.insert(self.nearby_objects, other.flammable)
else
table.remove(self.nearby_objects, utils.index_of(
self.nearby_objects, other.flammable))
end
end
--removes a flammable object when it fully burns up
function flammable:burn_up()
self.body:removeSelf()
table.remove(flammable_list, utils.index_of(flammable_list, self))
local index = 0
for i, object in ipairs(flammable_list) do
index = utils.index_of(object.nearby_objects, self)
if index > 0 then
table.remove(object.nearby_objects, index)
end
end
end
--increases a flammable object's heat if it is touching burning objects
function flammable:on_enter_frame(elapsed_time)
local highest_heat_value = 0
--find the hottest burning object touching this
for i, object in ipairs(self.nearby_objects) do
if object.current_heat > highest_heat_value and
object.current_heat >= object.flash_point then
highest_heat_value = object.current_heat
end
end
--if this is burning, its heat should increase up to burn_temperature
if self.current_heat >= self.flash_point
and self.burn_temperature > highest_heat_value then
highest_heat_value = self.burn_temperature
end
--increase this object's heat to approach the highest heat value found
if highest_heat_value > self.current_heat then
self.current_heat = math.min(highest_heat_value,
self.current_heat +
self.heat_increase_rate * elapsed_time)
end
--if this is on fire, decrease its health
if self.current_heat >= self.flash_point then
self.health = self.health - math.max(self.min_burn_rate,
math.min(self.max_burn_rate,
self.current_heat - self.flash_point))
if self.health <= 0 then
self:burn_up()
end
--if this isn't on fire and it isn't next to a burning object,
--let it cool off
elseif highest_heat_value == 0 then
self.time_away_from_heat = self.time_away_from_heat + elapsed_time
if self.time_away_from_heat >= self.cool_off_delay then
self.current_heat = math.max(0, self.current_heat
- self.heat_increase_rate * 0.7 * elapsed_time)
end
end
end
--increases the flammable object's heat to match the given heat value
function flammable:apply_heat(heat)
--TODO: increase this based on heat_increase_rate rather than all the way
self.current_heat = heat
end