I want to know how to collide things( for example: when a character collides with a ball then the character goes the other way ).
You can use the physics engine which will calculate everything very close to how it would react in the real world. Check out the physics lab examples to get an idea of how to do this.
For making a character react appropriately to collisions, you often don’t want to use the physics engine, though. Check out the Brickout example for a lesson on how to manually check for collisions and change an objects direction.
Here is a small example to get you started. A lot of this you can ignore, but look at the physics documentation and this example to get an idea of what you need. The best way to learn is to take an example, modify it and see what happens. As always, if you have more questions, we’re all here to help.
function setup()
b=65 -- starting value for letter A
c1 = physics.body(CIRCLE,5) -- create boundary for the letter
c1.x=295
c1.y=900
c1.restitution=.8
c1.gravityScale=1
c2 = physics.body(CIRCLE,50) -- create boundary for 1st circle
c2.type=STATIC
c2.x=300
c2.y=600
c3 = physics.body(CIRCLE,50) -- create boundary for 2nd circle
c3.type=STATIC
c3.x=120
c3.y=400
end
function draw()
a=string.char(b) -- convert value to a letter
background(30, 30, 30, 25)
stroke(255)
strokeWidth(1)
noFill()
ellipse(c2.x,c2.y,100,100) -- draw the 1st circle
ellipse(c3.x,c3.y,100,100) -- draw the 2nd circle
fill(255)
fontSize(30)
text(a,c1.x,c1.y) -- draw the letter
-- get next letter when previous gets below y position of 20
if c1.y<20 then
c1.y=900
c1.x=295
c1.linearVelocity=vec2(0,0)
b = b + 1
if b>90 then
b=65
end
end
end
@dave1707 Hey thanks a lot Dave! This very short piece of code is really useful for a newbe as myself. Several very short codes like this are better than a big, comprehensive , accurate but … scary piece of code: it shows Codea is really an easy platform and one can quickly have fun with it. Thanks!
@Rakarinn i have made this exemple of colliding particles with two bumpers, right from the exemple of Dave1707, in a couple hours. This is my first Codea program and i am rather proud of the result (remember, i am a newbe, so it doesn’t take much to make me happy!)
@dave1707 As you can see you quick exemple really helped me to go a step further, and really quick! Thanks a lot!
– Collision
function setup()
-- create balls
NUMBALLS = 10
SPEED0 = 1000
ball = {}
for i=0,NUMBALLS do
ball[i] = physics.body(CIRCLE,20)
ball[i].x = math.random(WIDTH/2) + WIDTH/4
ball[i].y = math.random(HEIGHT/2) + HEIGHT/4
ball[i].restitution = .9
ball[i].gravityScale = 0
ball[i].linearVelocity=vec2(math.random(SPEED0)-SPEED0/2,math.random(SPEED0)-SPEED0/2)
end
c2 = physics.body(CIRCLE,50) -- create boundary for 1st circle
c2.type=STATIC
c2.x=WIDTH/3
c2.y=HEIGHT/3
c2.restitution=2
c3 = physics.body(CIRCLE,50) -- create boundary for 2nd circle
c3.type=STATIC
c3.x=WIDTH/3*2
c3.y=HEIGHT/3
c3.restitution=2
-- create borders
local w = 5
b0 = physics.body(POLYGON, vec2(0,w), vec2(0,0), vec2(WIDTH,0), vec2(WIDTH,w))
b0.type = STATIC
b1 = physics.body(POLYGON, vec2(0,0), vec2(w,0), vec2(w,HEIGHT), vec2(0,HEIGHT))
b1.type = STATIC
b2 = physics.body(POLYGON, vec2(WIDTH - w,0), vec2(WIDTH,0), vec2(WIDTH,HEIGHT), vec2(WIDTH - w,HEIGHT))
b2.type = STATIC
b3 = physics.body(POLYGON, vec2(0,HEIGHT), vec2(0,HEIGHT - w), vec2(WIDTH,HEIGHT - w), vec2(WIDTH,HEIGHT))
b3.type = STATIC
end
function draw()
background(30, 30, 30, 25)
stroke(255)
strokeWidth(1)
noFill()
ellipse(c2.x,c2.y,100,100) -- draw the 1st circle
ellipse(c3.x,c3.y,100,100) -- draw the 2nd circle
fill(255, 13, 0, 255)
for i=0,NUMBALLS do
ellipse(ball[i].x,ball[i].y,40,40) -- draw the circle
end
end
Ooops! I hadnt read about the ‘three tilde’ format around the code.
Sorry
-- Collision
function setup()
-- create balls
NUMBALLS = 10
SPEED0 = 1000
ball = {}
for i=0,NUMBALLS do
ball[i] = physics.body(CIRCLE,20)
ball[i].x = math.random(WIDTH/2) + WIDTH/4
ball[i].y = math.random(HEIGHT/2) + HEIGHT/4
ball[i].restitution = .9
ball[i].gravityScale = 0
ball[i].linearVelocity=vec2(math.random(SPEED0)-SPEED0/2,math.random(SPEED0)-SPEED0/2)
end
c2 = physics.body(CIRCLE,50) -- create boundary for 1st circle
c2.type=STATIC
c2.x=WIDTH/3
c2.y=HEIGHT/3
c2.restitution=2
c3 = physics.body(CIRCLE,50) -- create boundary for 2nd circle
c3.type=STATIC
c3.x=WIDTH/3*2
c3.y=HEIGHT/3
c3.restitution=2
-- create borders
local w = 5
b0 = physics.body(POLYGON, vec2(0,w), vec2(0,0), vec2(WIDTH,0), vec2(WIDTH,w))
b0.type = STATIC
b1 = physics.body(POLYGON, vec2(0,0), vec2(w,0), vec2(w,HEIGHT), vec2(0,HEIGHT))
b1.type = STATIC
b2 = physics.body(POLYGON, vec2(WIDTH - w,0), vec2(WIDTH,0), vec2(WIDTH,HEIGHT), vec2(WIDTH - w,HEIGHT))
b2.type = STATIC
b3 = physics.body(POLYGON, vec2(0,HEIGHT), vec2(0,HEIGHT - w), vec2(WIDTH,HEIGHT - w), vec2(WIDTH,HEIGHT))
b3.type = STATIC
end
function draw()
background(30, 30, 30, 25)
stroke(255)
strokeWidth(1)
noFill()
ellipse(c2.x,c2.y,100,100) -- draw the 1st circle
ellipse(c3.x,c3.y,100,100) -- draw the 2nd circle
fill(255, 13, 0, 255)
for i=0,NUMBALLS do
ellipse(ball[i].x,ball[i].y,40,40) -- draw the circle
end
end
I’m glad I could help. I find small examples that get to the point are easier to follow and learn from than large ones that do a lot of other things. As you figured out, it doesn’t take a lot of code to do interesting things. If you’re interested in another example along the same line, here is a program I wrote back in June.
-- Random PinBall by Dave1707
function setup()
displayMode(FULLSCREEN)
-- define variables and tables
cx=0
cy=0
limit=150
tab1={}
tab2={}
create() -- set table values
-- set pinball values
circ1 = physics.body(CIRCLE,5)
circ1.x=300
circ1.y=HEIGHT-50
circ1.gravityScale=.6
circ1.restitution=1
-- set line values
line1 = physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT))
line2 = physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT))
line3 = physics.body(EDGE,vec2(0,0),vec2(WIDTH,0))
line4 = physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT))
end
function create()
-- set initial values for pins in tables
for x=1,limit do
tab1[x] = physics.body(CIRCLE,10)
tab1[x].x = math.random(WIDTH)
tab1[x].y = math.random(HEIGHT)
tab1[x].type = STATIC
tab2[x]=0 -- 0=pin not hit, 1=pin was hit
end
end
function collide(contact)
-- check for collision
if contact.state == BEGAN then
cx=contact.bodyA.x -- x position of hit pin
cy=contact.bodyA.y -- y position of hit pin
-- restart pinball when at bottom of screen
if circ1.y < 20 then
circ1.y = HEIGHT-50
circ1.x = math.random(WIDTH)
end
end
end
function draw()
background(0, 0, 0)
-- draw pinball
fill(255,0,0,255)
ellipse(circ1.x,circ1.y,10,10)
-- draw boundary lines
line(0,0,0,HEIGHT)
line(WIDTH,0,WIDTH,HEIGHT)
line(0,0,0,WIDTH)
line(0,HEIGHT,WIDTH,HEIGHT)
-- draw flashing pins or white pins each draw cycle
for x=1,limit do
-- check which pin was hit
if cx == tab1[x].x and cy == tab1[x].y then
tab2[x] = 1 -- set table for hit pin
cx=0 -- clear values
cy=0
end
fill(255) -- set color to white
if tab2[x] > 0 then -- pin was hit, set random color
fill(math.random(255),math.random(255),math.random(255),255)
end
ellipse(tab1[x].x,tab1[x].y,20) -- draw pins
end
-- draw credits
fill(0, 252, 0, 255)
text("Random PinBall by Dave1707",WIDTH/2,HEIGHT/2)
end
Lots of helpful stuff here however how would you do a game over screen when object gets hit. Any advice would be appreciated.
Not exactly sure what you’re after. Maybe something here will give you an idea.
function setup()
displayMode(FULLSCREEN)
showShip=true
explodeShip=false
endGame=false
x=0
e=30
end
function draw()
background(40, 40, 50)
x = x + 1 -- simulate game
if showShip then
ship()
if x==100 then -- simulate ship being hit
explodeShip=true
end
end
if explodeShip then
explode()
end
if endGame then
endOfGame()
end
end
function ship()
sprite("SpaceCute:Rocketship",350,500)
end
function explode()
e = e + 2
sprite("Tyrian Remastered:Explosion Huge",350,500,e,e)
if e>500 then
showShip=false
explodeShip=false
endGame=true
end
end
function endOfGame()
fill(255)
font("Baskerville-SemiBold")
fontSize(40)
text("End of Game",WIDTH/2,HEIGHT/1.3)
text("Press New Game for another game",WIDTH/2,HEIGHT/1.5)
fill(255,0,0)
text("NEW GAME",WIDTH/2,HEIGHT/1.8)
end
My program keeps crashing (codea closes) when i try to use the body.info property to store a value like a number or a string. Can someone tell me how to use this property? Thanks
@dave1707 @Simeon
Body.info uses a table. I don’t think there’s anything that says that, but this example works.
function setup()
tab={"qwerty","asdfg","zxcvb"}
circle = physics.body(CIRCLE,10)
circle.info=tab
print(circle.info)
print()
for x,y in pairs(circle.info) do
print(x,y)
end
end
thanks dave however i was looking for if an object hits something it then explodes and then game over screen. I believe you helped me before on the math.randomseed topic, and this is for that same game I have managed to get it to explode but can not figure out how to then get game over screen. I already have a game over screen just wondering how you get to it. Sorry if I wasn’t clear before.
@dave1707 thanks for this info. @Simeon maybe the fact that body.info is a table should be added in the refrence? Without this information i couldnt make it work. By the way, i have the feeling that in a contact involving contact.bodyA and contact.bodyB, bodyA is always the physics object that was defined first in the code. This is useful to know (if true) because only half the number of tests have to be made during a collision.
As an example for others who need a hand to start with collisions, here is my last version of the code: access to body info, collision management, sounds… Woks nicely.
-- Collision
function setup()
-- create balls
NUMBALLS = 10
SPEED0 = 1000
ball = {}
ballInfo = {}
for i=0,NUMBALLS do
ball[i] = physics.body(CIRCLE,20)
ball[i].x = math.random(WIDTH/2) + WIDTH/4
ball[i].y = math.random(HEIGHT/2) + HEIGHT/4
ball[i].restitution = 0.9
ball[i].gravityScale = 0
ball[i].linearVelocity=vec2(math.random(SPEED0)-SPEED0/2,math.random(SPEED0)-SPEED0/2)
ball[i].info = {} -- body.info is a table and has to be initialized otherwise ..bug!
ball[i].info.state = 0
ball[i].info.type = "ball"
end
c2 = physics.body(CIRCLE,50) -- create boundary for 1st circle
c2.x=WIDTH/3
c2.y=HEIGHT/2
c2.restitution=0.9
c2.gravityScale = 0
c2.info = {}
c2.info.state = 0
c2.info.type = "target"
c3 = physics.body(CIRCLE,50) -- create boundary for 2nd circle
c3.type=STATIC
c3.x=WIDTH/3*2
c3.y=HEIGHT/2
c3.restitution=4
c3.info = {}
c3.info.state = 0
c3.info.type = "bumper"
-- create borders
local w = 5
b0 = physics.body(POLYGON, vec2(0,w), vec2(0,0), vec2(WIDTH,0), vec2(WIDTH,w))
b0.type = STATIC
b1 = physics.body(POLYGON, vec2(0,0), vec2(w,0), vec2(w,HEIGHT), vec2(0,HEIGHT))
b1.type = STATIC
b2 = physics.body(POLYGON, vec2(WIDTH - w,0), vec2(WIDTH,0), vec2(WIDTH,HEIGHT), vec2(WIDTH - w,HEIGHT))
b2.type = STATIC
b3 = physics.body(POLYGON, vec2(0,HEIGHT), vec2(0,HEIGHT - w), vec2(WIDTH,HEIGHT - w), vec2(WIDTH,HEIGHT))
b3.type = STATIC
end
function collide(contact)
-- check for collision
if contact.state == ENDED then
if contact.bodyA.info.type == "ball" then
if contact.bodyB.info.type == "bumper" then
contact.bodyA.info.state = 1
contact.bodyB.info.state = 1
sound(SOUND_HIT, 2652)
-- print(contact.bodyB.info.type.." "..contact.bodyA.info.type)
end
if contact.bodyB.info.type == "target" then
contact.bodyA.info.state = 2
sound(SOUND_PICKUP, 2652)
-- print(contact.bodyB.info.type.." "..contact.bodyA.info.type)
end
end
end
end
function action(obj,val)
-- print("contact: "..obj.info)
end
function draw()
background(30, 30, 30, 25)
stroke(255)
strokeWidth(1)
fill(0, 1, 255, 255)
ellipse(c2.x,c2.y,100,100) -- draw the 1st circle
-- draw the 2nd circle
fill(255, 222, 0, 255)
if c3.info.state==0 then
ellipse(c3.x,c3.y,100,100)
else
ellipse(c3.x,c3.y,120,120)
c3.info.state = 0
end
for i=0,NUMBALLS do
if ball[i].info.state == 0 then
fill(255, 13, 0, 255)
elseif ball[i].info.state == 1 then
fill(255, 147, 0, 255)
elseif ball[i].info.state == 2 then
fill(255, 0, 236, 255)
end
ellipse(ball[i].x,ball[i].y,40,40) -- draw the circle
end
end
Is this something that you’re after. I added the circles to show you the collision areas. Play around with this to get an idea of what’s happening. There are collisions as soon as the program starts because I set the x,y values for s1, r1, and r2 to the same values in setup.
function setup()
x = WIDTH/2
y = HEIGHT/2
c = color(0, 0, 0, 255)
x1=0
y1=0
s1=physics.body(CIRCLE,30) -- collision area around star
s1.x=x
s1.y=y
r1=physics.body(CIRCLE,90) -- collision area at back of ship
r1.x=x
r1.y=y
r2=physics.body(CIRCLE,40) -- collision area at front of ship
r2.x=x
r2.y=y
end
function draw()
background(0, 0, 0, 225)
x1=x1-5
if x1<1 then
rand()
end
sprite("SpaceCute:Star",x1,y1) -- x,y position of star
s1.x=x1 -- x,y position of star collision area
s1.y=y1
sprite("SpaceCute:Rocketship",150,y) -- x,y position of ship
r1.x=100 -- x,y position of both ship collision areas
r1.y=y
r2.x=230
r2.y=y-10 -- -10 to adjust collision area down
-- this just shows collision area circles, to be removed in game
noFill()
stroke(255)
strokeWidth(4)
ellipse(s1.x,s1.y,60,60)
ellipse(r1.x,r1.y,180,180)
ellipse(r2.x,r2.y-10,80,80) -- -10 to adjust circle down
--
end
function touched(touch)
x = x
y = touch.y
end
function rand()
y1=math.random(100,HEIGHT-100)
x1=WIDTH
end
function collide(contact)
if contact.state == BEGAN then
print("collision") -- collision occurs, add your code here
end
end
On the example that you have where you have the letters bouncing off the balls, how would you code it so you can touch the ball and move it?
Starting here, I have some tutorials on bouncing things with and without physics
http://coolcodea.wordpress.com/2013/03/11/3-moving-an-object-around-the-screen/
. @Andrewsimpson4 I added the touched function so it allows you to move the balls. There are other ways of doing this, but I was in a hurry.
function setup()
b=65 -- starting value for letter A
c1 = physics.body(CIRCLE,5) -- create boundary for the letter
c1.x=295
c1.y=900
c1.restitution=.8
c1.gravityScale=1
c2 = physics.body(CIRCLE,50) -- create boundary for 1st circle
c2.type=STATIC
c2.x=300
c2.y=600
c3 = physics.body(CIRCLE,50) -- create boundary for 2nd circle
c3.type=STATIC
c3.x=120
c3.y=400
end
function draw()
a=string.char(b) -- convert value to a letter
background(30, 30, 30, 25)
stroke(255)
strokeWidth(1)
noFill()
ellipse(c2.x,c2.y,100,100) -- draw the 1st circle
ellipse(c3.x,c3.y,100,100) -- draw the 2nd circle
fill(255)
fontSize(30)
text(a,c1.x,c1.y) -- draw the letter
-- get next letter when previous gets below y position of 20
if c1.y<20 then
c1.y=900
c1.x=295
c1.linearVelocity=vec2(0,0)
b = b + 1
if b>90 then
b=65
end
end
end
function touched(t)
if math.abs(t.x-c2.x)<50 and math.abs(t.y-c2.y)<50 then
c2.x=t.x
c2.y=t.y
end
if math.abs(t.x-c3.x)<50 and math.abs(t.y-c3.y)<50 then
c3.x=t.x
c3.y=t.y
end
end
Thant you so much one more thing how can I make the circles to a rectangle because the physics.body is still set to CIRCLE and I could not figure out how to change that.
. @Andrewsimpson4 I changed one of the circles to a square so you can compare the code for a circle and a square.
function setup()
b=65 -- starting value for letter A
rectMode(CENTER)
c1 = physics.body(CIRCLE,10) -- create boundary for the letter
c1.x=295
c1.y=900
c1.restitution=.8
c1.gravityScale=1
c1.sleepingAllowed=false -- don't let letter sleep
-- create a square physics body
c2 = physics.body(POLYGON,vec2(-50,-50),vec2(-50,50),vec2(50,50),vec2(50,-50))
c2.type=STATIC
c2.x=300
c2.y=600
-- create circle physics body
c3 = physics.body(CIRCLE,50)
c3.type=STATIC
c3.x=120
c3.y=400
end
function draw()
a=string.char(b) -- convert value to a letter
background(30, 30, 30, 25)
stroke(255)
strokeWidth(2)
noFill()
rect(c2.x,c2.y,100,100) -- draw square
ellipse(c3.x,c3.y,100,100) -- draw circle
fill(255)
fontSize(30)
text(a,c1.x,c1.y) -- draw the letter
-- get next letter when previous gets below y position of 20
if c1.y<20 then
c1.y=900
c1.x=295
c1.linearVelocity=vec2(0,0)
b = b + 1
if b>90 then
b=65
end
end
end
function touched(t)
if math.abs(t.x-c2.x)<50 and math.abs(t.y-c2.y)<50 then
c2.x=t.x
c2.y=t.y
end
if math.abs(t.x-c3.x)<50 and math.abs(t.y-c3.y)<50 then
c3.x=t.x
c3.y=t.y
end
end