# Multiple physics objects

I was making a small game for me to play when I’m bored and I came across an issue.
What I want to do is shoot bullets by clicking on the screen and it also happens that way.
But if I click quickly then the first bullet disappears and a new bullet is formed. I need to know how can I make the first bullet go on even after making a second one. I tried to see the inbuilt physics example, test 1, where he creates multiple polygons but I couldn’t understand it.
Here is my code.

``````function setup()
bullet = physics.body(CIRCLE,10)
end

function draw()
background(0, 0, 0, 255)
pushStyle()
fill(255, 255, 255, 255)
ellipse(bullet.x,bullet.y,10)
popStyle()
end

function createBullet()
bullet.x = x
bullet.y = y
bullet.linearVelocity = vec2(1000,0)
bullet.restitution = 0
bullet.type = DYNAMIC
end

function touched(touch)
x = touch.x
y = touch.y
if touch.state == BEGAN then
createBullet()
end
end
``````

Hi again, Saurabh

You need to add your bullets to a table, so in set up you add

``````bullets={}
``````

Then in createBullet you add at the end

``````table.insert(bullets,bullet)
``````

Then in draw, you loop through your bullets

``````for i,b in bullets do
ellipse(b.x,b.y,10)
--insert code here to adjust position of bullet for next time
--then check if bullet is off screen
if b.x<1 or b.x>WIDTH or b.y<1 or b.y>HEIGHT or [anything else you want to test] then
b=nil --remove bullet from table
end
end
``````

Thanks for the quick reply!
But I’m getting an error stating “attempt to call table value” in function setup.
Can you explain what you mean by inserting code to adjust position of next bullet
I’m new to coding, I’m interested in it too, but a few things are just going a bouncer

This is untested, but I think it’s what Ignatz meant.

I suspect the error you got was due to a missing `pairs`.

``````function setup()
bullets = {}
end

function draw()
background(0, 0, 0, 255)
pushStyle()
fill(255, 255, 255, 255)
local dels = {}
for k,v in ipairs(bullets) do
ellipse(v.x,v.y,10)
if v.x<1 or v.x>WIDTH or v.y<1 or v.y>HEIGHT then
table.insert(dels,k,1)
end
end
for _,v in ipairs(dels) do
table.remove(bullets,v)
end
popStyle()
end

function createBullet(x,y)
local bullet = physics.body(CIRCLE,10)
bullet.x = x
bullet.y = y
bullet.linearVelocity = vec2(1000,0)
bullet.restitution = 0
bullet.type = DYNAMIC
table.insert(bullets,bullet)
end

function touched(touch)
if touch.state == BEGAN then
createBullet(touch.x,touch.y)
end
end
``````

I hadn’t noticed you were using physics objects. Try this code. Note I’ve moved the definition of bullet into createBullet, and made it local, so a new bullet is created each time. If you create your bullet in setup, then even if you add it to a table, you are adding the same old bullet.

I might write a post about this because it is interesting.

``````function setup()
physics.gravity(0,0) -- turn gravity off
bullets={}
end

function draw()
background(0, 0, 0, 255)
pushStyle()
fill(255, 255, 255, 255)
for i,b in pairs(bullets) do
ellipse(b.x,b.y,10)
--then check if bullet is off screen
if b.x<1 or b.x>WIDTH or b.y<1 or b.y>HEIGHT then
b=nil --remove bullet from table
end
end
popStyle()
end

function createBullet()
--create bullet in here
local bullet = physics.body(CIRCLE,10)
bullet.x = x
bullet.y = y
bullet.linearVelocity = vec2(100,0)
bullet.restitution = 0
bullet.type = DYNAMIC
table.insert(bullets,bullet)
end

function touched(touch)
x = touch.x
y = touch.y
if touch.state == BEGAN then
createBullet()
end
end
``````

Thanks guys it worked perfectly the both of them.

I am into a new issue now what I did is that I added some ballons which rise from the bottom and we have to shoot those ballons using the bullets.
I can make the ballons but I can’t make them disappear properly I am using table.remove and collide(contact) as all of them are physics objects but I can’t figure out how to give each ballon a unique name I tried out the following code but most of the times I hit one ballon and some other ballon pops and though the ballon disappears the physics object stays there and I also want the bullets to burst along with the ballon

I used sound so that I can come to know when there’s contact

Here’s the code

``````function setup()
physics.gravity(0,0)
bullets={}
ball = {}
for i = 1,5 do
ball[i] = Ballons()
ball[i].info = "ball[i]"
end
end

function draw()
background(255, 255, 255, 255)
pushStyle()
fill(0, 0, 0, 255) -- drawing the bullets
for i,b in pairs(bullets) do
ellipse(b.x,b.y,10)
if b.x<1 or b.x>WIDTH or b.y<1 or b.y>HEIGHT then
b=nil
end
end
popStyle()
for i = 1,#ball do -- drawing the ballons
pushStyle()
fill(ball[i].ballon.colr)
popStyle()
end
end

function createBullet()
local bullet = physics.body(CIRCLE,5)
bullet.x = x
bullet.y = y
bullet.linearVelocity = vec2(1000,0)
bullet.restitution = 0
bullet.type = DYNAMIC
bullet.info = "bullet"
table.insert(bullets,bullet)
end

function touched(touch)
x = touch.x
y = touch.y
if touch.state == BEGAN then
createBullet()
end
end

function collide(contact)
if contact.bodyA.info == "ball[i]" or contact.bodyB.info == "ball[i]" and
contact.bodyA.info == "bullet" or contact.bodyB.info == "bullet" then
if contact.state == BEGAN then
sound(DATA, "ZgNAfj01Pzc2Qz1AnatePohA3T0LSTE+YgB/fz54NlVoQ0A6")
table.remove(ball,i,ball[i])
table.remove(bullets,bullet)
end
end
end

Ballons = class()

function Ballons:init(x,y,r,c,lv)
self.radius = r or math.random(25,50)
self.ballon.x = x or math.random(WIDTH/2,WIDTH)
self.ballon.y = y or math.random(-HEIGHT/2,-self.radius)
self.ballon.linearVelocity = lv or vec2(0,math.random(100,150))
self.ballon.colr = c or color(math.random(255),math.random(255),math.random(255),math.random(100,150))
end
``````

You can edit your posts so there’s no need to double post the code. I added the tildes to the first post and deleted (removed from view, nothing gets truly deleted) the second. Hope that’s okay.

It’s completely fine See below

1. when you are deleting objects in tables, it’s probably best to use the for…pairs approach when looping, because the usual for i=1,… loop may not work properly once there are gaps in the table

2. you need to destroy the physics objects with the destroy function before setting them to nil, otherwise they will live on
however…

3. destroying physics objects in the collide function seems to cause Codea to crash, so I’ve simply stored the details and done the deletion in draw

``````function setup()
physics.gravity(0,0)
bullets={}
ball = {}
for i = 1,5 do
ball[i] = Ballons()
end
end

function draw()
background(255, 255, 255, 255)

if collision~=nil then        ------------------- see note 3. above
ball[collision].ballon:destroy()   --- see note 2 above
table.remove(ball,collision)
bullets[collision]:destroy()
table.remove(bullets,collision)
collision=nil
end

pushStyle()
fill(0, 0, 0, 255) -- drawing the bullets
for i,b in pairs(bullets) do
ellipse(b.x,b.y,10)
if b.x<1 or b.x>WIDTH or b.y<1 or b.y>HEIGHT then
b=nil
end
end
popStyle()

for i,b in pairs(ball) do -- drawing the ballons
pushStyle()
fill(b.colr)
popStyle()
end
end

function createBullet()
local bullet = physics.body(CIRCLE,5)
bullet.x = x
bullet.y = y
bullet.linearVelocity = vec2(1000,0)
bullet.restitution = 0
bullet.type = DYNAMIC
bullet.info = "bullet"
table.insert(bullets,bullet)
end

function touched(touch)
x = touch.x
y = touch.y
if touch.state == BEGAN then
createBullet()
end
end

function collide(contact)
if contact.bodyA.info~=nil and contact.bodyB.info~=nil then
for i,b in pairs(ball) do
if b.ballon==contact.bodyA or b.ballon==contact.bodyB then
for j,bb in pairs(bullets) do
if bb==contact.bodyA or bb==contact.bodyB then
sound(DATA, "ZgNAXS4wQEBAQEBA/9iePiN3mD64nKs+cgBAf0BAQEBAb0BA  ")
collision={i,j}   -- see note 3 above
end
end
end
end
end
end

Ballons = class()

function Ballons:init(x,y,r,c,lv)
self.radius = r or math.random(25,50)
self.ballon.x = x or math.random(WIDTH/2,WIDTH)
self.ballon.y = y or math.random(-HEIGHT/2,-self.radius)
self.ballon.linearVelocity = lv or vec2(0,math.random(100,150))
self.ballon.info="ball"
self.colr = c or color(math.random(255),math.random(255),math.random(255),math.random(100,150))
end
``````

.@Ignatz, @Saurabh There is still one more thing you need to do, that’s to destroy the physics.bodies that were removed from the table. If you shoot at a ballon and remove it, even though you don’t see it anymore, the bullets still bounce off it and the program crashes after awhile.

yep, I fixed that above. Had a bit of trouble with Codea crashing if I destroyed objects in the collide function.

Thanks for the post Ignatz.
But the code you have shared in the post is not working properly, the code over here is working perfectly fine I can’t find out what you have missed out. I think you should paste the code from here to your post.
And by the way I’m a guy and 16

Oops!! I’ll fix that.

Done, I hope.

. @Ignatz Another way you could destroy the objects is to set up a variable like self.ballon.destroy and bullet.destroy. Set them to false when each object is created, then set them to true when they need to be destroyed. In the draw function, if they need to be destroyed, destroy them and remove them from the table, else draw them.

@dave1707 absolutely. I took the suggestion of a table (or “stack”) of objects to be destroyed from one of the help pages, but your way looks good, too.

How can we keep track of the number of bullets that don’t hit the ballon and go beyond the WIDTH of the screen if I make a function to increase count by one then if its called the number keeps on increasing (60 per second)

I tried it using this class

``````
Point = class()

function Point:init(score)
self.score = score or 0
end

function Point:ScoreIncrease()
for i,b in pairs(bullets) do
if b.x<1 or b.x>WIDTH or b.y<1 or b.y>HEIGHT then
self.score = self.score + 1
end
end
end

``````

The inbuilt codes like invader were too complicated for me to understand.
And I had parameter.watch in setup to check value

Why do you need a class? Just put your counter into draw (you’re already checking if the bullet is offscreen in there)

If I put it in draw the value keeps on increasing even if one bullet passes through
I use count = count +1.
How should I make counter stop??

Try this, see the line marked ADD THIS. This should only increase when a bullet goes off the edge.

``````function draw()

....other code

pushStyle()
fill(0, 0, 0, 255) -- drawing the bullets
for i,b in pairs(bullets) do
ellipse(b.x,b.y,10)
if b.x<1 or b.x>WIDTH or b.y<1 or b.y>HEIGHT then
b=nil
score=score+1.     -- ADD THIS
end
end
popStyle()

.....other code....
end
``````