# Splinerider

My take on the flash game line rider using a ball and splines, check it out!
http://youtu.be/14uCT3_zQAc
Tell me what you think

Really great work I think the video is being processed atm it’ll be up in a few minutes

Pretty cool, nice work!

Thanks I’ve added setting a marker and swipe off screen to delete and a few other things a bit smaller than that but seem to boost the overall performance by about 100 times by using meshes instead, gives quite a nice look but I prefered the lines with a cap on them, anyway heres the newer one: http://youtu.be/14uCT3_zQAc

very cool!

Very nice. Clean interface and nifty functionality.

That is awesome. I love the way you made those curvy shapes always been thinking how to make them. Now that you’ve made them I atleast know that there’s a way to do it!!

For your convenience heres how I do it:

``````
-- spline

-- Use this function to perform your initial setup
function setup()
Splines = {}
table.insert(Splines,Spline({vec2(200,500),vec2(300,400),vec2(400,400),vec2(500,500)}))
scr = vec2()
touches = {}
end

function angleOfPoint( pt )
local x, y = pt.x, pt.y
local radian = math.atan2(y,x)
local angle = radian*180/math.pi
if angle < 0 then angle = 360 + angle elseif angle > 360 then angle = 0 + (angle-360) end
return angle
end

function touched(t)
for k,v in pairs(Splines) do
v:touched(t)
end
end

-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(161, 161, 161, 255)

-- This sets the line thickness
strokeWidth(5)

-- Do your drawing here
for k,v in pairs(Splines) do
v:drawPoints()
v:draw()
end
end

------------------

Points = class()

function Points:init(v)
self.m = mesh()
self.r = {}
for i=1,#v*2 do
if i <= 4 then
self.p = v[i]
self.m:setColors(50,50,50,255)
elseif i > 4 then
self.p = v[i-4]
self.m:setColors(50,50,50,255)
end
end
end

function Points:draw()
self.m:draw()
end

function Points:touched(touch)
-- Codea does not automatically call this method
end

--------------

Spline = class()

function Spline:init(v)
-- you can accept and set parameters here
self.v = v
self.holding = {}
self.moving = nil
self.verts = {}
self.newv = {}
local n = 31
local t = 0
for i = 1,n do
self.verts[i] = (1-t)^3 * v + 3*(1-t)^2 *t * v + 3*(1-t)* t^2 *v + t^3*v
t=t+1/(n-1)
end
self.lines = Lines(self.verts,50)
self.vlines = Lines(self.v,200)
self.points = Points(self.v)
self.spline = physics.body(CHAIN,false,unpack(self.verts))
end

function Spline:draw()
self.lines:draw()
end

function Spline:drawPoints()
self.vlines:draw()
self.points:draw()
self.p = vec2()
for i = 1,#self.v do
local pos = self.v[i]
self.p = self.p + pos
end
strokeWidth(2)
stroke(255,200)
self.p = self.p/4
fill(179, 21, 21, 150)
ellipse(self.p.x,self.p.y,30)
end

function Spline:pos()
return self.p
end

function Spline:touched(t)
if t.state == BEGAN then
for i=1,#self.v do
local pos = self.v[i]+scr
if vec2(t.x,t.y):dist(pos) < 25 then
self.holding[i] = true
end
end
if vec2(t.x,t.y):dist(self.p+scr) < 25 then
self.moving = 1
for i=1,#self.v do
self.newv[i] = (self.v[i]-self.p)
end
end
for i=1,#self.v do
if self.v[i]:dist(self.p) < 20 then
self.v[i] = self.v[i] + (self.v[i]-self.p):normalize()*20
end
end
elseif t.state == MOVING and self.moving == 1 then
tp = vec2(t.x,t.y)
for i=1,#self.v do
self.v[i] = tp + self.newv[i]-scr
end
local t = 0
local n = 31
local v = self.v
for i = 1,n do
self.verts[i] = (1-t)^3 * v + 3*(1-t)^2 *t * v + 3*(1-t)* t^2 *v + t^3*v
t=t+1/(n-1)
end
self.lines = Lines(self.verts,50)
self.vlines = Lines(self.v,200)
self.points = Points(self.v)
elseif t.state == ENDED and self.moving == 1 then
self.moving = nil
end
for i=1,#self.v do
local pos = self.v[i]
if t.state == MOVING and self.holding[i] then
touches = t
tp = vec2(t.x,t.y)
self.v[i] = tp-scr
local t = 0
local n = 31
local v = self.v
for i = 1,n do
self.verts[i] = (1-t)^3 * (v) + 3*(1-t)^2 *t * (v) + 3*(1-t)* t^2 *(v)+ t^3*(v)
t=t+1/(n-1)
end
self.lines = Lines(self.verts,50)
self.vlines = Lines(self.v,200)
self.points = Points(self.v)
elseif t.state == ENDED and self.holding[i] then
self.holding[i] = nil
end
end
end

------------------

Lines = class()

function Lines:init(v,col)
self.m = mesh()
self.r = {}
for i=1,#v do
if i > 1 then
self.p = (v[i*1-1]+v[i*1])/2
self.dir = (v[i*1]-v[i*1-1]):normalize()
self.len = (v[i*1]-v[i*1-1]):len()
self.m:setColors(col,col,col,255)
end
end
end

function Lines:draw()
self.m:draw()
end

function Lines:touched(touch)
-- Codea does not automatically call this method
end
``````

I plan to make a game out of it but its not that hard to make a game when you’ve got that!
Also note you can only use a table of four vertices in the Spline(v) function.

I hope you enjoy it and to make more curves just add them to the table of Splines.

Btw it runs about 60fps even with about 20 on the screen, if I bothered to use meshes with the ellipse in the middle I doubt it would go down at all until about 40

Thanks @Luatee. I’ll look into it.

Thanks @Luatee for the code. I hope you don’t mind if I borrow your curves equation. Making an equation that too cubic will be difficult for me. Here’s the code I wrote though its not exactly the same but its similar. (Long hold on new project and paste into project)

``````

--# Main
function setup()
p = Points(WIDTH/2-100,HEIGHT/2)
BallSetup()
parameter.boolean("start",false)
end

function draw()
background(255)
p:draw()
BallDraw()
if start then
physics.resume()
elseif not start then
physics.pause()
end
end

function touched(touch)
tx = touch.x
ty = touch.y
touchPoint = false
p:touched(touch)
BallTouch(touch)
end

--# Points
Points = class()

function Points:init(x1,y1)
self.px = {}
self.py = {}
self.x1 = x1
self.y1 = y1
self.x2 = self.x1+100
self.y2 = self.y1-100
self.x3 = self.x2+100
self.y3 = self.y2
self.x4 = self.x3+100
self.y4 = self.y3+100
n = 30
end

function Points:draw()
pushStyle()
fill(127, 127, 127, 255)
ellipse(self.x1,self.y1,15)
ellipse(self.x2,self.y2,15)
ellipse(self.x3,self.y3,15)
ellipse(self.x4,self.y4,15)
popStyle()
local t = 0
for i=1,n do
self.px[i] = (1-t)^3 * (self.x1) + 3*(1-t)^2 *t * (self.x2) + 3*(1-t)* t^2 *(self.x3)+ t^3*(self.x4)
self.py[i] = (1-t)^3 * (self.y1) + 3*(1-t)^2 *t * (self.y2) + 3*(1-t)* t^2 *(self.y3)+ t^3*(self.y4)
t=t+1/(n-1)
end
for i=1,n-1 do
pushMatrix()
pushStyle()
stroke(0, 0, 0, 255)
strokeWidth(5)
line(self.px[i],self.py[i],self.px[i+1],self.py[i+1])
self.body = physics.body(EDGE,vec2(self.px[i],self.py[i]), vec2(self.px[i-1],self.py[i-1]))
popStyle()
popMatrix()
end
pushStyle()
stroke(73, 73, 73, 80)
strokeWidth(7)
line(self.x1,self.y1,self.x2,self.y2)
line(self.x2,self.y2,self.x3,self.y3)
line(self.x3,self.y3,self.x4,self.y4)
popStyle()
end

function Points:touched(touch)
if tx>self.x1-30 and tx<self.x1+30 and ty>self.y1-30 and ty<self.y1+30 then
touchPoint = true
self.x1 = tx
self.y1 = ty
end
if tx>self.x2-30 and tx<self.x2+30 and ty>self.y2-30 and ty<self.y2+30 then
touchPoint = true
self.x2 = tx
self.y2 = ty
end
if tx>self.x3-30 and tx<self.x3+30 and ty>self.y3-30 and ty<self.y3+30 then
touchPoint = true
self.x3 = tx
self.y3 = ty
end
if tx>self.x4-30 and tx<self.x4+30 and ty>self.y4-30 and ty<self.y4+30 then
touchPoint = true
self.x4 = tx
self.y4 = ty
end
end

--# Ball
function BallSetup()
ball = physics.body(CIRCLE,20)
ball.x = WIDTH/2
ball.y = HEIGHT/2
ball.restitution = 0
ball.friction = 0
ball.gravityScale = 2
end

function BallDraw()
pushStyle()
fill(255, 0, 0, 255)
stroke(0, 0, 0, 255)
strokeWidth(3)
ellipse(ball.x,ball.y,40)
popStyle()
end

function BallTouch(touch)
if not touchPoint then
ball.x = tx
ball.y = ty
end
end
``````

Just checked that out thats a good way of doing it but make sure when you’re holding the ball to set its velocity to vec2(0,0) the BallTouch function but other than that its a good way of doing it, I prefer to keep it in the class though as its easy to create many of these curves.

Also the equation itself is standard so feel free to use it, but if you create a game using the classes then all I ask is credit, thanks!

Yeah I made the game using classes I just posted this to show it to you. Thanks for the idea and main part of the games code @Luatee. But now I am into a problem how should I move the screen along with the ball. I am trying to use translate but it’s not working. I tried using FPS but then the movement was becoming jerky. I’ll be grateful if you could help.

@Luatee how did you move the splines along with the cycle without using FPS I did as in the code below. But the movement becomes jerky and inaccurate as I am using DeltaTime. Could you help me out??https://gist.github.com/Saurabh96jun/5655889

Well the red circle in the middle (The one I assume you’re talking about), I just found the midpoint of all the vectors (the average) so you divide all the points by 4 assuming you have 4 points in total. Then create variable in the class called self.moving and then set it to true in the touched function using a statement such as if touchpos:dist(self.p) < 25 then blah blah end, then create a set of new vectors (we’ll call them newvecs, which is a table of four vectors) which consist of each vertex/point minus the midpoint (I call the midpoint self.p) and then move self.p to your touchpos and then add the contents of newvecs to self.p and set each vertex to this new value and it should work. If you dont understand the above then feel free to send me a message me on here.

Thanks @Luatee

Here’s a newer version what do you guys think? http://youtu.be/dg_t9V5S-y8
I’ve added a few things and I think its overall better than before…

That looks fantastic @Luatee. I love the little pedalling animation you have going on the bike rider. It seems to correlate to the speed of the bike, nice touch.

Thanks Simeon, I’ve mainly been experimenting with adding realistic motion to the body and such but also get the legs in sync, I have made it to go to how much he would realistically need to pedal using the spacing of splines Bézier curve points. But yeah Im going to try and get most of it sorted and maybe make it a bit less grey haha looks quite depressing atm