1--[[ 2 3omns - old-school arcade-style tile-based bomb-dropping deathmatch jam 3 <https://chazomaticus.github.io/3omns/> 4 base - base game logic for 3omns 5 Copyright 2014-2015 Charles Lindsay <chaz@chazomatic.us> 6 7 3omns is free software: you can redistribute it and/or modify it under the 8 terms of the GNU General Public License as published by the Free Software 9 Foundation, either version 3 of the License, or (at your option) any later 10 version. 11 12 3omns is distributed in the hope that it will be useful, but WITHOUT ANY 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License along with 17 3omns. If not, see <http://www.gnu.org/licenses/>. 18]] 19 20local obj = require("object") 21local Entity = require("entities.entity") 22 23local Bomn = obj.class("Bomn", Entity) 24package.loaded[...] = Bomn 25 26local core = require("core") 27local util = require("util") 28local serial = require("serial") 29local Blast = require("sprites.blast") 30 31 32Bomn.TIME = 3 33Bomn.RADIUS = 8 34 35Bomn.ANIMATION = nil 36 37local function init_animation() 38 if Bomn.ANIMATION then return end 39 40 Bomn.ANIMATION = { 41 {time = 5.0, image = core.IMAGES.BOMNS[5], z_order = 2}, 42 {time = 4.75, image = nil, z_order = 2}, 43 {time = 4.5, image = core.IMAGES.BOMNS[#core.IMAGES.BOMNS], z_order = 2}, 44 {time = 4.25, image = nil, z_order = 2}, 45 {time = 4.0, image = core.IMAGES.BOMNS[4], z_order = 2}, 46 {time = 3.75, image = nil, z_order = 2}, 47 {time = 3.5, image = core.IMAGES.BOMNS[#core.IMAGES.BOMNS], z_order = 2}, 48 {time = 3.25, image = nil, z_order = 2}, 49 {time = 3.0, image = core.IMAGES.BOMNS[3], z_order = 2}, 50 {time = 2.75, image = nil, z_order = 2}, 51 {time = 2.5, image = core.IMAGES.BOMNS[#core.IMAGES.BOMNS], z_order = 2}, 52 {time = 2.25, image = nil, z_order = 2}, 53 {time = 2.0, image = core.IMAGES.BOMNS[2], z_order = 2}, 54 {time = 1.75, image = nil, z_order = 2}, 55 {time = 1.5, image = core.IMAGES.BOMNS[#core.IMAGES.BOMNS], z_order = 2}, 56 {time = 1.25, image = nil, z_order = 2}, 57 {time = 1.0, image = core.IMAGES.BOMNS[1], z_order = 2}, 58 {time = 0.75, image = nil, z_order = 2}, 59 {time = 0.5, image = core.IMAGES.BOMNS[#core.IMAGES.BOMNS], z_order = 2}, 60 {time = 0.4, image = nil, z_order = 2}, 61 {time = 0.3, image = core.IMAGES.BOMNS[#core.IMAGES.BOMNS], z_order = 2}, 62 {time = 0.2, image = nil, z_order = 2}, 63 {time = 0.1, image = core.IMAGES.BOMNS[#core.IMAGES.BOMNS], z_order = 2}, 64 } 65end 66 67function Bomn:init_base(entities, backing) 68 init_animation() 69 70 Entity.init_base(self, entities, backing) 71 72 self.solid = false 73 self.time = Bomn.TIME 74 self.dude_id = nil 75 76 self:animate(backing) 77end 78 79function Bomn:init(entities, pos, dude_id) 80 Entity.init(self, entities, pos, 1) 81 82 self.dude_id = dude_id 83end 84 85function Bomn:serialize() 86 return serial.serialize_number(self.time) 87 .. serial.serialize_number(self.dude_id) 88end 89 90function Bomn:sync(serialized, start, backing) 91 self.time, start = serial.deserialize_number(serialized, start) 92 self.dude_id, start = serial.deserialize_number(serialized, start) 93 return start 94end 95 96function Bomn:animate(backing) 97 local frame = util.get_animation_frame(Bomn.ANIMATION, self.time) 98 self:set_image(frame.image, backing) 99 self:set_z_order(frame.z_order, backing) 100end 101 102-- TODO: if the server deletes this entity before it explodes, we get no 103-- explosion locally (though the effect is exactly the same, since it does 104-- happen on the server). 105function Bomn:explode(backing) 106 self:kill(backing) 107 108 local blasts = {} 109 local to_blast = {} 110 util.circle_contig(self.pos, Bomn.RADIUS, function(edge_pos) 111 util.line(self.pos, edge_pos, function(pos) 112 if not self.entities:walkable(pos) then 113 return false 114 end 115 116 local key = core.pos_key(pos) 117 if not blasts[key] then 118 blasts[key] = pos 119 end 120 121 local other = self.entities:get_entity(pos) 122 if other and other.solid then 123 if not to_blast[key] then 124 to_blast[key] = other 125 end 126 127 return core.pos_equal(pos, self.pos) 128 end 129 130 return not core.pos_equal(pos, edge_pos) 131 end) 132 end) 133 134 for _, e in pairs(to_blast) do 135 e:blasted(self, backing) 136 end 137 138 for _, p in pairs(blasts) do 139 Blast(self.entities.level, p) 140 end 141end 142 143function Bomn:bumped(dude, dude_backing) 144 if self.dude_id ~= dude.id then 145 self:kill() 146 end 147 return true 148end 149 150function Bomn:l3_update(backing, elapsed) 151 self.time = self.time - elapsed 152 if self.time <= 0 then 153 self:explode(backing) 154 return 155 end 156 157 self:animate(backing) 158end 159