Smooth Hill Segments

Hi,

I am trying to write an engine that resembles that of all the hill racing games.

I just can’t get my bike to ride on the segments without it freaking out because of some imaginary bumps, even on a straight line. When a new segment begins, there seems to be an edge. No matter if it has the same height as that one before. I tried wheel joints, dampings, masses, frictions, etc etc… The bike feels like it was riding on a minefield. Why does this happen?

Thanks in advance!  :slight_smile:

local physics = require("physics")  physics.start() physics.setScale(72) physics.setDrawMode("hybrid") physics.setContinuous = true   display.setStatusBar(display.HiddenStatusBar) display.setDefault("background", 1,1,1) display.setDefault("fillColor", 0.7,0.7,0.7)   local \_W = display.contentWidth local \_H = display.contentHeight local \_w = \_W/2 local \_h = \_H/2   local hasFriction = 1 local hasBounce = 0   local oLength = 20 local oCount = 150       ----   local world = display.newGroup()   local obstacle = {} for a = 1,oCount do local theShape = {oLength/2,150, -oLength/2,150, -oLength/2,-150, oLength/2,-150} obstacle[a] = display.newPolygon(oLength\*(a-2), \_H, theShape) physics.addBody(obstacle[a], "static", {friction = hasFriction, shape = theShape, density = 100000, bounce = hasBounce}) obstacle[a].isBullet = true world: insert(obstacle[a]) end   local bikeAt = {60,200} local bikeShape = {-8,-16, 24,-16, 24,16, -24,16}   local bike = { display.newCircle(bikeAt[1]-20, bikeAt[2], 13), display.newCircle(bikeAt[1]+20, bikeAt[2], 13), display.newPolygon(bikeAt[1], bikeAt[2]-10, bikeShape) }   physics.addBody(bike[1], "dynamic", {radius = 13, friction = hasFriction, density = 0.01, bounce = hasBounce}) physics.addBody(bike[2], "dynamic", {radius = 13, friction = hasFriction, density = 0.01, bounce = hasBounce}) physics.addBody(bike[3], "dynamic", {shape = bikeShape, friction = hasFriction, density = 0.01, bounce = hasBounce})   bike[1].isRiding = false   for a = 1,3 do world: insert (bike[a]) end   local wheel1joint = physics.newJoint("pivot", bike[1], bike[3], bike[1].x, bike[1].y) local wheel2joint = physics.newJoint("pivot", bike[2], bike[3], bike[2].x, bike[2].y)   wheel1joint.isMotorEnabled = true wheel1joint.maxMotorTorque = 0.1   local timer = 0 local function onTouch(e) if e.phase == "began" then bike[1].isRiding = true wheel1joint.maxMotorTorque = 0.1 elseif e.phase == "ended" then timer = 0 bike[1].isRiding = false wheel1joint.motorSpeed = 0 wheel1joint.maxMotorTorque = 0.0003 end end   Runtime: addEventListener ("touch", onTouch)   local function moveBike() if bike[1].isRiding == true then timer = timer + 1 wheel1joint.motorSpeed = -700-timer\*30 end end   Runtime: addEventListener("enterFrame", moveBike)     local function camera() world.x = -bike[1].x+bikeAt[1] end Runtime: addEventListener("enterFrame", camera)

Hi @philipp3,

Just to clarify, you’re saying that when the bike’s wheel moves directly across two flat shapes, and those shapes mesh together (corners) exactly, you get some kind of weird bouncy collision response? That doesn’t seem like expected behavior (obviously). Can you post a screenshot of this simulation in the “hybrid” view so I can see what is going on?

Brent

P.S. - as a general note, you probably don’t need to set physics.setScale() in this. That’s not an overly common function and it’s normally reserved for special circumstances.

Thanks for caring, Brent, here’s a screenshot after a riding a few inches:

di-E3QB.png

The game should run like this one, for example, from the video I saw of that game, it doesn’t seem to have the same problem: 

http://forums.coronalabs.com/topic/37822-uphills-racing-my-first-corona-game/

Hi @philipp3,

Ok, this may be caused because the density is so very low (0.01) on your bike objects. Try increasing this to a more standard value like 1.0 and see what happens…

Brent

When I change the mass, nothing happens, also when I make the body heavy and the wheels light or vice versa.

Can you try using display.newRect() objects instead of polygons? That way you don’t need to use the “shape” for the bodies… the engine will trace those rectangles automatically.

Of course, you may be asking why, since you want a “hills” game, but my eventually advice will be to use neither polygons nor rectangles (but we’ll get to that point once we work out this first issue).

Brent

Changing the shapes to rectangles makes no difference.

I’m the author of Level Director and one of my users came across a similar problem where it was snagging against joined objects/polygons.

Apart from creating a single polygon/rectangle that covers a large area the only way I could make it work smoothly was by using chain edge physics, so it might be worth taking a look.

FYI - http://forums.coronalabs.com/topic/55079-bezier-curves-physics-and-ghost-vertices/?hl=edge

The next version of Level Director will support chain edge physics for bezier curves and normal line paths (very useful for terrain style games).

Hope this helps.

Hi @philipp3,

The advice that @retrofitProductions provides is the same I was going to give you. For a hill racing game, you should use Box2D “edge shape” (chain) bodies instead of a series of polygons. Not only are they easier to work with for this purpose, but they allow for up to 32 segments, while shapes are limited to 8 segments.

Here is the official documentation on this topic:

http://docs.coronalabs.com/api/library/physics/addBody.html#edge-shape-chain-body

Brent

Thank you both! Never heard of that before, to be honest. I will try that out and tell if it worked :slight_smile:

Thank you so much, this works perfectly. Just why would anyone not want to use edge shape bodies?

Btw, when Brent said to change the density to 1, your response was that you changed the mass and it didn’t help. Did you change a value called mass, or the actual density value to 1? Just wondering, because if you did change it to ‘mass’ and the problem persisted, that’s why.

I see no reason why, for example, a ball rolling along a series of rectangle would bounce at all, given the above parameter.

Oh I meant density, not mass.

I just knocked this up to test the idea. Is this what you’re looking for?

require("physics") physics.start() physics.setGravity(0,10) physics.setDrawMode("hybrid") for i=1, 10 do local r = display.newRect( (display.actualContentWidth/10)\*(i-.5), display.actualContentHeight\*.75, display.actualContentWidth/10, display.actualContentHeight\*.5 ) r.fill = {0,1,0} physics.addBody( r, "static" ) end local body = display.newRect( display.actualContentWidth\*.15, display.actualContentHeight\*.35, 200, 100 ) body.fill = {1,0,0} local frontwheel = display.newCircle( body.x-75, body.y+50, 50 ) frontwheel.fill = {0,0,1} local backwheel = display.newCircle( body.x+75, body.y+50, 50 ) backwheel.fill = {0,0,1} physics.addBody( body, "dynamic", { friction=.2, bounce=.1, density=1 } ) physics.addBody( frontwheel, "dynamic", { friction=.2, bounce=.1, density=1, radius=50 } ) physics.addBody( backwheel, "dynamic", { friction=.2, bounce=.1, density=1, radius=50 } ) local frontaxle = physics.newJoint( "pivot", body, frontwheel, frontwheel.x, frontwheel.y ) local backaxle = physics.newJoint( "pivot", body, backwheel, backwheel.x, backwheel.y ) local function activateMotor( motor, speed ) motor.isMotorEnabled = true motor.motorSpeed = speed motor.maxMotorTorque = 100000 end timer.performWithDelay( 2000, function() activateMotor( frontaxle, 200 ) activateMotor( backaxle, 200 ) end, 1 )

Sorry, I know I’m late to this thread…

Hey horacebury,

Thanks a lot for your time. I modified your code a bit to show the problem (my vehicle will drive pretty fast). After a few elements, it will start to shake:

(Edge shape bodies work fine though)

require("physics") physics.start() physics.setGravity(0,20) --physics.setDrawMode("hybrid")     local gameGroup = display.newGroup() gameGroup: scale (0.3,0.3) gameGroup: translate (0,200)   for i=1, 100 do local r = display.newRect( (display.actualContentWidth/10)\*(i-1.5), display.actualContentHeight\*.75, display.actualContentWidth/10, display.actualContentHeight\*.5 ) r.fill = {0,1,0} physics.addBody(r, "static", {friction = 1, bounce = 0}) gameGroup: insert (r) end   local body = display.newRect( display.actualContentWidth\*.15, display.actualContentHeight\*.35, 200, 100 ) body.fill = {1,0,0} local frontwheel = display.newCircle( body.x-75, body.y+50, 50 ) frontwheel.fill = {0,0,1} local backwheel = display.newCircle( body.x+75, body.y+50, 50 ) backwheel.fill = {0,0,1}   physics.addBody( body, "dynamic", { friction=.2, bounce=.1, density=1 } ) physics.addBody( frontwheel, "dynamic", { friction=.2, bounce=.1, density=1, radius=50 } ) physics.addBody( backwheel, "dynamic", { friction=1, bounce=0, density=1, radius=50 } )   gameGroup: insert (body) gameGroup: insert (frontwheel) gameGroup: insert (backwheel)   local frontaxle = physics.newJoint( "pivot", body, frontwheel, frontwheel.x, frontwheel.y ) local backaxle = physics.newJoint( "pivot", body, backwheel, backwheel.x, backwheel.y )   local counter = 0 local function activateMotor( motor, speed ) motor.isMotorEnabled = true counter = counter + 1 motor.motorSpeed = speed motor.maxMotorTorque = 800 end   timer.performWithDelay( 1000, function() activateMotor( frontaxle, 10000000 ) --activateMotor( backaxle, 200 ) end, 1 )       local function camera() gameGroup.x = 100-body.x\*0.3 end Runtime: addEventListener("enterFrame", camera)

Hi @philipp3,

Just to clarify, you’re saying that when the bike’s wheel moves directly across two flat shapes, and those shapes mesh together (corners) exactly, you get some kind of weird bouncy collision response? That doesn’t seem like expected behavior (obviously). Can you post a screenshot of this simulation in the “hybrid” view so I can see what is going on?

Brent

P.S. - as a general note, you probably don’t need to set physics.setScale() in this. That’s not an overly common function and it’s normally reserved for special circumstances.

Thanks for caring, Brent, here’s a screenshot after a riding a few inches:

di-E3QB.png

The game should run like this one, for example, from the video I saw of that game, it doesn’t seem to have the same problem: 

http://forums.coronalabs.com/topic/37822-uphills-racing-my-first-corona-game/

Hi @philipp3,

Ok, this may be caused because the density is so very low (0.01) on your bike objects. Try increasing this to a more standard value like 1.0 and see what happens…

Brent

When I change the mass, nothing happens, also when I make the body heavy and the wheels light or vice versa.

Can you try using display.newRect() objects instead of polygons? That way you don’t need to use the “shape” for the bodies… the engine will trace those rectangles automatically.

Of course, you may be asking why, since you want a “hills” game, but my eventually advice will be to use neither polygons nor rectangles (but we’ll get to that point once we work out this first issue).

Brent