1

Using Cocos2D to create a shoot-em-up bullet hell style game. One finger drags to move the ship and there are fire layers in the corner.

From my main layer, I detect ccTouchesBegan, ccTouchesMoved and ccTouchesEnded. I pass a CGPoint into my logic controller.

If a touch down point is inside one of the 2 "fire button" layers, then I trigger a fire event. Otherwise I set a new location for the player ship. When a touch moves outside of the fire layer areas, I set a new location for the player ship.

Problem: Dragging a finger from within the fire layer into non-fire layer space causes the ship to jump to that point because of the "touch moves set player location" rule.

How can I architect this better?

Perhaps I need an array of "touch objects", and nullify them when crossing the boundary of the fire layer. I feel like I am missing some important concept about touch handling here that, if understood, would give the control I want without having to hack a "touch object" class that compares where you're tapping to an array of locations.

Please advise. Thanks!

(Yes, I saw: How do I limit touch handling to one layer when layers overlap? . That does not answer my question. The rectContainsPoint is how I determine if a touch is within or out of a fire layer).

Community
  • 1
  • 1
quantumpotato
  • 9,637
  • 14
  • 70
  • 146

1 Answers1

1

Can you set a flag (a BOOL ivar) in touchesBegan to indicate that the touch began in the fire area, and if this flag is set, dont move the ship? You would re-set it at touchesEnded.

That sounds too simple, so I'm probably missing something.

I was indeed. To handle multi touch you would need an array as you guess in the question - on touches began, if the touch was in the fire zone, add it to the array, then don't allow that touch to subsequently move the ship. Remove on touches ended. I don't see anything wrong or hacky about this, except for this note in the UITouch docs:

A UITouch object is persistent throughout a multi-touch sequence. You should never retain an UITouch object when handling an event. If you need to keep information about a touch from one phase to another, you should copy that information from the UITouch object.

But the persistence seems to support what you want to do. I don't know if a different class is used in cocos2d but the principle remains the same.

jrturton
  • 118,105
  • 32
  • 252
  • 268
  • I'm setting a BOOL iVar for touches *not* in the fire area, to prevent from touches began from warping if you tap a second time in the "move" area. Your solution does not work because I want the player to be able to move and fire simultaneously. If I mark an ivar from hitting fire and then my main movement finger moves, nothing would happen. (Thanks for the quick response) – quantumpotato Dec 17 '11 at 07:53
  • So what should happen when the player touches down in the fire area and drags out of it? Are you wanting that particular touch to be ignored whilst still allowing further touches to work to move the ship? (I did say I was missing something - that something was multi touch?) – jrturton Dec 17 '11 at 08:07
  • Yes - exactly! I asked a simpler version of this question here: http://stackoverflow.com/questions/8543473/ignoring-touchesmoved-for-subsequent-touches-while-counting-touchesbegan-total Actually.. it may be more difficult there since there aren't multiple layers. (I'll flag if there is a universal answer) – quantumpotato Dec 17 '11 at 15:49
  • I'm thinking there may be a way to not just "ignore" the touch (and maybe removing from an array and then if touchesMoved is not sufficiently close to a touch in the array, ignore it -- will work). Ignore in such a way that ccTouchesMoved never gets called on the movement layer if it began on the fire layer. Like on a UITableView: Dragging from the nav controller down to the table view then back up will not scroll the table view. – quantumpotato Dec 17 '11 at 15:53
  • Re-read your post - I was keeping a copy of the CGPoint from the touch instead of the touch. If I could add the *UITouch* to a local array that makes sense. But if I can't retain directly then it looks like I need an array. I'll experiment. – quantumpotato Dec 19 '11 at 15:24