Advice on coding of On-Screen Controls ( Joystick and multiple buttons)

Posts: 48
Joined: 2009.05
Post: #1

I'm finally getting somewhere now! Wink

I'd just like to know if there are any good tutorials or advice or even code snippets on how best to handle on screen controls and multiple buttons presses / releases.

The way I've implemented it, is that I've abstracted out of the EAGLView the touch events and they are being passed down a chain to an object that is just concerned with making 'sense' of them.

I have the requirement for a joystick (say, D-Pad) on the left of the screen and three buttons on the right.

The three buttons can be pressed down at the same time as one or more of the D-Pad buttons, however, no more than one of the buttons on the right can be down at the same time.

Also, no more that 2 of the D-Pad buttons can be down at the same time, and as ofcourse, with a D-Pad I must expect the user to drag/move their finger from one part of the buttons to another and transition accurately between these 'states'

At the moment I've got the 'touchesBegan:touches blah blah' event passing the entire NSSet * of touches down to my delegate, so I can get the 'full' list of touch events.

But how do I seperate them out and make sense of it all?

My first attempt, was just to get the current position of the touch and make a basic ( if touch.x > button1.x and touch.x < button1.x + button1.width) blah
blah blah for all the buttons,

but I scrapped that because it can't handle all the 'semantics' of what I need.

Can anyone please advise?

Thanks so much.

Quote this message in a reply
Posts: 48
Joined: 2009.05
Post: #2

Quote this message in a reply
Posts: 1,563
Joined: 2003.10
Post: #3
I'd approach it like this:
  • When a new touch begins, do rough partitioning to determine whether it's in the d-pad area, the button area, or elsewhere (probably with a simple 2D squared distance test).
  • If in d-pad area:
    • If there's already d-pad touch being tracked, ignore it.
    • If not, partition the d-pad into 8 equal wedge-shaped regions and determine which one the touch is in, where the regions mean "left", "left-down", "down", etc. Compute this again each time this touch moves.
  • If in the button area:
    • Determine which button was pressed with some sort of partitioning that makes sense for your button layout. It's possible you'll want larger hit areas than the buttons themselves, but I'd have to play with it to know for sure.
    • Regardless of where this touch moves, the button is "down" while the touch is held, and "up" once it's released.
Quote this message in a reply
Posts: 48
Joined: 2009.05
Post: #4
Sorry Thems...

That doesn't help.

Knowing if the touch happened in an area is not the problem.

The problem is with the standard event handlers as I mentioned and handling the 'multi touch ' and a touch MOVED / END on the D-PAD at the same time another touch Down/Up is happening on a button.

THAT'S the hard part -and one I can't find any help on.
Quote this message in a reply
Posts: 268
Joined: 2005.04
Post: #5
Something like this?

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    NSEnumerator        *enumerator;
    UITouch            *touch;
    CGPoint            location;

    enumerator = [touches objectEnumerator];
    while (touch = [enumerator nextObject])
        location = [touch locationInView:self];
        if (location is inside of button rect)
            // Set button down/activated/whatever
        else if... // yadda yadda yadda

touchesMoved:withEvent: is basically the same and touchesEnded:withEvent is the same, but in reverse (buttons deactivating, etc). You can test against the touch's previous location with...

CGPoint        oldLocation = [touch previousLocationInView:self];

... to see if a touch has left a button's rect without being released.
Quote this message in a reply
Posts: 48
Joined: 2009.05
Post: #6
Bachus Wrote:Something like this?

Yeah, kinda. Thanks Bachus.

That's kinda what I've already got, except I'm using the '
for ( UITouch * touch in touches)
     CGPoint point = [touch locationInView:receivingView];
         [self callTestMethod:point];
way of doing things..

The problem I'm having - and have had all this time is with the 'touchesMoved' method.


If I move my finger over the D-Pad, I want to track the movement and operate upto 2 adjacent sectors, i.e. Left and Up.. okay?

BUT if I move my finger from say the 'up' position, and move it OFF of the on-screen D-Pad, then I need to 'release' the D-Pad.

Same goes for the 3 buttons on the right hand side. If I press them, and then move / drag my finger up and off of them, but still in contact with the screen, they 'stay pressed' and not released.

This is my big mental block.

Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Suggestions for controls in a tank driving game iamflimflam1 0 2,801 Oct 7, 2010 03:33 AM
Last Post: iamflimflam1
  Game buttons Miglu 7 6,727 Sep 25, 2010 01:42 PM
Last Post: AnotherJake
  Coding A Card Game Jerm #1 3 7,043 Apr 11, 2010 03:05 PM
Last Post: TimMcD
  How to support gamepad/joystick OptimisticMonkey 6 6,418 Dec 4, 2009 11:51 AM
Last Post: AnotherJake
  Coding efficiently (pygame) perks 10 7,905 Sep 11, 2007 08:09 AM
Last Post: Blacktiger