Help - physics demo

Hello,

Trying to build a simple physics-based golf game but running into issues where objects are passing through each other. Here is a simple example - two physics objects, a small circle for the ball and a polygon shape for the ground. Sometimes the ball passes through the ground (I’ve set the bullet property to true which is supposed to prevent tunnelling). Also, sometimes the ball reacts to vertices of the polygon, almost as if there were a discontinuity between adjacent line segments. Any insights would be appreciated.


-- Micro Golf
viewer.mode=FULLSCREEN
-- Use this function to perform your initial setup
function setup()
  drive=false
  len=WIDTH
  physics.continuous=true

  --set up tee and green
  points={vec2(len-100,100),vec2(len-55,100),vec2(len-55,90),vec2(len-45,90),vec2(len-45,100),vec2(len,100),vec2(len,0),vec2(0,0),vec2(0,100),vec2(50,100)}  
  prev=vec2(50,100)
  --create varying ground
  local step=20
  for i=prev.x,len-110,step do    
    local hadj=-2+math.random(3)
    if i>len-130 then
      hadj=-(prev.y-100)/2
    end
    table.insert(points,vec2(prev.x+step,prev.y+hadj))
    prev=vec2(prev.x+step,prev.y+hadj)
  end
  
  bsize=3
  ball=physics.body(CIRCLE,bsize)
  ball.type=DYNAMIC
  ball.x=50
  ball.y=800
  ball.restitution=0.3
  ball.bullet=true
  ball.friction=0.2

  
  ground=physics.body(POLYGON,table.unpack(points))
  ground.x=0
  ground.y=500
  ground.type=STATIC
  ground.bullet=true
  --  ball:applyTorque(30)  --backspin?
end

function draw()
  background(40, 40, 50)
  pushMatrix()
  translate(ground.x,ground.y)
  strokeWidth(2)
  stroke(85, 146, 29)
  local pts = ground.points
  for j = 1,#pts-1 do
    a= pts[j]
    b=pts[j+1]
    stroke(85, 146, 29)
    line(a.x, a.y, b.x, b.y)
    stroke(255)
    ellipse(a.x,a.y,3)    
  end
  
  line(pts[1].x,pts[1].y,pts[#pts].x,pts[#pts].y)
  fill(236, 218, 67)
  stroke(236, 160, 67)
  rect(len-50,140,12,9)
  stroke(255)
  line(len-50,90,len-50,150)
  popMatrix()
  stroke(150)
  fill(255)
  ellipse(ball.x,ball.y,bsize*2)
  
  fill(255)
  text("Tap to drive",WIDTH/2,HEIGHT/2)
end

function touched(t)
  if not drive then
    ball:applyForce(vec2(15,20))
    drive=true
    sound(asset.downloaded.A_Hero_s_Quest.Hit_Monster_1)
  end
end

Ok - after doing a bit more reading into the box2D physics engine, it looks like I should be using a chain instead of a polygon.

@West Nice little program. Yes, you should be using CHAIN.

@West I took one of my CHAIN programs and stripped it down and made this. You can set the tee and green area widths. The grass in between has random heights.

viewer.mode=FULLSCREEN

function setup()
    teeWidth=100
    greenWidth=100
    pt={vec2(0,100),vec2(teeWidth,100)}          
    for z=teeWidth+teeWidth/4,WIDTH-(greenWidth+greenWidth/4),WIDTH//30 do
        table.insert(pt,vec2(z,100+math.random(-8,8)))
    end  
    table.insert(pt,vec2(WIDTH-greenWidth,100))
    table.insert(pt,vec2(WIDTH,100))
    c1=physics.body(CHAIN,false,table.unpack(pt))
end

function draw()
    background(40,40,50)
    for z=2,#c1.points do
        stroke(0,255,0)
        strokeWidth(4)
        if z==2 then
            stroke(255,0,0)
        elseif z==#c1.points then
            stroke(255,255,0)
        end
            line(c1.points[z].x,c1.points[z].y,c1.points[z-1].x,c1.points[z-1].y)        
    end
end

Thanks @dave1707

I played with this for awhile and was able to get the ball in the hole a few times. Waiting to see the finished version.

@dave1707 like so many of my projects it will unlikely get to a finished version :smile:

Here is a work in progress. Lots left to do including a better shot control, but for the time touch below the club selection line to hit the ball. Ball hits on release, x position sets the animation of the swing and the higher the touch the stronger the shot. Different clubs have different lofts.

@West It has a lot of potential, I like it. I managed to get a hole in 1.