Skip to content

Instantly share code, notes, and snippets.

@a327ex
Created January 10, 2020 16:26
Show Gist options
  • Save a327ex/1b2ac2a19cac37617cd9f605a115aec0 to your computer and use it in GitHub Desktop.
Save a327ex/1b2ac2a19cac37617cd9f605a115aec0 to your computer and use it in GitHub Desktop.
function init()
white = {1, 1, 1, 1}
black = {0, 0, 0, 1}
red = {1.0, 0.1, 0.2, 1}
doodle = g.newShader("doodle.frag")
doodle:send("doodle_max_offset", {0.0020, 0.0020})
doodle:send("doodle_noise_scale", {6, 8})
doodle:send("doodle_frame_count", 8)
doodle:send("doodle_frame_time", 0.2)
combine = g.newShader("combine.frag")
doodle_canvas = g.newCanvas(gw, gh)
game_canvas = g.newCanvas(gw, gh)
new_animation("hit1", 96, 47)
new_animation("smoke1", 50, 50, {1})
player = Player(gw/2, gh - 6)
projectiles = {}
effects = {}
enemies = {}
ui = {}
ammo_bars = {}
hp_bars = {}
timer:every(2, function()
table.insert(enemies, Enemy1(rng:float(60, gw - 60), -60))
end)
local h = (gh - 55)
local bh = h/player.max_ammo
for i = 1, player.max_ammo do table.insert(ammo_bars, UIBar(gw - 24, 50 + (i-1)*(bh), bh - 3, "ammo")) end
player_ammo_ui = PlayerAmmoUI(gw - 24, 22)
local hh = (gh/2)/player.max_hp
for i = 1, player.max_hp do table.insert(hp_bars, UIBar(24, 55 + (i-1)*(hh), hh - 3, "hp")) end
player_hp_ui = PlayerHPUI(24, 22)
end
function update(dt)
doodle:send("time", time)
player:update(dt)
update_objects(projectiles, dt)
update_objects(enemies, dt)
update_objects(effects, dt)
update_objects(ammo_bars, dt)
update_objects(hp_bars, dt)
player_ammo_ui:update(dt)
player_hp_ui:update(dt)
end
function draw()
g.setCanvas(game_canvas)
g.clear()
g.setColor(white)
camera:attach()
draw_objects(projectiles)
draw_objects(enemies)
draw_objects(effects)
draw_objects(ammo_bars)
draw_objects(hp_bars)
player_ammo_ui:draw()
player_hp_ui:draw()
player:draw()
camera:detach()
g.setCanvas()
g.setCanvas(doodle_canvas)
g.clear()
g.setColor(white)
g.setShader(doodle)
g.draw(game_canvas, 0, 0, 0, 1, 1)
g.setShader()
g.setCanvas()
g.setColor(1, 1, 1, 1)
g.setBlendMode("alpha", "premultiplied")
g.draw(doodle_canvas, 0, 0, 0, sx, sy)
g.setBlendMode("alpha")
end
Player = Class:extend()
function Player:new(x, y)
self.x, self.y = x, y
self.rs = 16
self.sx, self.sy = 1, 1
self.e1x, self.e1y = -self.rs/2.5, -self.rs/2.5
self.e2x, self.e2y = self.rs/2.5, -self.rs/2.5
self.e1ox, self.e1oy = 0, 0
self.e2ox, self.e2oy = 0, 0
self.r = 0
self.scale_spring = Spring(1)
timer:everyi(2, function() timer:tween(1, self, {sx = 1.025, sy = 1.025}, cubic_in, function() timer:tween(1, self, {sx = 1, sy = 1}, linear) end) end)
self.rso = 0; timer:everyi({0.1, 0.2}, function() self.rso = rng:float(-1, 1) end)
self.attack_spring = Spring(1)
self.attack_timer = 0
self.attack_pulse_timer = 0
self.attack_cd = 0.06
self.shape = HC.circle(self.x, self.y, 16)
self.shape.parent = self
self.max_ammo = 35
self.ammo = self.max_ammo
self.max_hp = 10
self.hp = self.max_hp
self.reloading = false
self.reload_timer = 0
self.reload_cd = 0.6
self.reload_spring = Spring(1)
end
function Player:update(dt)
self.scale_spring:update(dt)
self.attack_spring:update(dt)
self.reload_spring:update(dt)
self.s = self.scale_spring.x*self.attack_spring.x*self.reload_spring.x
self.r = angle_to_mouse(self.x, self.y)
if m.isDown(1) and not m.isDown(2) then
self.attack_timer = self.attack_timer + dt
if self.attack_timer > self.attack_cd and self.ammo > 0 then
self.attack_timer = 0
local r = rng:float(-6, 6)
local v = rng:float(600, 700)
table.insert(projectiles, Projectile(self.x + self.s*1.5*self.rs*math.cos(self.r) + r*math.cos(self.r + math.pi/2), self.y + self.s*1.5*self.rs*math.sin(self.r) + r*math.sin(self.r + math.pi/2), v*math.cos(self.r), v*math.sin(self.r)))
self.scale_spring:pull(0.1)
for i = 1, 4 do table.insert(effects, EllipseParticle(self.x + self.s*1.5*self.rs*math.cos(self.r), self.y + self.s*1.5*self.rs*math.sin(self.r), self.r + rng:float(-math.pi/2, math.pi/2), rng:float(100, 400))) end
table.insert(effects, ShootCircle(self.x + self.s*1.5*self.rs*math.cos(self.r), self.y + self.s*1.5*self.rs*math.sin(self.r)))
table.insert(effects, ShootCapsule(self.x + self.s*1.5*self.rs*math.cos(self.r), self.y + self.s*1.5*self.rs*math.sin(self.r), self.r + rng:float(-math.pi/4, math.pi/4), rng:float(100, 300)))
player_ammo_ui:jiggle()
ammo_bars[self.ammo]:spend()
self.ammo = self.ammo - 1
end
self.attack_pulse_timer = self.attack_pulse_timer + dt
if self.attack_pulse_timer > 4*self.attack_cd then
self.attack_pulse_timer = 0
self.attack_spring:pull(0.25)
end
end
local r = math.deg(self.r)
local mx = camera:get_mouse_position()
local rd = 1
if mx > self.x then rd = -1 else rd = 1 end
if mouse_pressed(2) then
self.reloading = true
self.reload_spring:pull(0.4)
self.reload_text = ReloadText(self.x + rd*62, self.y - 14, self.reload_cd, rd*math.pi/32)
table.insert(effects, self.reload_text)
end
if mouse_released(2) then
self.reloading = false
self.reload_spring:pull(0.2)
if self.reload_text then
self.reload_text:die()
self.reload_text = nil
end
end
if self.reloading then
self.reload_timer = self.reload_timer + dt
if self.reload_text then self.reload_text.t = self.reload_timer/self.reload_cd end
player_ammo_ui.t = self.reload_timer/self.reload_cd
if self.reload_timer > self.reload_cd then
for i = 1, self.max_ammo do ammo_bars[i]:refresh() end
player_ammo_ui:refresh()
table.insert(effects, CircleEffect(self.x, self.y, self.s*self.rs))
self.reload_spring:pull(0.4)
self.reload_timer = 0
self.ammo = self.max_ammo
if self.reload_text then
self.reload_text:die()
self.reload_text = nil
end
end
else self.reload_timer = 0 end
self.shape:moveTo(self.x, self.y)
end
function Player:draw()
push(self.x, self.y, 0, self.s*self.sx, self.s*self.sy)
circle(self.x, self.y, self.rs + self.rso, 2)
pop()
circlef(self.x + self.s*1.5*self.rs*math.cos(self.r), self.y + self.s*1.5*self.rs*math.sin(self.r), 3)
end
function Player:hit(damage)
self.hp = self.hp - 1
slow(0.5, 0.5)
flash(2, black)
end
PlayerHPUI = Class:extend()
function PlayerHPUI:new(x, y)
self.timer = Timer()
self.x, self.y = x, y
self.sx, self.sy = 1.25, 1.25
self.scale_spring = Spring(1)
end
function PlayerHPUI:update(dt)
self.timer:update(dt)
self.scale_spring:update(dt)
self.hp = player.hp
self.max_hp = player.max_hp
end
function PlayerHPUI:draw()
push(self.x, self.y, 0, self.scale_spring.x*self.sx, self.scale_spring.x*self.sy)
draw_text(self.hp, self.x, self.y, 0, 1, 1, font_medium)
pop()
end
function PlayerHPUI:refresh()
self.scale_spring:pull(0.5)
end
function PlayerHPUI:jiggle()
self.scale_spring:pull(0.2)
end
PlayerAmmoUI = Class:extend()
function PlayerAmmoUI:new(x, y)
self.timer = Timer()
self.x, self.y = x, y
self.sx, self.sy = 1.25, 1.25
self.oy = 0
self.scale_spring = Spring(1)
self.timer:tween(0.1, self, {sx = 1, sy = 1}, cubic_in, function() self.sx, self.sy = 1, 1 end)
end
function PlayerAmmoUI:update(dt)
self.timer:update(dt)
self.scale_spring:update(dt)
self.ammo = player.ammo
self.max_ammo = player.max_ammo
end
function PlayerAmmoUI:draw()
if player.reloading then
if player.reload_text then
if not player.reload_text.visible then return end
end
end
push(self.x, self.y + self.oy, 0, self.scale_spring.x*self.sx, self.scale_spring.x*self.sy)
draw_text(self.ammo, self.x, self.y + self.oy, 0, 1, 1, font_medium)
pop()
if player.reloading then
local x = self.x
local y1
for i = 1, #ammo_bars do
if ammo_bars[i].spent then
y1 = ammo_bars[i].y
break
end
end
local y2 = ammo_bars[#ammo_bars].y
if y1 then
g.setLineWidth(4)
g.line(x, y1, x, y1 + (y2-y1)*self.t)
g.setLineWidth(1)
end
end
end
function PlayerAmmoUI:refresh()
self.t = 0
self.scale_spring:pull(0.5)
end
function PlayerAmmoUI:jiggle()
self.scale_spring:pull(0.2)
end
UIBar = Class:extend()
function UIBar:new(x, y, h, type)
self.type = type
self.timer = Timer()
self.x, self.y = x, y
self.sx, self.sy = 1.25, 1.25
self.w = 16
self.ow = 16
self.h = h
self.spent = false
self.scale_spring = Spring(1)
self.timer:tween(0.1, self, {sx = 1, sy = 1}, cubic_in, function() self.sx, self.sy = 1, 1 end, "refreshs")
end
function UIBar:update(dt)
self.timer:update(dt)
self.scale_spring:update(dt)
end
function UIBar:draw()
if self.type == "ammo" then
if player.reloading then
if player.reload_text then
if not player.reload_text.visible then return end
end
end
end
push(self.x, self.y, 0, self.sx*self.scale_spring.x, self.sy*self.scale_spring.x)
if self.fake_spent then rect(self.x, self.y, self.w, self.h, nil, nil, 2, white)
else rectf(self.x, self.y, self.w, self.h, nil, nil, white) end
pop()
end
function UIBar:refresh()
self.spent = false
self.fake_spent = false
self.scale_spring:pull(0.4)
self.timer:tween(0.05, self, {w = self.ow}, linear, function() self.w = self.ow end, "refresh")
end
function UIBar:spend()
self.spent = true
self.scale_spring:pull(0.4)
self.timer:tween(0.05, self, {w = 0}, linear, function() self.w = 0 end, "spend")
table.insert(effects, ShootCircle(self.x, self.y))
table.insert(effects, ShootCapsule(self.x, self.y, rng:float(-math.pi/4, 0), rng:float(50, 150)))
end
function UIBar:fake_spend()
self.fake_spent = true
self.scale_spring:pull(0.4)
end
function UIBar:spend2()
self.spent = true
self.scale_spring:pull(0.4)
table.insert(effects, ShootCircle(self.x, self.y, 24))
self.timer:tween(0.1, self, {w = 0}, linear, function() self.w = 0 end, "spend")
for i = 1, 8 do table.insert(effects, DeathParticle(self.x, self.y, rng:float(0, 2*math.pi), rng:float(100, 400))) end
end
CircleEffect = Class:extend()
function CircleEffect:new(x, y, r, color)
self.x, self.y = x, y
self.r = r
self.lw = 8
self.color = color or white
timer:tween(0.15, self, {r = 4*self.r, lw = 1}, linear, function() self.dead = true end)
end
function CircleEffect:update(dt)
end
function CircleEffect:draw()
circle(self.x, self.y, self.r, self.lw, self.color)
end
ReloadText = Class:extend()
function ReloadText:new(x, y, duration, r)
self.timer = Timer()
self.x, self.y = x, y
self.r = r
self.sx, self.sy = 1, 1
self.characters = {}
self.visuals = {1, 1, 1, 1, 1, 1}
self.visible = true
self.font = font_medium
self.w, self.h = self.font:getWidth("RELOAD"), self.font:getHeight()
self.scale_spring = Spring(1)
self.scale_spring:pull(0.15)
self.t = 0
local characters = {"R", "E", "L", "O", "A", "D"}
for i = 1, 6 do
self.timer:after((i-1)*(0.15/6), function()
self.visuals[i] = 3
if self.visuals[i-1] then self.visuals[i-1] = 2 end
if self.visuals[i-2] then self.visuals[i-2] = 1 end
table.insert(self.characters, characters[i])
end)
end
self.timer:after(0.15, function()
self.visuals = {1, 1, 1, 1, 1, 1}
self.timer:every(0.05, function() self.visible = not self.visible end, math.floor((duration - 0.15)/0.05))
self.timer:after((duration - 0.15), function() self.visible = true end)
self.timer:every(0.035, function()
local random_characters = "0123456789abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWYXZ"
for i, c in ipairs(self.characters) do
if rng:bool(10) then
local r = rng:int(1, #random_characters)
self.characters[i] = random_characters:sub(r, r)
end
if rng:bool(10) then self.visuals[i] = rng:int(1, 4) end
end
end, math.floor((duration - 0.15)/0.035))
end)
end
function ReloadText:update(dt)
self.timer:update(dt)
self.scale_spring:update(dt)
end
function ReloadText:draw()
if not self.visible then return end
local w, h = 0, 0
local x, y = self.x - self.w/2, self.y - self.h/2
g.setFont(self.font)
push(self.x, self.y, self.r, self.scale_spring.x*self.sx, self.scale_spring.x*self.sy)
for i = 1, #self.characters do
local cw, ch = self.font:getWidth(self.characters[i]), self.font:getHeight()
if self.visuals[i] == 1 then
g.setColor(white)
g.print(self.characters[i], x + w, y + h)
elseif self.visuals[i] == 2 then
g.setColor(white)
rectf(x + w + cw/2, y + h + ch/2, cw, ch)
g.setColor(black)
g.print(self.characters[i], x + w, y + h)
elseif self.visuals[i] == 3 then
g.setColor(white)
rectf(x + w + cw/2, y + h + ch/2, cw, ch)
elseif self.visuals[i] == 4 then
g.setColor(black)
rectf(x + w + cw/2, y + h + ch/2, cw, ch)
end
w = w + self.font:getWidth(self.characters[i])
end
g.setColor(white)
g.rectangle("fill", x, y - 5, self.w*self.t, 3)
pop()
end
function ReloadText:die()
self.dead = true
end
RefreshEffect = Class:extend()
function RefreshEffect:new(x, y, w, h)
self.x, self.y = x, y
self.w, self.h = w, h
self.oy = h/3
timer:tween(0.15, self, {h = 0}, linear, function() self.dead = true end)
end
function RefreshEffect:update(dt)
end
function RefreshEffect:draw()
g.rectangle("fill", self.x - self.w/2, self.y - self.oy, self.w, self.h)
end
Projectile = Class:extend()
function Projectile:new(x, y, vx, vy, opts)
for k, v in pairs(opts or {}) do self[k] = v end
self.x, self.y = x, y
self.vx, self.vy = vx, vy
self.sx, self.sy = 1, 1
self.w, self.h = 16, 4
self.shape = HC.rectangle(self.x - self.w/2, self.y - self.h/2, self.w, self.h)
self.shape.parent = self
self.damage = rng:int(40, 60)
end
function Projectile:update(dt)
self.vy = self.vy + 300*dt
self.x = self.x + self.vx*dt
self.y = self.y + self.vy*dt
self.r = math.atan2(self.vy, self.vx)
if self.x < 0 then self:die(0) end
if self.x > gw then self:die(math.pi) end
if self.y < 0 then self:die(math.pi/2) end
if self.y > gh then self:die(-math.pi/2) end
self.shape:moveTo(self.x, self.y)
self.shape:setRotation(self.r)
end
function Projectile:draw()
push(self.x, self.y, self.r, self.sx, self.sy)
rectf(self.x, self.y, self.w, self.h, nil, nil, white)
pop()
end
function Projectile:die(r)
self.dead = true
for i = 1, 2 do table.insert(effects, EllipseParticle(self.x, self.y, (r or math.atan2(-self.vy, -self.vx)) + rng:float(-math.pi/4, math.pi/4), rng:float(100, 300))) end
table.insert(effects, ShootCircle(self.x, self.y))
end
Enemy1 = Class:extend()
function Enemy1:new(x, y)
self.timer = Timer()
self.x, self.y = x, y
self.w = 16
self.r = 0
self.sx, self.sy = 1, 1
self.d = 1
self.v = 100
self.vs = {}
local r = 0
for i = 1, 8 do
local w = rng:float(0.95, 1.05)
self.vs[2*(i-1)+1] = self.w*w*math.cos(r)
self.vs[2*i] = self.w*w*math.sin(r)
r = r + math.pi/4
end
self.vr = rng:float(-4*math.pi, 4*math.pi)
self.shape = HC.polygon(unpack(to_polygon(self.x, self.y, self.vs)))
self.shape.parent = self
self.hp = 800
end
function Enemy1:update(dt)
self.timer:update(dt)
self.y = self.y + self.d*self.v*dt
self.r = self.r + self.vr*dt
self.shape:moveTo(self.x, self.y)
self.shape:setRotation(self.r)
for other in pairs(HC.neighbors(self.shape)) do
if other.parent:is(Projectile) then
local collides = self.shape:collidesWith(other)
if collides then
self:hit(other.parent.damage, other.parent.r)
other.parent:die()
table.insert(effects, HitEffect(other.parent.x, other.parent.y))
end
end
end
if self.y > gh then
self.fast = true
self.d = -1
self.v = 150
self.y = gh - 2
table.insert(effects, DeathCircle(self.x, self.y, 2*self.w, red))
table.insert(effects, CircleEffect(self.x, self.y, self.w, red))
for i = player.max_hp, 1, -1 do
if not hp_bars[i].spent and not hp_bars[i].fake_spent then
hp_bars[i]:fake_spend()
break
end
end
flash(1, black)
end
if self.y < 0 and self.fast then
self.dead = true
player:hit(1)
table.insert(effects, DeathCircle(self.x, self.y, 2*self.w, red))
table.insert(effects, CircleEffect(self.x, self.y, self.w, red))
for i = player.max_hp, 1, -1 do
if hp_bars[i].fake_spent and not hp_bars[i].spent then
hp_bars[i]:spend2()
break
end
end
end
end
function Enemy1:draw()
if self.y > gh + 64 then return end
local color = red
if self.hit_flash then color = white end
push(self.x, self.y, self.r, self.sx, self.sy)
polygon(to_polygon(self.x, self.y, self.vs), 2, color)
pop()
end
function Enemy1:hit(damage, r)
self.sx, self.sy = 1.35, 1.35
self.hit_flash = true
self.timer:tween(0.1, self, {sx = 1, sy = 1}, linear, function() self.hit_flash = false end, "hit")
self.hp = self.hp - damage
if self.hp <= 0 then
self.dead = true
table.insert(effects, DeathCircle(self.x, self.y, 2*self.w))
for i = 1, 4 do table.insert(effects, DustParticle(self.x, self.y, white)) end
if self.fast then
for i = 1, player.max_hp do
if hp_bars[i].fake_spent then
hp_bars[i]:refresh()
break
end
end
end
end
end
DamageNumber = Class:extend()
function DamageNumber:new(x, y, vx, vy, t)
self.x, self.y = x, y
self.sx, self.sy = 1.00, 1.00
self.vx, self.vy = vx, vy
self.t = t
self.scale_spring = Spring(1)
self.scale_spring:pull(0.25)
self.r = 0
-- if vx > 0 then self.vr = rng:float(2*math.pi, 4*math.pi) else self.vr = rng:float(-4*math.pi, -2*math.pi) end
timer:after(0.25, function()
timer:tween(0.05, self, {sx = 0, sy = 0}, linear, function() self.dead = true end)
end)
end
function DamageNumber:update(dt)
self.scale_spring:update(dt)
self.vy = self.vy + 400*dt
self.x = self.x + self.vx*dt
self.y = self.y + self.vy*dt
-- self.r = self.r + self.vr*dt
end
function DamageNumber:draw()
push(self.x, self.y, self.r, 1.25*self.scale_spring.x*self.sx, 1.25*self.scale_spring.x*self.sy)
draw_text(self.t, self.x, self.y, 0, 1, 1, font_small)
pop()
end
HitEffect = Class:extend()
function HitEffect:new(x, y)
self.x, self.y = x, y
self.r = rng:float(0, 2*math.pi)
self.animation = Animation(0.025, get_animation_frames("hit1"), "once", {[0] = function() self.dead = true end})
self.sx, self.sy = 1.2, 1.2
timer:tween(0.025*get_animation_frames("hit1"), self, {sx = 1, sy = 1}, linear)
end
function HitEffect:update(dt)
self.animation:update(dt)
end
function HitEffect:draw()
draw_animation("hit1", self.animation:get_current_frame(), self.x, self.y, self.r, 1.35*self.sx, 1.35*self.sy)
end
DustParticle = Class:extend()
function DustParticle:new(x, y, color)
self.x, self.y = x, y
self.animation = Animation(1, get_animation_frames("smoke1"), "once")
self.color = color or red
self.sx, self.sy = 0, 0
self.v = rng:float(100, 220)
self.r = rng:float(0, 2*math.pi)
self.rs = 0
self.vr = rng:float(0, 2*math.pi)
timer:after(0.1, function() self.color = color or white end)
timer:tween(rng:float(0.04, 0.06), self, {sx = 0.7, sy = 0.7}, cubic_in_out, function()
timer:tween(rng:float(0.3, 0.4), self, {sx = 0, sy = 0, v = 0}, linear, function() self.dead = true end)
end)
end
function DustParticle:update(dt)
self.animation:update(dt)
self.rs = self.rs + self.vr*dt
self.x, self.y = self.x + self.v*math.cos(self.r)*dt, self.y + self.v*math.sin(self.r)*dt
end
function DustParticle:draw()
g.setShader(combine)
g.setColor(self.color)
draw_animation("smoke1", self.animation:get_current_frame(), self.x, self.y, self.rs, 3.5*self.sx, 3.5*self.sy)
g.setShader()
g.setColor(white)
end
AnimatedEffect = Class:extend()
function AnimatedEffect:new(x, y, name, delay, loop_mode)
self.x, self.y = x, y
self.r, self.sx, self.sy = 0, 1, 1
self.name = name
self.delay = delay
self.loop_mode = loop_mode or "once"
self.animation = Animation(delay, get_animation_frames(name), self.loop_mode, {[0] = function() self.dead = true end})
end
function AnimatedEffect:update(dt)
self.animation:update(dt)
end
function AnimatedEffect:draw()
draw_animation(self.name, self.animation:get_current_frame(), self.x, self.y, self.r, self.sx, self.sy)
end
EllipseParticle = Class:extend()
function EllipseParticle:new(x, y, r, v)
self.x, self.y = x, y
self.r = r
self.v = v
self.w, self.h = 9, 3
timer:tween({0.2, 0.5}, self, {v = 0}, linear, function() self.dead = true end)
end
function EllipseParticle:update(dt)
self.x = self.x + self.v*math.cos(self.r)*dt
self.y = self.y + (self.v*math.sin(self.r) + 100)*dt
self.w = remap(self.v, 0, 400, 0, 9)
self.h = remap(self.v, 0, 400, 0, 3)
end
function EllipseParticle:draw()
push(self.x, self.y, math.atan2(self.v*math.sin(self.r) + 100, self.v*math.cos(self.r)))
ellipsef(self.x, self.y, self.w, self.h)
pop()
end
DeathCircle = Class:extend()
function DeathCircle:new(x, y, r, color)
self.x, self.y = x, y
self.r = r
self.color = color or white
timer:tween(0.26, self, {r = 0}, cubic_in_out, function() self.dead = true end)
end
function DeathCircle:update(dt)
end
function DeathCircle:draw()
circlef(self.x, self.y, self.r, self.color)
end
DeathParticle = Class:extend()
function DeathParticle:new(x, y, r, v, color)
self.x, self.y = x, y
self.r = r
self.v = v
self.w, self.h = 14, 4.5
self.color = color or white
timer:tween({0.2, 0.4}, self, {v = 0}, linear, function() self.dead = true end)
end
function DeathParticle:update(dt)
self.x = self.x + self.v*math.cos(self.r)*dt
self.y = self.y + (self.v*math.sin(self.r) + 0)*dt
self.w = remap(self.v, 0, 400, 0, 14)
self.h = remap(self.v, 0, 400, 0, 4.5)
end
function DeathParticle:draw()
push(self.x, self.y, math.atan2(self.v*math.sin(self.r) + 0, self.v*math.cos(self.r)))
rectf(self.x, self.y, self.w, self.h, nil, nil, self.color)
pop()
end
ShootCircle = Class:extend()
function ShootCircle:new(x, y, rs)
self.x, self.y = x, y
self.rs = rs or 12
timer:tween(0.1, self, {rs = 0}, linear, function() self.dead = true end)
end
function ShootCircle:update(dt)
end
function ShootCircle:draw()
circlef(self.x, self.y, self.rs)
end
ShootCapsule = Class:extend()
function ShootCapsule:new(x, y, r, v)
self.x, self.y = x, y
self.vx, self.vy = v*math.cos(r), v*math.sin(r)
self.w, self.h = 6, 3
self.r = 0
self.vr = rng:float(-4*math.pi, 4*math.pi)
end
function ShootCapsule:update(dt)
self.vy = self.vy + 600*dt
self.x = self.x + self.vx*dt
self.y = self.y + self.vy*dt
self.r = self.r + self.vr*dt
if self.y > gh or self.y < 0 or self.x > gw or self.x < 0 then
self.dead = true
table.insert(effects, ShootCircle(self.x, self.y))
end
end
function ShootCapsule:draw()
push(self.x, self.y, self.r)
rectf(self.x, self.y, self.w, self.h)
pop()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment