is there something wrong with just calling the audio.play() each time I fire? I am not sure what the reason behind the loop is.
This is what I am using now (for sound) and it seems to work fine as best I can tell.
local function onTouch(event) local phase = event.phase local newLaser if phase == "began" then local function fireLaser() -- Play fire sound! audio.play( fireSound ) newLaser = display.newImageRect( mainGroup, objectSheet, 5, 14, 40 ) physics.addBody( newLaser, "dynamic", { isSensor=true } ) newLaser.isBullet = true newLaser.myName = "laser" newLaser.x = ship.x newLaser.y = ship.y newLaser:toBack() transition.to( newLaser, { y=-100, time=500, onComplete = function() display.remove( newLaser ) end } ) end bulletTimer = timer.performWithDelay(200, fireLaser, -1) --The 200 is the rate of fire, fastest posisble is 17 elseif phase == "ended" then if bulletTimer then timer.cancel(bulletTimer) end end end
This is purely a suggestion that I put together blind, but I hope it approximates what you’re trying to do.
ORIGINAL
-- -- ORIGINAL -- local function fireLaser() -- Play fire sound! audio.play( fireSound ) local newLaser = display.newImageRect( mainGroup, objectSheet, 5, 14, 40 ) physics.addBody( newLaser, "dynamic", { isSensor=true } ) newLaser.isBullet = true newLaser.myName = "laser" newLaser.x = ship.x newLaser.y = ship.y newLaser:toBack() transition.to( newLaser, { y=-40, time=500, onComplete = function() display.remove( newLaser ) end } ) end ship:addEventListener( "tap", fireLaser )
SUGGESTION
-- -- REPLACEMENT - Not Perfect; But should work OK... (may contain typos) -- -- NOTE: Assumes you already loaded the sound 'fireSound' local laserChannel = audio.findFreeChannel() -- Find a free channel to play sounds on audio.reserveChannels( laserChannel ) -- Lock it for use by laser sound ONLY. local firePeriod = 100 -- one shot every 100 ms ==\> 10 shot per second local lastTime = system.getTimer() local function fireLaser() audio.stop( laserChannel ) audio.play( fireSound, { channel = laserChannel } ) local newLaser = display.newImageRect( mainGroup, objectSheet, 5, 14, 40 ) physics.addBody( newLaser, "dynamic", { isSensor=true } ) newLaser.isBullet = true newLaser.myName = "laser" newLaser.x = ship.x newLaser.y = ship.y newLaser:toBack() transition.to( newLaser, { y=-40, time=500, onComplete = function() display.remove( newLaser ) end } ) end local function onEnterFrame( self ) if( ship.firing ) then local curTime = system.getTimer() local dt = lastTime - curTime if( dt \>= firePeriod ) then fireLaser() end end end local function onTouch( self, event ) local phase = event.phase local id = event.id if phase == "began" then display.getCurrentStage():setFocus( self, id ) self.isFocus = true self.firing = true elseif self.isFocus then if phase == "ended" then display.getCurrentStage():setFocus( self, nil ) self.isFocus = false self.firing = false audio.stop( laserChannel ) end end return false end ship.touch = onTouch ship.enterFrame = onEnterFrame ship:addEventListener( "touch" ) Runtime:addEventListner( "enterFrame", ship )
So the problem occurred because you made the newLaser var. local outside of the fireLaser function. Make inside of it. (Actually it was my mistake. But I edited the post later.)
As for the second question, I tend to create an invisible rectangle as big as I want my touch area to be and add your touch listener to the rectangle. There are a couple of things you need to do to make it work:
Rob, thanks for the help. The firelaser function was posted in the OP. I was trying what you recommended last night but I was using os.time but that onlY does seconds. Hopefully this method you linked can allow for shorter durations. Ill give it a try over the next couple nights
There are a couple of things. First, “newLaser” seems to be a global variable that you’re destroying when the transition completes. You never re-add the touch handler. This is why I recommend an invisible button as suggested above to have your touch handler. You should make newLaser local. In your transition’s onComplete event.target will be that specific laser blast that you can remove.
As far as the time for “t”, 16.6667 is probably the lowest for a 30fps app. Beyond that, your timer is firing faster than the screen is updating.
Alright, so I applied most of what saifuls.ctg89 recommended. I was able to control the speed by varying the bulletTimer (“t”). I didn’t do the invisible button yet, I will work on that next. The issue I am currently having is that after holding the “touch” for various times (between half second and 1 second typcially) it starts to cut my bullet travel distance (transition.to distance) to… like really small (maybe 1/4th of the screen". Any idea on why that is happening?
Lastly, I am wanting to keep the drag function as well, but use this newly defined BOX to control the travel of the ship. Currently, I have it so that when clicking in the box I can drag it, but if I stop touching and then retouch, it restarts my ship into the center of the screen (teleports it there if it isn’t already). Any ideas?
Below is my code.
--This is the code for my onTouch, which is triggered when touching the box. local function onTouch(event) local phase = event.phase local newLaser if phase == "began" then local function fireLaser() newLaser = display.newImageRect( mainGroup, objectSheet, 5, 14, 40 ) physics.addBody( newLaser, "dynamic", { isSensor=true } ) newLaser.isBullet = true newLaser.myName = "laser" newLaser.x = ship.x newLaser.y = ship.y newLaser:toBack() -- Play fire sound! audio.play( fireSound, {loops=-1} ) transition.to( newLaser, { y=-40, time=1000, onComplete = function() display.remove( newLaser ) end } ) end bulletTimer = timer.performWithDelay(200, fireLaser, -1) elseif phase == "ended" then timer.cancel(bulletTimer) end end
-- This is the info for the fireButton (or invisible rectangle) located in the function scene:create( event ) local fireButton = display.newRect(display.contentCenterX, display.actualContentHeight / 3 \* 2, display.actualContentWidth, display.actualContentHeight +100) fireButton.isVisible = false fireButton.isHitTestable = true fireButton:addEventListener( "touch", dragShip ) fireButton:addEventListener("touch", onTouch)
--This is the code I am currently using for dragShip local function dragShip( event ) local box = event.target local phase = event.phase if ( "began" == phase ) then -- Set touch focus on the ship display.currentStage:setFocus( box ) -- Store initial offset position ship.touchOffsetX = event.x - box.x elseif ( "moved" == phase ) then -- Move the ship to the new touch position ship.x = event.x - ship.touchOffsetX elseif ( "ended" == phase or "cancelled" == phase ) then -- Release touch focus on the ship display.currentStage:setFocus( nil ) end return true -- Prevents touch propagation to underlying objects end
--Lastly, this is how ship is defined (in the scene:create(event) section) ship = display.newImageRect( mainGroup, objectSheet, 4, 98, 79 ) ship.x = display.contentCenterX ship.y = display.contentHeight - 100 physics.addBody( ship, { radius=30, isSensor=true } ) ship.myName = "ship"
Thanks, that helped fix my movement issue. Any ideas on why my bullets start to fire full length and then after a half second/second, they begin only going about 1/4 of the screen?
--Fire button located in Scene:create( event ) local fireButton = display.newRect(display.contentCenterX, display.actualContentHeight / 3 \* 2, display.actualContentWidth, display.actualContentHeight + 100) fireButton:toFront() fireButton.isVisible = false fireButton.isHitTestable = true
--This function fires the bullet local function onTouch(event) local phase = event.phase local newLaser if phase == "began" then local function fireLaser() newLaser = display.newImageRect( mainGroup, objectSheet, 5, 14, 40 ) physics.addBody( newLaser, "dynamic", { isSensor=true } ) newLaser.isBullet = true newLaser.myName = "laser" newLaser.x = ship.x newLaser.y = ship.y newLaser:toBack() -- Play fire sound! audio.play( fireSound, {loops=1} ) transition.to( newLaser, { y=-40, time=1000, onComplete = function() display.remove( newLaser ) end } ) end bulletTimer = timer.performWithDelay(200, fireLaser, -1) --The 200 is the rate of fire, fastest posisble is 17 elseif phase == "ended" then timer.cancel(bulletTimer) end end
AHHHH, this creates unending sound audio again. The last one you posted did the same so I had to edit it. currently the one I use does 2 sounds for some reason, but it doesn’t make super loud unending audio. thoughts?