summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ai.lua64
-rw-r--r--collisions.lua34
-rw-r--r--dyl.lua11
-rw-r--r--dyl.p89
-rw-r--r--entity.lua46
-rw-r--r--map.lua9
-rw-r--r--math.lua9
-rw-r--r--util.lua9
8 files changed, 155 insertions, 36 deletions
diff --git a/ai.lua b/ai.lua
new file mode 100644
index 0000000..af1a807
--- /dev/null
+++ b/ai.lua
@@ -0,0 +1,64 @@
+AiController = {}
+AiController.__index = AiController
+
+function AiController:new(controlling)
+ return setmetatable({
+ controlling = controlling,
+ time = 0
+ }, AiController)
+end
+
+function AiController:follow(target)
+ self.target = target
+end
+
+function AiController:update(dt)
+ if self.target ~= nil and not self.target.knockback then
+ diff = self.target.position - self.controlling.position
+ self.controlling.velocity = diff:normal() * 20
+ self.controlling:transition_to(States.Walk)
+ end
+ self.time += dt
+ if self.time >= 5 then
+ self:shoot()
+ self.time = 0
+ end
+end
+
+function gliding_gun()
+ _glider_damage = { amount = 2, knockback = { magnitude = 300, time = 0.080 } }
+ GlidingGunBuilder = EntityBuilder:new(World)
+ function GlidingGunBuilder:transition_state()
+ end
+ return GlidingGunBuilder:b_type(Entities.Bullet)
+ :b_line_of_sight(vec2(1, 0))
+ :b_position(vec2(100, 100))
+ :b_render_order(0)
+ :b_collidable()
+ :b_live_for(25)
+ :b_velocity(vec2(-40, 0))
+ :b_collision_bounds(vec2(3, 4), vec2(5, 6))
+ :b_add_state(
+ States.Active, {
+ animation = {
+ pos_y = { sequence = { 75, 76, 77, 78 }, dt = 0.10 },
+ neg_y = { sequence = { 75, 76, 77, 78 }, dt = 0.10, reflect = vec2(true, true) },
+ pos_x = { sequence = { 75, 76, 77, 78 }, dt = 0.10 },
+ neg_x = { sequence = { 75, 76, 77, 78 }, dt = 0.10, reflect = vec2(true, true) }
+ }
+ }
+ )
+ :b_state(States.Active)
+ :build()
+end
+
+function AiController:shoot()
+ diff = (self.target.position - self.controlling.position):normal() * 50
+ a, b, c = gliding_gun(), gliding_gun(), gliding_gun()
+ a.position = vec2(self.controlling.position)
+ a.velocity = diff:clockwise_rotate(-0.05)
+ b.position = vec2(self.controlling.position)
+ b.velocity = diff:clockwise_rotate(0.05)
+ c.position = vec2(self.controlling.position)
+ c.velocity = diff
+end
diff --git a/collisions.lua b/collisions.lua
index f57554e..3d3ba46 100644
--- a/collisions.lua
+++ b/collisions.lua
@@ -1,10 +1,22 @@
function is_colliding(a, b)
- ax1, bx1 = a.position.x, b.position.x
- ax2, bx2 = ax1 + SPRITE_DIMS.x, bx1 + SPRITE_DIMS.y
- ay1, by1 = a.position.y, b.position.y
- ay2, by2 = ay1 + SPRITE_DIMS.y, by1 + SPRITE_DIMS.x
- return (ax1 < bx2 and ax2 > bx1
- and ay1 < by2 and ay2 > by1)
+ return (
+ a.top_left.x < b.bottom_right.x and a.bottom_right.x > b.top_left.x
+ and a.top_left.y < b.bottom_right.y and a.bottom_right.y > b.top_left.y
+ )
+end
+
+_hurts = {
+ vec2(Entities.Bullet, Entities.Player),
+ vec2(Entities.Sword, Entities.Enemy),
+}
+function hurts(a, b)
+ if b:is_in_iframe() then
+ return false
+ end
+ if not (a.damage and b.health) then
+ return false
+ end
+ return some(_hurts, function (v) return a.entity_type == v.x and b.entity_type == v.y end)
end
function handle_collision(a, b)
@@ -12,10 +24,7 @@ function handle_collision(a, b)
b:equip(a)
return
end
- if a.damage and b.health then
- if b:is_in_iframe() then
- return
- end
+ if hurts(a, b) then
b:take_damage(a.line_of_sight, a.damage)
end
end
@@ -27,7 +36,10 @@ function run_collisions()
if a.id == b.id then
goto continue
end
- if is_colliding(a, b) then
+ if is_colliding(
+ {top_left = (a.collision_bounds.top_left + a.position), bottom_right = (a.collision_bounds.bottom_right + a.position) },
+ {top_left = (b.collision_bounds.top_left + b.position), bottom_right = (b.collision_bounds.bottom_right + b.position) }
+ ) then
handle_collision(a, b)
end
::continue::
diff --git a/dyl.lua b/dyl.lua
index 398a6f7..116315b 100644
--- a/dyl.lua
+++ b/dyl.lua
@@ -152,7 +152,7 @@ end
function sword()
_particle_distance = 4
- _attack_burst_sec = 0.200
+ _attack_burst_sec = 0.300
_sword_damage = { amount = 2, knockback = { magnitude = 300, time = 0.080 } }
SwordBuilder = EntityBuilder:new(World)
function SwordBuilder:transition_state()
@@ -167,7 +167,7 @@ function sword()
end
end
end
- SwordBuilder:b_type(Entities.Sword)
+ return SwordBuilder:b_type(Entities.Sword)
:b_line_of_sight(vec2(1, 0))
:b_position(vec2(-50, 20))
:b_render_order(0)
@@ -200,7 +200,7 @@ function sword()
}
)
:b_state(States.Idle)
- return SwordBuilder:build()
+ :build()
end
function block(pos, sprite)
@@ -291,12 +291,13 @@ end
building(vec2(10, -90))
_enemy = enemy()
+_enemy.controller = AiController:new(_enemy)
_sword = sword()
_wife = wife()
-- _bow = bow()
_fire = fire()
_player = player()
--- _player:equip(_sword)
+_enemy.controller:follow(_player)
_walk_speed = 35 -- powerup increase?
function handle_input()
@@ -323,7 +324,7 @@ function resume()
_continue = true
_step_t = time()
end
-function _update60()
+function _update()
-- clear here in case we want to print to screen outside of _draw
cls(0)
diff --git a/dyl.p8 b/dyl.p8
index 610a367..23004b5 100644
--- a/dyl.p8
+++ b/dyl.p8
@@ -7,6 +7,7 @@ __lua__
#include world.lua
#include collisions.lua
#include camera.lua
+#include ai.lua
#include dyl.lua
------------------------
-- don't you leave --
@@ -48,10 +49,10 @@ __gfx__
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000030005c00050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-04444000000990000000300005cc0c50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-04994000009a7900000880000511c150000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-04444000009aa9000087880005111150000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-00440000000990000088880005111150000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+04444000000990000000300005cc0c50000000000000000000000000000000000000000000000000000000000000800000800000000800000000000000000000
+04994000009a7900000880000511c150000000000000000000000000000000000000000000000000000000000080800000088000000080000080800000000000
+04444000009aa9000087880005111150000000000000000000000000000000000000000000000000000000000008900000890000008890000008900000000000
+00440000000990000088880005111150000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000
00000000000000000008800000555500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
diff --git a/entity.lua b/entity.lua
index 849674e..5698c77 100644
--- a/entity.lua
+++ b/entity.lua
@@ -7,9 +7,11 @@ Entities = {
Wife = 5,
Fire = 6,
Door = 7,
- Block = 8
+ Block = 8,
+ Bullet = 9,
}
- -- TODO: Why are these all in one object. We should have like "SpriteStates", "FireStates", etc.
+
+-- TODO: Why are these all in one object. We should have like "SpriteStates", "FireStates", etc.
States = {
Walk = "walk",
Idle = "idle",
@@ -45,6 +47,10 @@ function Entity:kill()
end
function Entity:update(dt)
+ if self.controller ~= nil then
+ self.controller:update(dt)
+ end
+
self:integrate(dt)
self:update_line_of_sight()
@@ -69,16 +75,20 @@ function Entity:update(dt)
end
function Entity:update_line_of_sight()
- nv = self.velocity:apply(normalize_scalar)
- if nv.y != 0 then
- self.line_of_sight = vec2(0, nv.y)
- elseif nv.x != 0 then
- self.line_of_sight = vec2(nv.x, 0)
+ los = self.velocity:normal():apply(abs)
+ n_los = self.velocity:apply(normalize_scalar)
+ if n_los == vec2(0, 0) then
+ return
+ end
+ if los.y >= los.x then
+ self.line_of_sight = vec2(0, n_los.y)
+ else
+ self.line_of_sight = vec2(n_los.x, 0)
end
end
-- prevent cobblestoning during non-manhattan movement by "lagging" the sprite
--- behind the actual physical position
+-- behind the actual physical position.
-- this part was painful.
function Entity:update_sprite_position()
if self.sprite_position == nil then return end
@@ -119,14 +129,9 @@ function Entity:update_sprite_position()
if dy < 0 then func = ceil end
self.sprite_position.y += func(dy)
end
-
- return self
end
function Entity:take_damage(direction, damage_spec)
- if self.health == nil or self:is_in_iframe() then
- return
- end
self.health -= damage_spec.amount
if damage_spec.knockback ~= nil then
self.knockback = {
@@ -268,8 +273,23 @@ function EntityBuilder:b_line_of_sight(vec)
self.line_of_sight = vec2(vec)
return self
end
+function EntityBuilder:b_velocity(vec)
+ self.velocity = vec2(vec)
+ return self
+end
+function EntityBuilder:b_collision_bounds(top_left, bottom_right)
+ self.collision_bounds = {
+ top_left = vec2(top_left),
+ bottom_right = vec2(bottom_right)
+ }
+ return self
+end
function EntityBuilder:build()
self.equipped = {}
+ self.collision_bounds = {
+ top_left = vec2(0, 0),
+ bottom_right = vec2(SPRITE_DIMS)
+ }
return self.build_context.world.add(setmetatable(self, Entity))
end \ No newline at end of file
diff --git a/map.lua b/map.lua
index 87cb5f3..fcf823a 100644
--- a/map.lua
+++ b/map.lua
@@ -3,7 +3,7 @@ _t = {
C = { name = "current", color = 7, blink = true },
K = { name = "visited", color = 6 },
M = { name = "mystery", color = 2 },
- R = { name = "restock", color = 9 },
+ S = { name = "supply", color = 9 },
E = { name = "empty", color = 0 }
}
@@ -21,4 +21,9 @@ DisplayMap = {
{ _t.E, _t.E, _t.H, _t.E, _t.E },
{ _t.E, _t.E, _t.E, _t.E, _t.E },
{ _t.E, _t.E, _t.E, _t.E, _t.E }
-} \ No newline at end of file
+}
+
+-- todo
+-- function Map.blit()
+-- for i=1,DisplayMap.
+-- end \ No newline at end of file
diff --git a/math.lua b/math.lua
index 429e1ab..ddc6644 100644
--- a/math.lua
+++ b/math.lua
@@ -25,7 +25,14 @@ end
function Vec2:normal()
local m = self:magnitude()
if m == 0 then return vec2(self.x, self.y) end
- return self / m
+ return vec2(self / m)
+end
+
+-- 1 picorad == 2pi
+function Vec2:clockwise_rotate(picorads)
+ local m = self:magnitude()
+ local a = atan2(self.x, self.y) + picorads
+ return vec2(m * cos(a), m * sin(a))
end
function Vec2:apply(f)
diff --git a/util.lua b/util.lua
index 8f1de2a..6aae259 100644
--- a/util.lua
+++ b/util.lua
@@ -47,6 +47,15 @@ function qsort(a, c, l, r)
return a
end
+function some(a, pred)
+ for k, v in pairs(a) do
+ if pred(v) then
+ return true
+ end
+ end
+ return false
+end
+
function filter(a, pred)
filtered = {}
for k, v in pairs(a) do