_slashing_timer_sec = .12 _slash_animation_distance = 3 function slashing_particle(following) SlashingParticleBuilder = EntityBuilder:new(World) :b_type(Entities.Particle) :b_render_order(-1) :b_live_for(_slashing_timer_sec) :b_position(vec2(following.position)) :b_sprite_position(vec2(following.sprite_position)) :b_line_of_sight(vec2(following.line_of_sight)) :b_add_state( States.Equipped, { animation = { pos_y = { sequence = { 115, 116, 117 }, dt = _slashing_timer_sec / 3, reflect = vec2(true, true) }, neg_y = { sequence = { 115, 116, 117 }, dt = _slashing_timer_sec / 3 }, pos_x = { sequence = { 112, 113, 114 }, dt = _slashing_timer_sec / 3 }, neg_x = { sequence = { 112, 113, 114 }, dt = _slashing_timer_sec / 3, reflect = vec2(true, false) } } } ) :b_state(States.Equipped) function SlashingParticleBuilder:transition_state() end return SlashingParticleBuilder:build() end function fire() FireBuilder = EntityBuilder:new(World) function FireBuilder:transition_state() end FireBuilder:b_type(Entities.Fire) :b_position(vec2(50, 45)) :b_sprite_position(vec2(50, 45)) :b_line_of_sight(vec2(1, 0)) :b_render_order(1) :b_add_state( States.Hot, { animation = { sequence = { 195, 196, 197, 198 }, dt = 0.20 } } ) :b_add_state( States.Warm, { animation = { sequence = { 211, 212, 213, 214 }, dt = 0.20, } } ) :b_state(States.Hot) return FireBuilder:build() end function enemy() EnemyBuilder = EntityBuilder:new(World) function EnemyBuilder:transition_state() end EnemyBuilder:b_type(Entities.Enemy) :b_health(10) :b_position(vec2(30, -40)) :b_sprite_position(vec2(30, 40)) :b_line_of_sight(vec2(1, 0)) :b_render_order(1) :b_collidable() :b_add_state( States.Idle, { animation = { pos_y = { sequence = { 32, 33 }, dt = 1 }, neg_y = { sequence = { 32, 33 }, dt = 1 }, pos_x = { sequence = { 32, 33 }, dt = 1 }, neg_x = { sequence = { 32, 33 }, dt = 1, reflect = vec2(true, false) } } } ) :b_add_state( States.Walk, { animation = { pos_x = { sequence = { 32, 34 }, dt = 0.20 }, neg_x = { sequence = { 32, 34 }, dt = 0.20, reflect = vec2(true, false) }, pos_y = { sequence = { 32, 34 }, dt = 0.20 }, neg_y = { sequence = { 32, 34 }, dt = 0.20 } } } ) :b_state(States.Idle) return EnemyBuilder:build() end function wife() WifeBuilder = EntityBuilder:new(World) function WifeBuilder:transition_state() end WifeBuilder:b_type(Entities.Wife) :b_line_of_sight(vec2(1, 0)) :b_render_order(2) :b_collidable() :b_position(vec2(42, 42)) :b_sprite_position(vec2(42, 42)) :b_add_state( States.Idle, { animation = { pos_y = { sequence = { 16, 17 }, dt = 1 }, neg_y = { sequence = { 16, 17 }, dt = 1 }, pos_x = { sequence = { 16, 17 }, dt = 1 }, neg_x = { sequence = { 16, 17 }, dt = 1, reflect = vec2(true, false) } } } ) :b_state(States.Idle) return WifeBuilder:build() end function bow() BowBuilder = EntityBuilder:new(World) function BowBuilder:transition_state() end BowBuilder:b_type(Entities.Bow) :b_position(vec2(0, 0)) :b_sprite_position(vec2(0, 0)) :b_line_of_sight(vec2(1, 0)) :b_render_order(1) :b_collidable() :b_add_state( States.Equipped, { animation = { pos_y = { sequence = { 96 }, dt = 1, reflect = vec2(false, true) }, neg_y = { sequence = { 96 }, dt = 1 }, pos_x = { sequence = { 80 }, dt = 1 }, neg_x = { sequence = { 80 }, dt = 1, reflect = vec2(true, false) } } } ) :b_add_state( States.Drawn, { animation = { pos_y = { sequence = { 97 }, dt = 1, reflect = vec2(false, true) }, neg_y = { sequence = { 97 }, dt = 1 }, pos_x = { sequence = { 81 }, dt = 1 }, neg_x = { sequence = { 81 }, dt = 1, reflect = vec2(true, false) } } } ) :b_add_state( States.Drawing, { animation = BowBuilder.states[States.Equipped] } ) :b_state(States.Equipped) return BowBuilder:build() end function sword() _particle_distance = 4 _attack_burst_sec = 0.200 _sword_damage = { amount = 2, knockback = { magnitude = 300, time = 0.080 } } SwordBuilder = EntityBuilder:new(World) function SwordBuilder:transition_state() if button_just_pressed(5) and self.state == States.Equipped and self.state_stopwatch > _attack_burst_sec then self:transition_to(States.Slashing) self:equip(slashing_particle(self), _particle_distance) self.damage = _sword_damage elseif self.state == States.Slashing then self.damage = nil if (self.state_stopwatch > _slashing_timer_sec) then self:transition_to(States.Equipped) end end end SwordBuilder:b_type(Entities.Sword) :b_line_of_sight(vec2(1, 0)) :b_position(vec2(-50, 20)) :b_render_order(0) :b_collidable() :b_add_state( States.Equipped, { animation = { pos_y = { sequence = { 99 }, dt = 1, reflect = vec2(false, true) }, neg_y = { sequence = { 99 }, dt = 1, reflect = vec2(true, false) }, pos_x = { sequence = { 98 }, dt = 1 }, neg_x = { sequence = { 98 }, dt = 1, reflect = vec2(true, false) } } } ) :b_add_state( States.Slashing, { animation = { pos_y = { sequence = { 82, 98 }, dt = _slashing_timer_sec / 2, reflect = vec2(false, true) }, neg_y = { sequence = { 82, 98 }, dt = _slashing_timer_sec / 2, reflect = vec2(true, false) }, pos_x = { sequence = { 82, 99 }, dt = _slashing_timer_sec / 2, reflect = vec2(false, false)}, neg_x = { sequence = { 82, 99 }, dt = _slashing_timer_sec / 2, reflect = vec2(true, false) } } } ) :b_add_state( States.Idle, { animation = { sequence = { 98 }, dt = 1 } } ) :b_state(States.Idle) return SwordBuilder:build() end function block(pos, sprite) BlockBuilder = EntityBuilder:new(World) function BlockBuilder:transition_state() end BlockBuilder :b_type(Entities.Block) -- :b_line_of_sight(vec2(1, 0)) :b_render_order(2) :b_collidable() :b_position(vec2(pos)) :b_add_state( States.Idle, { animation = { sequence = { sprite }, dt = 1 } } ) :b_state(States.Idle) return BlockBuilder:build() end function door(pos) return block(pos, 193) end function building(pos) b = { { 0, 0, 2, 0 }, { 1, 1, 1, 1 }, { 1, 3, 1, 1 } } for y = 1,3 do for x = 1,4 do v = pos + (vec2(x - 1, y - 1) * SPRITE_DIMS) if b[y][x] == 1 then block(v, 192) elseif b[y][x] == 2 then block(v, 194) elseif b[y][x] == 3 then door(v) end end end end function player() PlayerBuilder = EntityBuilder:new(World) function PlayerBuilder:transition_state() if (self.velocity.x == 0 and self.velocity.y == 0) then self:transition_to(States.Idle) else self:transition_to(States.Walk) end end PlayerBuilder :b_type(Entities.Player) :b_line_of_sight(vec2(1, 0)) :b_render_order(2) :b_collidable() :b_position(vec2(30, 30)) :b_sprite_position(vec2(30, 30)) :b_add_state( States.Idle, { animation = { pos_y = { sequence = { 3, 19 }, dt = 1 }, neg_y = { sequence = { 6, 22 }, dt = 1 }, pos_x = { sequence = { 0, 1 }, dt = 1 }, neg_x = { sequence = { 0, 1 }, dt = 1, reflect = vec2(true, false) } } } ) :b_add_state( States.Walk, { animation = { pos_x = { sequence = { 2, 0 }, dt = 0.20 }, neg_x = { sequence = { 2, 0 }, dt = 0.20, reflect = vec2(true, false) }, pos_y = { sequence = { 4, 5 }, dt = 0.20 }, neg_y = { sequence = { 7, 8 }, dt = 0.20 } } } ) :b_state(States.Idle) return PlayerBuilder:build() end building(vec2(10, -90)) _enemy = enemy() _sword = sword() _wife = wife() -- _bow = bow() _fire = fire() _player = player() -- _player:equip(_sword) _walk_speed = 35 -- powerup increase? function handle_input() dpos = vec2(0, 0) if btn(0) then dpos.x -= 1 end if btn(1) then dpos.x += 1 end if btn(3) then dpos.y += 1 end if btn(2) then dpos.y -= 1 end _player.velocity = dpos:normal() * _walk_speed end function _init() end _camera = Camera:new(_player) _step_t = time() _continue = true function pause() _continue = false end function resume() _continue = true _step_t = time() end function _update60() -- clear here in case we want to print to screen outside of _draw cls(0) old_step = _step_t _step_t = time() step_dt = _step_t - old_step foreach(update_hooks, function(f) f(step_dt) end) handle_input() if not _continue then return end World.foreach(function(e) e:update(step_dt) end) run_collisions() World.cull_the_dead() end function _draw() -- TODO: FIX THIS -- World.sort(function(a, b) -- return b.render_order < a.render_order -- end) World.foreach(function(e) _camera:render(e) end) end