From a66ea9feeeadbf1b60d184ed1c935d4a15101c18 Mon Sep 17 00:00:00 2001 From: Quinn Date: Sun, 26 Dec 2021 20:57:41 -0800 Subject: [PATCH] Separate logic into class files --- ball.lua | 56 +++++++++++++++++++++++ main.lua | 109 -------------------------------------------- picosync.json | 11 ++--- qphys.p8 | 122 ++++++++++++++++++++++++++------------------------ vec2.lua | 52 +++++++++++++++++++++ 5 files changed, 178 insertions(+), 172 deletions(-) create mode 100644 ball.lua create mode 100644 vec2.lua diff --git a/ball.lua b/ball.lua new file mode 100644 index 0000000..59cfd77 --- /dev/null +++ b/ball.lua @@ -0,0 +1,56 @@ +ball = { + __count = 0, + id = nil, + pos = vec2:new(0,0), + vel = vec2:new(0,0), + rad = 1, + col = 7, + + draw = function(self) + circfill(self.pos.x, self.pos.y, self.rad, self.col) + end, + + move = function(self) + self.pos += self.vel + end, + + edge_bounce = function(self) + edge_normal = vec2:new() + for axis in all({"x","y"}) do + val = self.pos[axis] + if (val - self.rad < 0) then + self.pos[axis] = self.rad + edge_normal[axis] = 1 + elseif (val + self.rad > 127) then + self.pos[axis] = 127 - self.rad + edge_normal[axis] = -1 + end + end + if (edge_normal.x != 0 or edge_normal.y != 0) then + self.vel = self.vel:bounce(edge_normal) + end + end, + + check_collisions = function(self, balls) + for b in all(balls) do + if (b.id != self.id and (collisions[b] == nil or collisions[b][self] == nil)) then + local diff = self.pos - b.pos + if ((diff):mag() < self.rad + b.rad) then + collisions[self] = collisions[self] or {} + collisions[self][b] = diff + end + end + end + end, +} +ball.__index = ball + +function ball:new(o) + ball.__count += 1 + local o = o or {} + o.id = ball.__count + o.col = o.id % 16 + setmetatable(o, self) + o.__index = self + return o +end diff --git a/main.lua b/main.lua index 69d9339..f883c8e 100644 --- a/main.lua +++ b/main.lua @@ -54,115 +54,6 @@ function handle_collisions() end end -vec2 = { - x = 0, - y = 0, - - mag = function(self) - return sqrt(self.x^2+self.y^2) - end, - - dot = function(self,v) - return self.x * v.x + self.y * v.y - end, - - normal = function(self) - local mag = self:mag() - return vec2:new(self.x/mag, self.y/mag) - end, - - bounce = function(self, n, b) - local b = b or 1 - local n = n:normal() - return (n * -2 * self:dot(n) + self) * b - end -} - -vec2.__eq = function(v1,v2) return v1.x == v2.x and v1.y == v2.y end -vec2.__add = function(v1,v2) return vec2:new(v1.x+v2.x,v1.y+v2.y) end -vec2.__sub = function(v1,v2) return vec2:new(v1.x-v2.x,v1.y-v2.y) end -vec2.__mul = function(v,s) return vec2:new(v.x*s,v.y*s) end -vec2.__div = function(v,s) return vec2:new(v.x/s,v.y/s) end -vec2.__unm = function(v) return vec2:new(-v.x,-v.y) end -vec2.__tostring = function(v) return "{x: "..v.x..",y: "..v.y.."}" end -vec2.__index = vec2 - -function vec2:new(x,y) - local x = x or 0 - local y = y or 0 - local o = {x=x,y=y} - setmetatable(o, self) - o.__index = self - return o -end - -function vec2:print_debug(v) - local v = v or vec2:new(0,1) - print("vec: "..vec2.__tostring(self)) - print("mag: "..self:mag()) - print("dot: "..self:dot(v)) - print("normal: "..vec2.__tostring(self:normal())) - print("bounce: "..vec2.__tostring(self:bounce(v))) - print("inv: "..vec2.__tostring(-self)) -end - -ball = { - __count = 0, - id = nil, - pos = vec2:new(0,0), - vel = vec2:new(0,0), - rad = ball_radius, - col = 7, - - draw = function(self) - circfill(self.pos.x, self.pos.y, self.rad, self.col) - end, - - move = function(self) - self.pos += self.vel - end, - - edge_bounce = function(self) - edge_normal = vec2:new() - for axis in all({"x","y"}) do - val = self.pos[axis] - if (val - self.rad < 0) then - self.pos[axis] = self.rad - edge_normal[axis] = 1 - elseif (val + self.rad > 127) then - self.pos[axis] = 127 - self.rad - edge_normal[axis] = -1 - end - end - if (edge_normal.x != 0 or edge_normal.y != 0) then - self.vel = self.vel:bounce(edge_normal) - end - end, - - check_collisions = function(self, balls) - for b in all(balls) do - if (b.id != self.id and (collisions[b] == nil or collisions[b][self] == nil)) then - local diff = self.pos - b.pos - if ((diff):mag() < self.rad + b.rad) then - collisions[self] = collisions[self] or {} - collisions[self][b] = diff - end - end - end - end, -} -ball.__index = ball - -function ball:new(o) - ball.__count += 1 - local o = o or {} - o.id = ball.__count - o.col = o.id % 16 - setmetatable(o, self) - o.__index = self - return o -end - function collision_vel(x1,v1,x2,v2) local x_diff = x1 - x2 local v_diff = v1 - v2 diff --git a/picosync.json b/picosync.json index 38a743f..1cdb14f 100644 --- a/picosync.json +++ b/picosync.json @@ -1,7 +1,8 @@ { - "picoFile":"qphys.p8", - - "sources":[ - "main.lua" - ] + "picoFile":"qphys.p8", + "sources":[ + "vec2.lua", + "ball.lua", + "main.lua" + ] } diff --git a/qphys.p8 b/qphys.p8 index 57e8231..50a6cd6 100644 --- a/qphys.p8 +++ b/qphys.p8 @@ -1,62 +1,6 @@ pico-8 cartridge // http://www.pico-8.com version 34 __lua__ -ball_count = 16 -ball_radius = 5 - -function _init() - balls = {} - collisions = {} - for i=1,ball_count do - add(balls, ball:new({ - pos=vec2:new(rnd(127),rnd(127)), - vel=vec2:new(rnd(2)-1,rnd(2)-1):normal(), - col=rnd(15)+1 - })) - end -end - -function _update60() - for b in all(balls) do - b:move() - b:edge_bounce() - end - for b in all(balls) do - b:check_collisions(balls) - end - handle_collisions(balls) - collisions = {} -end - -function _draw() - cls() - for b in all(balls) do - b:draw() - end -end - -function handle_collisions() - for source,colls in pairs(collisions) do - for target,diff in pairs(colls) do - local n = diff:normal() - local steps = 0 - local rewind = 0 - local s_xpoint = source.pos - local t_xpoint = target.pos - repeat - steps += 1 - rewind += 0.1 * steps - s_xpoint = source.pos - source.vel * rewind - t_xpoint = target.pos - target.vel * rewind - until (s_xpoint - t_xpoint):mag() >= source.rad + target.rad - source.vel = collision_vel(s_xpoint, source.vel, t_xpoint, target.vel) - target.vel = collision_vel(t_xpoint, target.vel, s_xpoint, source.vel) - source.pos = s_xpoint + source.vel * rewind - target.pos = t_xpoint + target.vel * rewind - end - end -end - vec2 = { x = 0, y = 0, @@ -78,7 +22,7 @@ vec2 = { local b = b or 1 local n = n:normal() return (n * -2 * self:dot(n) + self) * b - end + end, } vec2.__eq = function(v1,v2) return v1.x == v2.x and v1.y == v2.y end @@ -109,12 +53,14 @@ function vec2:print_debug(v) print("inv: "..vec2.__tostring(-self)) end + +-->8 ball = { __count = 0, id = nil, pos = vec2:new(0,0), vel = vec2:new(0,0), - rad = ball_radius, + rad = 1, col = 7, draw = function(self) @@ -166,6 +112,66 @@ function ball:new(o) return o end +-->8 +ball_count = 16 +ball_radius = 5 + +function _init() + balls = {} + collisions = {} + for i=1,ball_count do + add(balls, ball:new({ + pos=vec2:new(rnd(127),rnd(127)), + vel=vec2:new(rnd(2)-1,rnd(2)-1):normal(), + rad=ball_radius, + col=rnd(15)+1 + })) + end +end + +function _update60() + for b in all(balls) do + b:move() + b:edge_bounce() + end + for b in all(balls) do + b:check_collisions(balls) + end + handle_collisions(balls) + collisions = {} +end + +function _draw() + cls() + for b in all(balls) do + b:draw() + end +end + +function handle_collisions() + for source,colls in pairs(collisions) do + for target,diff in pairs(colls) do + local n = diff:normal() + local steps = 0 + local rewind = 0 + local s_xpoint = source.pos + local t_xpoint = target.pos + repeat + steps += 1 + rewind += 0.1 * steps + s_xpoint = source.pos - source.vel * rewind + t_xpoint = target.pos - target.vel * rewind + until (s_xpoint - t_xpoint):mag() >= source.rad + target.rad + local s_newvel = collision_vel(s_xpoint, source.vel, t_xpoint, target.vel) + local t_newvel = collision_vel(t_xpoint, target.vel, s_xpoint, source.vel) + source.pos = s_xpoint + source.vel * rewind + target.pos = t_xpoint + target.vel * rewind + source.vel = s_newvel + target.vel = t_newvel + end + end +end + function collision_vel(x1,v1,x2,v2) local x_diff = x1 - x2 local v_diff = v1 - v2 diff --git a/vec2.lua b/vec2.lua new file mode 100644 index 0000000..38b0528 --- /dev/null +++ b/vec2.lua @@ -0,0 +1,52 @@ +vec2 = { + x = 0, + y = 0, + + mag = function(self) + return sqrt(self.x^2+self.y^2) + end, + + dot = function(self,v) + return self.x * v.x + self.y * v.y + end, + + normal = function(self) + local mag = self:mag() + return vec2:new(self.x/mag, self.y/mag) + end, + + bounce = function(self, n, b) + local b = b or 1 + local n = n:normal() + return (n * -2 * self:dot(n) + self) * b + end, +} + +vec2.__eq = function(v1,v2) return v1.x == v2.x and v1.y == v2.y end +vec2.__add = function(v1,v2) return vec2:new(v1.x+v2.x,v1.y+v2.y) end +vec2.__sub = function(v1,v2) return vec2:new(v1.x-v2.x,v1.y-v2.y) end +vec2.__mul = function(v,s) return vec2:new(v.x*s,v.y*s) end +vec2.__div = function(v,s) return vec2:new(v.x/s,v.y/s) end +vec2.__unm = function(v) return vec2:new(-v.x,-v.y) end +vec2.__tostring = function(v) return "{x: "..v.x..",y: "..v.y.."}" end +vec2.__index = vec2 + +function vec2:new(x,y) + local x = x or 0 + local y = y or 0 + local o = {x=x,y=y} + setmetatable(o, self) + o.__index = self + return o +end + +function vec2:print_debug(v) + local v = v or vec2:new(0,1) + print("vec: "..vec2.__tostring(self)) + print("mag: "..self:mag()) + print("dot: "..self:dot(v)) + print("normal: "..vec2.__tostring(self:normal())) + print("bounce: "..vec2.__tostring(self:bounce(v))) + print("inv: "..vec2.__tostring(-self)) +end +