Whats the best way to have an Image onTouch perform an event or function?

I’m trying to add a simple Dpad style controller in my game. I have images for each button and want to add a function to move an object on the x and y axis on touch. What would be the best way to go about this. I’ve tried a few things and failed… Would a widget button be best or what?
I have this code below first that works when I touch the button… But if I try to use applyForce then I get an error. I’ll post the code and error below…

Error: (/Users/mkjt88/Library/Application Support/Corona Simulator/Scroller-0925D93CFA3CB11CBDED963F819C3755)
2013-01-29 17:00:41.591 Corona Simulator[21435:707] Runtime error
…ations/CoronaSDK/SampleCode/mkjt88/Scroller/test.lua:217: attempt to call method ‘applyForce’ (a nil value)
stack traceback:
[C]: in function ‘applyForce’
…ations/CoronaSDK/SampleCode/mkjt88/Scroller/test.lua:217: in function <…ations>
?: in function <?:229>

[lua]function btnUp:touch(event)
if event.phase == “began” then
iRocket.x = iRocket.x + 5
end
return true
end
btnUp:addEventListener(“touch”, btnUp)

function btnUp:touch(event)
if event.phase == “began” then
iRocket:applyForce(0, -15, iRocket.x, iRocket.y)
end
return true
end
btnUp:addEventListener(“touch”, btnUp)
[import]uid: 20272 topic_id: 35441 reply_id: 335441[/import] </…ations>

Keep in mind that touch events don’t continuously generate events. You have to combine the touch event with a Runtime “enterFrame” listener. Basically on the “began” phase of your touch event, you set a flag indicating the button is pressed. Then use the enterFrame function to say “If button is pressed then move the object”. When the player releases the touch and you get the “ended” phase, you unset the flag so that the movement stops.

As far as the applyForce() goes, the main reason why you would get that error is if your object is not a physics body. [import]uid: 199310 topic_id: 35441 reply_id: 140828[/import]

Ok I have this so far and my down will work but nothing with the up… No errors but no movements with up

[lua]function btnUp(event)
if event.phase == “began” then
iRocket.enterFrame = moveRocket
Runtime:addEventListener(“enterFrame”, iRocket)
end
end

function btnDown:touch(event)
if event.phase == “began” then
iRocket.y = iRocket.y + 15
end
end
btnDown:addEventListener(“touch”, btnDown)

function moveRocket(self,event)
self:applyForce(0, -15, self.x, self.y)
end [import]uid: 20272 topic_id: 35441 reply_id: 140831[/import]

Only if I make my iRocket “dynamic” then will this work but it only moves it 15px once…not constant. How come it don’t move 15px per frame instead of just once? Also If i change my body type back to static on event.phase == “ended” then it don’t move at all… Any ideas why?

[lua]iRocket = display.newImage (“rocket.png”)
physics.addBody(iRocket, “static”, {})

function btnUp:touch(event)
if event.phase == “began” then
iRocket.bodyType = “dynamic”
iRocket.enterFrame = moveRocket
Runtime:addEventListener(“enterFrame”, iRocket)
end
end
btnUp:addEventListener(“touch”, btnUp)

function moveRocket(self,event)
print(“Works”)
self:applyForce(0, -15, self.x, self.y)

if event.phase == “ended” or “canceled” then

Runtime:removeEventListener(“enterFrame”, iRocket)
end
end
I also tried this below and same results…

function moveRocket(event)
print(“Works”)
iRocket:applyForce(0, -15, iRocket.x, iRocket.y)

if event.phase == “ended” or “canceled” then

Runtime:removeEventListener(“enterFrame”, iRocket)
end
end [import]uid: 20272 topic_id: 35441 reply_id: 140840[/import]

iRocket = display.newImage ("rocket.png")  
physics.addBody(iRocket, "static", {})   
   
function btnUp:touch(event)  
 if event.phase == "began" then  
 iRocket.bodyType = "dynamic"  
 btnUp.isPressed = true  
 elseif event.phase == "ended" then  
 iRocket.bodyType = "static"  
 btnUp.isPressed = false  
 end  
end  
btnUp:addEventListener("touch", btnUp)  
  
function btnDown:touch(event)  
 if event.phase == "began" then  
 iRocket.bodyType = "dynamic"  
 btnDown.isPressed = true  
 elseif event.phase == "ended" then  
 iRocket.bodyType = "static"  
 btnDown.isPressed = false  
 end  
end  
btnUp:addEventListener("touch", btnUp)  
  
  
function moveRocket(event)  
 print("Works")  
 if btnUp.isPresssed then  
 iRocket:applyForce(0, -15, iRocket.x, iRocket.y)  
 elseif btnDown.isPressed then  
 iRocket:applyForce(0, 15, iRocket.x, iRocket.y)  
 end  
end  
  
Runtime:addEventListener("enterFrame", moveRocket)  

Or something like that. Your other way would probably work, but you never programmed a down button.
[import]uid: 199310 topic_id: 35441 reply_id: 140844[/import]

I don’t know why I’m having such trouble with this… If i use that code and just make the change to the btnDown event listener instead of btnUp again like this then it works… But both buttons send the rocket down on the Y axis… And the down button sends it down twice as fast for some reason…

[lua]function btnUp:touch(event)
if event.phase == “began” then
iRocket.bodyType = “dynamic”
btnUp.isPressed = true
elseif event.phase == “ended” then
iRocket.bodyType = “static”
btnUp.isPressed = false
end
end
btnUp:addEventListener(“touch”, btnUp)

function btnDown:touch(event)
if event.phase == “began” then
iRocket.bodyType = “dynamic”
btnDown.isPressed = true
elseif event.phase == “ended” then
iRocket.bodyType = “static”
btnDown.isPressed = false
end
end
btnDown:addEventListener(“touch”, btnDown)

function moveRocket(event)
– print(“Works”)
if btnUp.isPresssed then
iRocket:applyForce(0, -15, iRocket.x, iRocket.y)
elseif btnDown.isPressed then
iRocket:applyForce(0, 15, iRocket.x, iRocket.y)
end
end

Runtime:addEventListener(“enterFrame”, moveRocket) [import]uid: 20272 topic_id: 35441 reply_id: 140853[/import]

That is physics for you. Without any force, once you make the body dynamic, gravity is going to kick in and it’s going to fall at 9.8 meters per second per second (unless you’ve changed gravity). If you add more down force its going to fall on its own.

You might need to apply more force in the upward direction to compensate for the gravity. This is getting out of my field of expertise

When you release the button it sets back to static so gravity won’t continue to pull down on the object. [import]uid: 199310 topic_id: 35441 reply_id: 140856[/import]

I think your error is on line 26. You typed “isPresssed” with 3 "s"s. So, your button press turns the body into dynamic, but then you don’t get any upward force because you spelled the property wrong.

On another note, if you want this rocket to be immune to gravity, you can either turn off all gravity, or turn it off on just the rocket, if you want other objects affected by core gravity but not the rocket.

Brent [import]uid: 200026 topic_id: 35441 reply_id: 140866[/import]

Nice eye Brent that did fix it. I guess I didn’t specify at first and this works just like it should I guess but it isn’t exactly what I needed. I’ll restate what I need and then maybe I can get further help… I want the D-pad only to function when clicked and over a specific button but i also want it to stop the button press if I move my touch away from the button… Also if i start with up and move my finger to the down button I want the up to stop and down to take over… Right now I have to let off the up button and re-click on the down button for it to take place otherwise the up will still be functioning if i click up and move my finger to the down button… any suggestions on this? [import]uid: 20272 topic_id: 35441 reply_id: 140888[/import]

I actually have been thinking and was wondering if this approach is to bulky for what it’s worth… Would it be easier for me to just make a touch event anywhere on the screen and make my rocket coordinates follow that? I wouldn’t want it to just go directly to those coordinates but follow them at a set speed. I figured I’d have my phone landscape, x axis starting at left side and have touches accessed from about 0, 200px on the X axis. Anywhere I touch from 0 - 200px X then My rocket would follow that touch + 50px so it will be in front of your finger not under it. Is this about as easy as it sounds? If so would I need a enterFrame Runtime event for the whole screen or how would I go about that. Sorry for all the questions no rush to answer just when you can… I would just be lost without you guys :slight_smile:
EDIT: I have something basic like this for now that just makes the rocket follow the touch. I guess now I need guidance on what to do to make the rocket follow the path in a straight line to the touch or track and follow the touch instead of disappear and reappear at the new coordinates. The drag and follow part works fine.

[lua]function onScreenTouch (event)

if event.x <= 150 then
if rocket.x ~= event.x then
rocket.x = event.x
end

if rocket.y ~= event.y then
rocket.y = event.y
end
end

end
Runtime:addEventListener (“touch”, onScreenTouch)[/lua]
I failed on the transition trying something like this… When i touch the rocket just goes straight to 0,0 and doesn’t move…

[lua]function onScreenTouch (event)

if event.x <= 100 then
if rocket.x ~= event.x then
rocket.x = transition.to(event.x, {time = 500})
end

if rocket.y ~= event.y then
rocket.y = transition.to(event.y, {time = 500})
end
end

end
Runtime:addEventListener (“touch”, onScreenTouch)[/lua] [import]uid: 20272 topic_id: 35441 reply_id: 140891[/import]

Hi @mkjt88,
Since you’re using physics, I’d suggest you track the touch as it moves around the screen, calculating the angle between the rocket and the touch. Then, apply the necessary linear velocity behind the rocket going toward the touch. Don’t use impulses, as each move of the finger will affect the direction of the rocket, and thus you want a “constant” physical movement like linear velocity, not an additive one.

Brent [import]uid: 200026 topic_id: 35441 reply_id: 140999[/import]

Thanks Brent… I understand the logic behind it but I’m not quite so familiar with doing more than very basic maths in programming… Are there any guides, quick tips, or algorithms out there that can get me started on how to do those calculations? [import]uid: 20272 topic_id: 35441 reply_id: 141057[/import]

Keep in mind that touch events don’t continuously generate events. You have to combine the touch event with a Runtime “enterFrame” listener. Basically on the “began” phase of your touch event, you set a flag indicating the button is pressed. Then use the enterFrame function to say “If button is pressed then move the object”. When the player releases the touch and you get the “ended” phase, you unset the flag so that the movement stops.

As far as the applyForce() goes, the main reason why you would get that error is if your object is not a physics body. [import]uid: 199310 topic_id: 35441 reply_id: 140828[/import]

Ok I have this so far and my down will work but nothing with the up… No errors but no movements with up

[lua]function btnUp(event)
if event.phase == “began” then
iRocket.enterFrame = moveRocket
Runtime:addEventListener(“enterFrame”, iRocket)
end
end

function btnDown:touch(event)
if event.phase == “began” then
iRocket.y = iRocket.y + 15
end
end
btnDown:addEventListener(“touch”, btnDown)

function moveRocket(self,event)
self:applyForce(0, -15, self.x, self.y)
end [import]uid: 20272 topic_id: 35441 reply_id: 140831[/import]

Only if I make my iRocket “dynamic” then will this work but it only moves it 15px once…not constant. How come it don’t move 15px per frame instead of just once? Also If i change my body type back to static on event.phase == “ended” then it don’t move at all… Any ideas why?

[lua]iRocket = display.newImage (“rocket.png”)
physics.addBody(iRocket, “static”, {})

function btnUp:touch(event)
if event.phase == “began” then
iRocket.bodyType = “dynamic”
iRocket.enterFrame = moveRocket
Runtime:addEventListener(“enterFrame”, iRocket)
end
end
btnUp:addEventListener(“touch”, btnUp)

function moveRocket(self,event)
print(“Works”)
self:applyForce(0, -15, self.x, self.y)

if event.phase == “ended” or “canceled” then

Runtime:removeEventListener(“enterFrame”, iRocket)
end
end
I also tried this below and same results…

function moveRocket(event)
print(“Works”)
iRocket:applyForce(0, -15, iRocket.x, iRocket.y)

if event.phase == “ended” or “canceled” then

Runtime:removeEventListener(“enterFrame”, iRocket)
end
end [import]uid: 20272 topic_id: 35441 reply_id: 140840[/import]

iRocket = display.newImage ("rocket.png")  
physics.addBody(iRocket, "static", {})   
   
function btnUp:touch(event)  
 if event.phase == "began" then  
 iRocket.bodyType = "dynamic"  
 btnUp.isPressed = true  
 elseif event.phase == "ended" then  
 iRocket.bodyType = "static"  
 btnUp.isPressed = false  
 end  
end  
btnUp:addEventListener("touch", btnUp)  
  
function btnDown:touch(event)  
 if event.phase == "began" then  
 iRocket.bodyType = "dynamic"  
 btnDown.isPressed = true  
 elseif event.phase == "ended" then  
 iRocket.bodyType = "static"  
 btnDown.isPressed = false  
 end  
end  
btnUp:addEventListener("touch", btnUp)  
  
  
function moveRocket(event)  
 print("Works")  
 if btnUp.isPresssed then  
 iRocket:applyForce(0, -15, iRocket.x, iRocket.y)  
 elseif btnDown.isPressed then  
 iRocket:applyForce(0, 15, iRocket.x, iRocket.y)  
 end  
end  
  
Runtime:addEventListener("enterFrame", moveRocket)  

Or something like that. Your other way would probably work, but you never programmed a down button.
[import]uid: 199310 topic_id: 35441 reply_id: 140844[/import]

I don’t know why I’m having such trouble with this… If i use that code and just make the change to the btnDown event listener instead of btnUp again like this then it works… But both buttons send the rocket down on the Y axis… And the down button sends it down twice as fast for some reason…

[lua]function btnUp:touch(event)
if event.phase == “began” then
iRocket.bodyType = “dynamic”
btnUp.isPressed = true
elseif event.phase == “ended” then
iRocket.bodyType = “static”
btnUp.isPressed = false
end
end
btnUp:addEventListener(“touch”, btnUp)

function btnDown:touch(event)
if event.phase == “began” then
iRocket.bodyType = “dynamic”
btnDown.isPressed = true
elseif event.phase == “ended” then
iRocket.bodyType = “static”
btnDown.isPressed = false
end
end
btnDown:addEventListener(“touch”, btnDown)

function moveRocket(event)
– print(“Works”)
if btnUp.isPresssed then
iRocket:applyForce(0, -15, iRocket.x, iRocket.y)
elseif btnDown.isPressed then
iRocket:applyForce(0, 15, iRocket.x, iRocket.y)
end
end

Runtime:addEventListener(“enterFrame”, moveRocket) [import]uid: 20272 topic_id: 35441 reply_id: 140853[/import]

That is physics for you. Without any force, once you make the body dynamic, gravity is going to kick in and it’s going to fall at 9.8 meters per second per second (unless you’ve changed gravity). If you add more down force its going to fall on its own.

You might need to apply more force in the upward direction to compensate for the gravity. This is getting out of my field of expertise

When you release the button it sets back to static so gravity won’t continue to pull down on the object. [import]uid: 199310 topic_id: 35441 reply_id: 140856[/import]

I think your error is on line 26. You typed “isPresssed” with 3 "s"s. So, your button press turns the body into dynamic, but then you don’t get any upward force because you spelled the property wrong.

On another note, if you want this rocket to be immune to gravity, you can either turn off all gravity, or turn it off on just the rocket, if you want other objects affected by core gravity but not the rocket.

Brent [import]uid: 200026 topic_id: 35441 reply_id: 140866[/import]

Nice eye Brent that did fix it. I guess I didn’t specify at first and this works just like it should I guess but it isn’t exactly what I needed. I’ll restate what I need and then maybe I can get further help… I want the D-pad only to function when clicked and over a specific button but i also want it to stop the button press if I move my touch away from the button… Also if i start with up and move my finger to the down button I want the up to stop and down to take over… Right now I have to let off the up button and re-click on the down button for it to take place otherwise the up will still be functioning if i click up and move my finger to the down button… any suggestions on this? [import]uid: 20272 topic_id: 35441 reply_id: 140888[/import]