Skip to content

Instantly share code, notes, and snippets.

@felipetavares
Created April 7, 2019 20:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save felipetavares/fe09ee7411262cdace98203059475a39 to your computer and use it in GitHub Desktop.
Save felipetavares/fe09ee7411262cdace98203059475a39 to your computer and use it in GitHub Desktop.
Weird-ass Pong
function vec_(x, y)
return { x = x, y = y }
end
function add(a, b)
return vec_(a.x+b.x, a.y+b.y)
end
function sub(a, b)
return vec_(a.x-b.x, a.y-b.y)
end
function mul(v, s)
return vec_(v.x*s, v.y*s)
end
function cross(a, b)
return a.x*b.y - b.x*a.y;
end
function dot(a, b)
return a.x*b.x + a.y*b.y;
end
function inverse(v)
return vec_(-v.x, -v.y)
end
function length2(v)
return v.x*v.x+v.y*v.y
end
function length(v)
return math.sqrt(length2(v))
end
function rot(v, a)
local s = math.sin(a)
local c = math.cos(a)
return vec_(v.x*c - v.y*s,
v.x*s + v.y*c)
end
function normalized(v)
local l = length(v)
return vec_(v.x/l, v.y/l)
end
function perpendicular(v)
return vec_(v.y, -v.x)
end
function line_(origin, segment, angular_velocity)
return { o = origin, s = segment, a = 0, w = angular_velocity }
end
function ball_(origin, velocity)
return { o = origin, v = velocity }
end
function project(a, b)
local intensity = dot(a, b)
return mul(b, intensity), intensity
end
function distance(line_segment, point)
local distance = sub(line_segment.o, point)
local distance_end = add(distance, line_segment.s)
local normal = normalized(perpendicular(line_segment.s))
local side_a = cross(normal, distance)
local side_b = cross(normal, distance_end)
if side_b < 0 then
return distance_end, inverse(normalized(distance_end))
end
if side_a > 0 then
return distance, inverse(normalized(distance))
end
local min_distance = project(distance, normal)
return min_distance, normal
end
local lines = {}
local lines_n = 6
local point = nil
local prev_point = nil
for i=1,lines_n+1 do
prev_point = point
point = add(rot(vec_(0, 119), math.pi*2/lines_n*(i-1)), mul(vec_(320, 240), 0.5))
if i >= 2 then
local p1 = point
local p2 = sub(prev_point, point)
local w = (math.random()-0.5)*2
table.insert(lines, line_(p1, p2, w))
end
end
local ball = ball_(mul(vec_(320, 240), 0.5), vec_(150, 150))
local radius = 2
function draw()
clr(0)
for _, ln in ipairs(lines) do
local ds, n = distance(ln, ball.o)
local d = length(ds)
-- Draw distance
--line(ball.o.x, ball.o.y, ball.o.x+ds.x, ball.o.y+ds.y, 2)
end
circf(ball.o.x, ball.o.y, radius, math.random(2)+13)
for _, ln in ipairs(lines) do
line(ln.o.x, ln.o.y, ln.o.x+ln.s.x, ln.o.y+ln.s.y, 8)
end
end
function update(dt)
-- Collision
local solved = false
local counter = 4
while counter > 0 do
solved = true
counter -= 1
for _, ln in ipairs(lines) do
local ds, n = distance(ln, ball.o)
local d = length(ds)-radius
ds = mul(normalized(ds), d)
local movement_towards, amount = project(mul(ball.v, dt), normalized(ds))
if amount > d then
ball.v = add(ball.v, inverse(mul(project(ball.v, n), 2)))
solved = false
end
end
end
ball.o.x += ball.v.x*dt
ball.o.y += ball.v.y*dt
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment