I am fiddling around with the tutorial game (star explorer) and wanted to change the method of firing. Currently it uses the below method :
addEventListener("tap", fireLaser)
but I want to use the touch method so that I may tap and hold it. While holding I want it to continue to fire. I simply changed the above to:
ship:addEventListener( "touch", fireLaser )
I have 2 problems, and if they could be answered seperately to help me determine what is happening that would be great.
Problem 1. When using the touch method, it is firing extremely rapidly. I would love the ability to adjust the rate at which it fires while being held. Any ideas?
Problem 2. How do I get it to have the addEventListener to the ship and anything else on the screen (except future buttons). Meaning, how can I click and hold in the middle of the screen and it work instead of having to click specifically on the ship.
The above event listener is located in my scebe:Create right now according to the tutorial.
Below is the text that runs when it runs the function firelaser incase you need it.
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
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?
This set of code is causing the issue… specifically, the onComplete section. If I comment out that line, it works great (except it never removes the lasers).
I think this has something to do with once other lasers make it to that -40 or (Completion point) , it is deleting all of the lasers and continues to do so until released. Since I am using a touch event instead of tap this seems to be causing an issue.
So, to fix this… do I need to make a table and keep track of these lasers some how and delete them in a timeloop or something?