Can't get rapid-fire guns to work the way I want them to.

I am 11 years old and a novice at Corona.

I have been working to make it so you can have an airplane that moves towards your touch and can fire bullets quickly. I got it to work, but it only fires when your touch is moving and it fires so rapidly it seems more like a flame thrower than a machine gun. How do I get it work so that it fires once each half-second?

Here’s all my code:

[code]
– Activate the physics model
local physics = require(“physics”)
physics.start()
physics.setGravity( 0, 0 )

– Create the background for plane motion purposes
local background = display.newRect( 85, 0, 480, 320 )
background:setFillColor( 0, 0, 0 )

– Create the plane and give it a filter so it doesn’t collide with the bullets it’s firing
local planeCollisionFilter = { categoryBits = 2, maskBits = 0 }

local plane = display.newImage( “plane.png” )
plane.x = display.contentWidth / 2; plane.y = display.contentHeight / 1.25
plane.width = 90; plane.height = 70
physics.addBody( plane, { filter = planeCollisionFilter } )

– Create a function so the plane can be moved around
local function movePlane(event)

distanceX = event.x - plane.x
distanceY = event.y - plane.y
plane:setLinearVelocity( distanceX, distanceY )

end

– Give the background a touch listener so that the plane won’t move when you hit the ‘fire’ button
background:addEventListener( “touch”, movePlane )

– Create a collision filter for the bullets so they don’t collide with the plane
local bulletCollisionFilter = { categoryBits = 1, maskBits = 1 }

– Create a ‘fire’ button
local button = display.newCircle( 35, 285, 25 )
button:setFillColor( 155, 0, 0 )

– Create a function to fire the bullets
local function spawnBullets(event)

local leftBullet = display.newRect( 0, 0, 5, 15 )
leftBullet:setFillColor( 255, 255, 0 )
leftBullet.x = plane.x - 15
leftBullet.y = plane.y - 20
physics.addBody( leftBullet, “kinematic”, { filter = bulletCollisionFilter } )
leftBullet:setLinearVelocity( math.random( -10, 10 ), -200 )

local rightBullet = display.newRect( 0, 0, 5, 15 )
rightBullet:setFillColor( 255, 255, 0 )
rightBullet.x = plane.x + 15
rightBullet.y = plane.y - 20
physics.addBody( rightBullet, “kinematic”, { filter = bulletCollisionFilter } )
rightBullet:setLinearVelocity( math.random( -10, 10 ), -200 )

end

– Give the button a touch listener to fire the bullets
button:addEventListener( “touch”, spawnBullets ) [import]uid: 82408 topic_id: 17037 reply_id: 317037[/import]

This is how I’d do it. There might be a better way, but I can’t think of one.

[blockcode]–boolean variable to prevent firing while the half second is counting down
canFire = true

–new function to set the boolean to false and wait half a second
local function fireCheck
if canFire == true then
canFire = false
timer.performWithDelay (500, spawnBullets, 1)
end
end

–put this inside the spawn bullets function
canFire = true

–change the touch event to this
button:addEventListener( “touch”, fireCheck)[/blockcode] [import]uid: 89724 topic_id: 17037 reply_id: 63920[/import]

Thanks for the code, but I’m getting an error on terminal:

Syntax error: …In Progress/Firing Bullets/main.lua:42: ‘(’ expected near ‘if’

I keep trying different ways to place the brackets, but it’s not working. Here’s the code I have that’s relevant:

[code]
– Boolean variable to prevent firing while the half second is counting down
canFire = true

– New function to set the boolean to false and count down the half second
local function fireCheck
if ( canFire == true ) then
canFire = false
timer.performWithDelay( 500, spawnBullets, 1)
end
end

– Create a function to fire the bullets
local function spawnBullets(event)

local leftBullet = display.newRect( 0, 0, 5, 15 )
leftBullet:setFillColor( 255, 255, 0 )
leftBullet.x = plane.x - 15
leftBullet.y = plane.y - 20
physics.addBody( leftBullet, “kinematic”, { filter = bulletCollisionFilter } )
leftBullet:setLinearVelocity( math.random( -10, 10 ), -200 )

local rightBullet = display.newRect( 0, 0, 5, 15 )
rightBullet:setFillColor( 255, 255, 0 )
rightBullet.x = plane.x + 15
rightBullet.y = plane.y - 20
physics.addBody( rightBullet, “kinematic”, { filter = bulletCollisionFilter } )
rightBullet:setLinearVelocity( math.random( -10, 10 ), -200 )

canFire = true

end

– Give the button a touch listener to fire the bullets
button:addEventListener( “touch”, fireCheck ) [import]uid: 82408 topic_id: 17037 reply_id: 64339[/import]

To modify what x2495iii said :

[code]
–boolean variable to prevent firing while the half second is counting down
local canFire = true

–new function to set the boolean to false and wait half a second
local function fireCheck
if canFire == true then
timer.performWithDelay (500, spawnBullets, 1)
canFire = false --This has to be here not above it or the timer will never execute
end
end

–put this inside the spawn bullets function
canFire = true

–change the touch event to this
button:addEventListener( “touch”, fireCheck)
[/code] [import]uid: 84637 topic_id: 17037 reply_id: 64346[/import]

The error says that the problem is at line 42. Copy line 42 and paste it so we can see it. [import]uid: 89724 topic_id: 17037 reply_id: 64383[/import]

Sure:

[code]
if canFire == true then [import]uid: 82408 topic_id: 17037 reply_id: 64402[/import]

Still having the same terminal error even after your suggestion, Danny:

Syntax error: … In Progress/Firing Bullets/main.lua:42: ‘(’ expected near ‘if’

Why is this? [import]uid: 82408 topic_id: 17037 reply_id: 64382[/import]

The line before that should be

local function fireCheck( )

instead of

local function fireCheck

Keep this close by when you’re coding:
http://www.lua.org/pil/

Have fun. I wish I had Corona SDK when I was 11. [import]uid: 7026 topic_id: 17037 reply_id: 64409[/import]

Great! The crashing’s stopped. The new problem? The bullets don’t fire! It’s not like there’s an error. It’s just the bullets dont fire anymore. Anybody know why? To keep you all updated, here’s the code:

[code]
– Activate the physics model
local physics = require(“physics”)
physics.start()
physics.setGravity( 0, 0 )

– Create the background for plane motion purposes
local background = display.newRect( 85, 0, 480, 320 )
background:setFillColor( 0, 0, 0 )

– Create the plane and give it a filter so it doesn’t collide with the bullets it’s firing
local planeCollisionFilter = { categoryBits = 2, maskBits = 0 }

local plane = display.newImage( “plane.png” )
plane.x = display.contentWidth / 2; plane.y = display.contentHeight / 1.25
plane.width = 90; plane.height = 70
physics.addBody( plane, { filter = planeCollisionFilter } )

– Create a function so the plane can be moved around
local function movePlane(event)

distanceX = event.x - plane.x
distanceY = event.y - plane.y
plane:setLinearVelocity( distanceX, distanceY )

end

– Give the background a touch listener so that the plane won’t move when you hit the ‘fire’ button
background:addEventListener( “touch”, movePlane )

– Create a collision filter for the bullets so they don’t collide with the plane
local bulletCollisionFilter = { categoryBits = 1, maskBits = 1 }

– Create a ‘fire’ button
local button = display.newCircle( 35, 285, 25 )
button:setFillColor( 155, 0, 0 )

– Boolean variable to prevent firing while the half second is counting down
canFire = true

– New function to set the boolean to false and count down the half second
local function fireCheck( )
if canFire == true then
canFire = false
timer.performWithDelay( 500, spawnBullets, 1)
end
end

– Create a function to fire the bullets
local function spawnBullets(event)

canFire = true

local leftBullet = display.newRect( 0, 0, 5, 15 )
leftBullet:setFillColor( 255, 255, 0 )
leftBullet.x = plane.x - 15
leftBullet.y = plane.y - 20
physics.addBody( leftBullet, “kinematic”, { filter = bulletCollisionFilter } )
leftBullet:setLinearVelocity( math.random( -10, 10 ), -200 )

local rightBullet = display.newRect( 0, 0, 5, 15 )
rightBullet:setFillColor( 255, 255, 0 )
rightBullet.x = plane.x + 15
rightBullet.y = plane.y - 20
physics.addBody( rightBullet, “kinematic”, { filter = bulletCollisionFilter } )
rightBullet:setLinearVelocity( math.random( -10, 10 ), -200 )

end

– Give the button a touch listener to fire the bullets
button:addEventListener( “touch”, fireCheck ) [import]uid: 82408 topic_id: 17037 reply_id: 64550[/import]

bump [import]uid: 82408 topic_id: 17037 reply_id: 64910[/import]

i think you need to learn working with tables, the way you spawning bullets is not good practice

learningcorona.com should get you informed [import]uid: 16142 topic_id: 17037 reply_id: 64913[/import]

you can also eliminate the left and right fire code just have one function with x= plane.x+15*dir
then send dir of 1 or -1 for the direction you want

are you using groups if so it could be firing behind the bg put a print statement in the fire function and see if the function is getting called [import]uid: 7911 topic_id: 17037 reply_id: 64919[/import]

You really should also be putting everything into a table. That way you can iterate through all the bullets if you ever need to (lock on bullets for example).

Also, you currently don’t remove any bullets. You need to put up some invisible barriers that will remove the rects and release the memory.

Lastly, don’t use timers. It might be easier right now, but it causes so many problems if the frame rate drops on your device. It causes all sorts of problems. You can just make a local var and count up by 1 each frame. Then just use an ‘if’ statement and check if (myVar > 20) then… This would shoot a bullet every 20 frames. Always go by frames so that even if it lags, everything is based on frames so it won’t mess anything up.

Good luck! [import]uid: 51654 topic_id: 17037 reply_id: 64928[/import]

Right now I’m not using groups, and I just tried the “print” strategy and it doesn’t print what it should. The bullets don’t fire. [import]uid: 82408 topic_id: 17037 reply_id: 65146[/import]

First off, I just made some code to remove the bullets (can’t test it because the bullets don’t fire PERIOD):
[blockcode]
– Create a collision filter for the barrier so the bullets collide with it
local barrierCollisionFilter = { categoryBits = 1, maskBits = 3 }

– Create a barrier to destroy the bullets
local barrier = display.newRect( 0, -20, 480, 10 )
physics.addBody( barrier, “static”, { filter = barrierCollisionFilter } )

– Create a ‘fire’ button
local button = display.newCircle( 35, 285, 25 )
button:setFillColor( 155, 0, 0 )

– Boolean variable to prevent firing while the half second is counting down
canFire = true

– New function to set the boolean to false and count down the half second
local function fireCheck( )
if canFire == true then
canFire = false
timer.performWithDelay( 500, spawnBullets, 1)
end
end

– Create a function to fire the bullets
local function spawnBullets(event)

canFire = true

local leftBullet = display.newRect( 0, 0, 5, 15 )
leftBullet:setFillColor( 255, 255, 0 )
leftBullet.x = plane.x - 15
leftBullet.y = plane.y - 20
physics.addBody( leftBullet, “kinematic”, { filter = bulletCollisionFilter } )
leftBullet:setLinearVelocity( math.random( -10, 10 ), -200 )
leftBullet:addEventListener( “collision”, removeLeftBullet )

local rightBullet = display.newRect( 0, 0, 5, 15 )
rightBullet:setFillColor( 255, 255, 0 )
rightBullet.x = plane.x + 15
rightBullet.y = plane.y - 20
physics.addBody( rightBullet, “kinematic”, { filter = bulletCollisionFilter } )
rightBullet:setLinearVelocity( math.random( -10, 10 ), -200 )
rightBullet:addEventListener( “collision”, removeRightBullet )

print (“firing bullets”)

end

– Give the button a touch listener to fire the bullets
button:addEventListener( “touch”, fireCheck )

– Create some functions to remove the bullets when they collide with things
local function removeLeftBullet(event)
leftBullet:removeSelf()
end

local function removeRightBullet(event)
rightBullet:removeSelf()
end [import]uid: 82408 topic_id: 17037 reply_id: 65149[/import]

Second, I’m really a novice at this. I don’t know what tables really even are. I don’t know exactly how to use frames or var. If you could show me some example code for how I might do what you’re saying, that would be awesome (I’ll try and find an explanation of tables, but so far in the docs they just say “you know, tables” and don’t say what they are. [import]uid: 82408 topic_id: 17037 reply_id: 65151[/import]

I’ve got some stuff to get you started.

Tables:

Near the top of your code, make a table that will hold all your bullets.

local myTable = {}  

Then, after making each bullet, add it into the table using…

table.insert(myTable,myBullet)  

Just replace myBullet with the name of your display object.

This will help you in the future if you ever want to do cool things with them. You can use a simple ‘for’ loop and go through all the bullets in the table.

Frame Animation (Easy Way):

Near the top, make a couple local variable

local bulletCounter = 0;  
local bulletDelay = 60; --Every 60 frames your bullet will shoot  

Then here’s the rest of the code that you’d use:

  
local function doThisEveryFrame()  
  
bulletCounter = bulletCounter +1  
  
if (bulletCounter \>= bulletDelay) then  
  
--Make your bullet here  
  
bulletCounter = 0  
  
end  
  
end  
  
Runtime:addEventListener("enterFrame", doThisEveryFrame)  

That should be enough to get you started. [import]uid: 51654 topic_id: 17037 reply_id: 65152[/import]

Great! It’s working well now. I have to work out the kinks to get the timing just right, but this is very useful. The only issue is now I don’t know how to remove the bullets if they leave the screen. My previous method failed because it crashed the simulator (or at least prevented the code after it from running). Again, thanks a lot! With this stuff we can make some awesome games! I already have an idea for a game. It’ll require a LOT, but I’ll get it done eventually. Thanks everyone! [import]uid: 82408 topic_id: 17037 reply_id: 65295[/import]

Hey Perseus,
Fortunately, this is one of the few things I have learned how to do lol. The only thing I know about tables is that they can be used to create the bricks in a Breakout-style game.

In any case, you would create a long object just outside of the screen with which your bullets would collide. In your case, you could create four of them; one for each edge of the screen.

local platform = display.newRect (0, 0, display.contentWidth * 4, 50)
platform.x = (display.contentWidth/2)
platform.y = -200
physics.addBody(platform, “static”)
platform.name = “platform”
platform:addEventListener(“collision”, platform)

– Platform removes left over moving objects
function platform:collision (event)
if event.other.name == “bullet1” or event.other.name == “bullet2” then
event.other:removeSelf()
end
end

[import]uid: 68619 topic_id: 17037 reply_id: 66869[/import]

Don’t just use the collision listeners and remove the bullets like that. Setup the barriers along each side, and inside the:

 if (event.other.name == "bullet1") 

make sure you DON’T call removeSelf directly there. Instead, set a property of your bullet to true, and then inside your movement loop, check the value of the property and remove accordingly.

So inside your bullets loop, it would be something like this:

  
for i = #bulletsTable, 1, -1 do  
  
local myBullet = bulletsTable[i]  
  
if (myBullet.shouldBeAlive == true) then  
  
--code to move bullet  
  
else  
  
--destroy bullet here  
myBullet:removeSelf()  
myBullet = nil  
table.remove(bulletsTable,i)  
  
end  
  
end  
  

When spawning your bullet, give it a property called shouldBeAlive and set it to true. When it gets hit, just change it to false.

The above loop should then be called every frame as part of your game loop.

This way is much better, because if you call removeSelf() directly when the bullet gets hit, your program will still continue looping over the index that the bullet was located in (in the bulletsTable). By removing the bullet during the loop, we can clear out the exact location in the table that the bullet was occupying. [import]uid: 51654 topic_id: 17037 reply_id: 67058[/import]