Pinball Physics

First of all, excuse the newbness. I’m not only new to Corona, but also Lua (previously a professional web developer). That said, I feel like I’m picking both up pretty quickly, but have ran into a small problem I was hoping I could get some community help with.

I’m attempting to build a simple pinball game, which is really just practice/prototype for a larger idea I’ve got in mind. So far I’ve got some very basic elements in place - paddles which rotate correctly when you touch them, a ball which falls, etc.

The problem I’m finding is the interaction between the paddles and the ball being very “squishy” (for lack of a better word). I touch the paddle when the ball is near, the paddle moves quickly, and while the paddle does obviously interact with the ball (moving it a bit), the paddle also passes through the ball to some degree, producing a very unrealistic/unconvincing effect. At best it feels like they’re on top of each other, at worst they seem to be slowing each other down.

What I want (like in a real pinball game) is there to be a clear physical interaction between the paddle and ball, which shoots the ball upward (in an appropriate angle based on the interaction) realistically.

Admittedly my knowledge of physics is not what it used to be, but in the case of Corona they seem to be pretty simple (which is good I think). I’ve played with the bounce, density, friction, as well as the various body types. So far nothing has been able to add a real obvious “connection” between the objects.

I believe this is possible as I saw an example of a released hybrid Soccer/Pinball game written in Corona, but it unfortunately did not expose any code. ):

For reference my basic code follows:

[lua]local physics = require(“physics”)
physics.start()

– Ball

local ball = display.newImage(“ball.png”)
ball.x = 100
ball.y = 0

physics.addBody(ball, { friction=.8; bounce=0.5; radius=14; density=1.5; } )

– Left Paddle

local lPaddle = display.newImage(“lPaddle.png”)
lPaddle.x = 70
lPaddle.y = display.contentHeight - 30
lPaddle.xScale = 1
lPaddle.yScale = 1
lPaddle:setReferencePoint(display.CenterLeftReferencePoint)

physics.addBody(lPaddle, { friction=.8; bounce=0.1; density=1.5 } )
lPaddle.bodyType = “kinematic”

– Events

function moveLeftPaddle(event)
transition.to(lPaddle, { time=150; rotation=-90; })
transition.to(lPaddle, { time=150; delay=100; rotation=0; })
end

lPaddle:addEventListener(“touch”, moveLeftPaddle)[/lua]

Thanks ahead for any help. Challenges aside, I’ve been highly impressed by both this tool and the community (and Lua is pretty awesome too).

=Luke
[import]uid: 10553 topic_id: 3098 reply_id: 303098[/import]

Try setting isBullet to the paddles. [import]uid: 5712 topic_id: 3098 reply_id: 9104[/import]

I agree that should work (based on the SDK description), but it doesn’t seem to make any noticeable difference… Basically I added

[lua]lPaddle.isBullet = true[/lua]

after the .addBody statement for the paddle. I tried adding it to the ball as well. Neither seem to do anything. ): [import]uid: 10553 topic_id: 3098 reply_id: 9112[/import]

Did you try setting the update rate for the physic to 60 fps? And changing the paddle bodytype to dynamic? [import]uid: 5712 topic_id: 3098 reply_id: 9133[/import]

I have added the code to set it to 60fps (below) - which also had no noticable effect. Also, if I set the paddle to Dynamic - it falls off the screen. I’m not sure if there is another step to stop that from happening.

config.lua:
[lua]application =
{
content =
{
fps = 60,
},
}[/lua] [import]uid: 10553 topic_id: 3098 reply_id: 9203[/import]

Still haven’t been able to figure this out. ): [import]uid: 10553 topic_id: 3098 reply_id: 9472[/import]

Try to contact Ansca, maybe they can get the info from the creators of that soccer/pinball game. [import]uid: 5712 topic_id: 3098 reply_id: 9478[/import]

wow I fiddled with your code a little and then commented out the second transition line (the one that returns the paddle to its original position). As expected, the paddle doesnt return to the original position. But to my surprise, the ball still acts like the paddle is still DOWN!

Either we are misunderstanding something here or it is seriously broked.

local physics = require("physics")  
physics.setDrawMode("hybrid") -- normal, debug, hybrid  
physics.setScale(30)  
physics.start(true)  
  
-- Ball  
  
local ball = display.newImage("ball.png")  
ball.x = 100  
ball.y = 0  
   
physics.addBody(ball, { friction=.8; bounce=0.5; radius=14; density=3.5; } )  
   
-- Left Paddle  
   
local lPaddle = display.newImage("lPaddle.png")  
lPaddle.x = 87  
lPaddle.y = display.contentHeight - 30  
lPaddle.xScale = 1  
lPaddle.yScale = 1  
lPaddle:setReferencePoint(display.CenterLeftReferencePoint)  
   
physics.addBody(lPaddle, { friction=.8; bounce=0.1; density=5.5 } )  
lPaddle.bodyType = "kinematic"  
   
-- Events  
   
function moveLeftPaddle(event)  
 transition.to(lPaddle, { time=150; rotation=-90; })   
-- transition.to(lPaddle, { time=150; delay=100; rotation=0; })   
end  
   
lPaddle:addEventListener("touch", moveLeftPaddle)  

[import]uid: 9562 topic_id: 3098 reply_id: 9482[/import]

@lukefrieler:

I fiddled with your code a bit, adding some walls, and attached the paddle and the left to a physics joint. The ball still “sinks” to the paddle, but not that much anymore.

local physics = require("physics")  
physics.start()  
physics.setDrawMode("debug")  
  
-- Ball  
  
local ball = display.newImage("ball.png")  
ball.x = 100  
ball.y = 20  
  
physics.addBody(ball, { friction=1; bounce=0.8; radius=14; density=1; } )  
-- Left Paddle  
  
--local socket = display.newCircle( 0, display.contentHeight - 30, 15 )  
--physics.addBody(socket, { friction=1; bounce=0.1; density=50 } )  
  
local lPaddle = display.newImage("lPaddle.png")  
lPaddle.x = 0  
lPaddle.y = display.contentHeight - 30  
--lPaddle.xScale = 1  
--lPaddle.yScale = 1  
--lPaddle:setReferencePoint(display.CenterLeftReferencePoint)  
lPaddle.isBullet=true  
  
physics.addBody(lPaddle, { friction=1; bounce=0.1; density=50 } )  
lPaddle.bodyType = "dynamic"  
  
--\> Create Walls  
local leftWall = display.newRect (0, 0, 20, display.contentHeight)  
 leftWall:setFillColor (255, 255, 255, 128)  
local rightWall = display.newRect (display.contentWidth, 0, 1, display.contentHeight)  
local ceiling = display.newRect (0, 0, display.contentWidth, 1)  
local floor = display.newRect (0, display.contentHeight, display.contentWidth, 1)  
  
physics.addBody (leftWall, "static", {bounce = 0.0, density=10 , friction = 1})  
physics.addBody (rightWall, "static", {bounce = 0.0, friction = 10})  
physics.addBody (ceiling, "static", {bounce = 0.0, friction = 10})  
physics.addBody (floor, "static", {bounce = 0.0, friction = 10})  
  
--add joint  
  
pinballJoint = physics.newJoint ( "pivot", lPaddle, leftWall, lPaddle.x, lPaddle.y)  
pinballJoint.isMotorEnabled = true  
pinballJoint.isLimitEnabled = true  
--pinballJoint.maxMotorTorque = 100000  
pinballJoint:setRotationLimits ( 0.1, 90 )  
  
-- Events  
  
function moveLeftPaddle(event)  
 --transition.to(lPaddle, { time=250; rotation=-90; })  
 --transition.to(lPaddle, { time=550; delay=100; rotation=0; })  
 lPaddle:applyLinearImpulse(0,-1600,lPaddle.width, lPaddle.y)  
end  
  
Runtime:addEventListener("touch", moveLeftPaddle)  

As a fellow beginner, this code reflects what I have learned so far.
Hope this helps ;D [import]uid: 11930 topic_id: 3098 reply_id: 15324[/import]

This is a problem I’ve been running into as well… it would appear that changing the reference point to anything other than the center causes issues. The worst part is that debug draw mode doesn’t work as advertised: when you change the reference point for a physics object, the debug box on screen reflects the changed reference point, but the actual physics object does not, so you end up with objects bouncing off invisible objects: even in debug mode!

If anyone has advice about a way to change the reference point without breaking the physics engine (with sample code!) I’d love to see it.

The method that geodelapaz uses of sticking half the paddle off-screen won’t be appropriate for most situations, but I can’t think of another way to create a reliable paddle type object without moving the reference point. [import]uid: 14598 topic_id: 3098 reply_id: 26345[/import]

To be honest - I gave up. I could never get it working, and just didn’t have the energy to keep focusing on it. ): [import]uid: 10553 topic_id: 3098 reply_id: 26349[/import]

Since people are still looking at this thread…

Without seeing the paddle image itself, I note there’s no physics shape given for the paddle in the latest code version. (It could be the paddle is the full size of the image, in which case you don’t really need the shape… but either way it may help with the interaction.) Another thing to consider is toying slightly with the ball radius. [import]uid: 13859 topic_id: 3098 reply_id: 26552[/import]

I’m running exactly into the same issue: http://developer.anscamobile.com/forum/2011/03/20/wrong-physics-collisions-when-body-rotated-and-reference-point-not-centered

Collisions bug when a body is rotated and reference point is not centered. [import]uid: 10990 topic_id: 3098 reply_id: 28554[/import]

“when your enemy is too strong, outflank him” :slight_smile:
I guess a bypass for this would be to have your paddle graphic “mirrored”, with the exact same shape at the opposite end, but invisible, so it makes the rotation at it center, and have the opposite, invisible one, in an area where you don’t have any physics interaction. [import]uid: 44010 topic_id: 3098 reply_id: 29118[/import]

I haven’t read through that thread so maybe you already tried this, but what if you don’t change the reference point and simply draw a custom physics shape that extends off to the side? [import]uid: 12108 topic_id: 3098 reply_id: 29390[/import]

Hi,

Was the “Collisions bug when a body is rotated and reference point is not centered” fixed?

Will be creating a baseball game, so I will be rotating the baseball bat.

Thank you,
Mike

[import]uid: 53445 topic_id: 3098 reply_id: 34420[/import]

mike1: I dont know if it was ever fixed. I tried to create an android game with corona and there were so many problems that I decided to come back in a year or so and see if Corona’s android stuff had gotten better.
[import]uid: 9562 topic_id: 3098 reply_id: 34598[/import]

I tried geodelapaz code and it seemed to work o.k. It did seem to sink into the paddle at 30FPS, but at 60 FPS it worked very good.
Using a delta timing would work even better.

jlolofie, I just purchased Corona SDK Pro license mainly to convert my IOS games to Android. Hope everything works o.k.

I’m coming from GLBasic, so I am completely lost with LUA and events.
[import]uid: 53445 topic_id: 3098 reply_id: 34624[/import]

I have been experimenting with building a pinball game. I have a basic playfield programmed with a bumper, slingshot and flipper. There is no scoring and no sound. This is just to test out the physics, mainly that of the flipper and ball collisions.

I believe that I have the flipper and ball collisions working satisfactory. You are invited to inspect and use my code. You can download it here:

http://martinapps.com/files/pinball physics.zip

My thanks to Jonathan Beebe for his tip about waiting to do the processing associated with a collision event. I’m using the runtime “enterframe” event instead of the timer.performWithDelay that he used. Search for this statement in my code: Runtime:addEventListener( “enterFrame”, doCollision ) [import]uid: 23636 topic_id: 3098 reply_id: 38756[/import]

Hey Bruce, is this code still available? The link is broken.