Jump to content

  • Log In with Google      Sign In   
  • Create Account

FREE SOFTWARE GIVEAWAY

We have 4 x Pro Licences (valued at $59 each) for 2d modular animation software Spriter to give away in this Thursday's GDNet Direct email newsletter.


Read more in this forum topic or make sure you're signed up (from the right-hand sidebar on the homepage) and read Thursday's newsletter to get in the running!


Proper Touch Updating?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
1 reply to this topic

#1 blueshogun96   Crossbones+   -  Reputation: 1104

Like
0Likes
Like

Posted 13 March 2013 - 06:29 PM

There's a really annoying problem I'm having with my iOS multi-touch screen code. I've been trying to fix this for quite some time, and have absolutely no idea what the problem is, or even if it's my game's code or not. As soon as I fix this, I can finally release the app.

The problem is that if I hold a touch on one of the left or right virtual buttons, then even if I slide my finger out of the radius of that button, then it will still count as if it were being touched as long as that finger is still down. I can slide it all over the screen, and it will still move my character until I release my finger anywhere on the screen.

There's 3 parts to my multi-touch handling code. First, the actual interfacing with iOS/Cocoa touch:;>
 


-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
#if 0
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:touch.view];
    struct touch_t t;
    
    /* Add a touch to the screen */
    t.x = -(touchLocation.y-480);
    t.y = touchLocation.x;
    t.is_down = Yes;
    
    add_touch( &t );
#endif
    
    NSArray* touchArray = [touches allObjects];
    int count = touchArray.count;
    
    if( count > 1 )
    {
        int e = 0;
    }
    
    for( int i = 0; i < count; i++ )
    {
        UITouch* touch = [touchArray objectAtIndex:i];
        unsigned int touch_id = (unsigned int) touch;
        struct touch_t t;
        
        CGPoint touchLocation = [touch locationInView:touch.view];
        
        /* Add a touch to the screen */
        t.x = -(touchLocation.y-480);
        t.y = touchLocation.x;
        t.is_down = Yes;
        t.addr = touch_id;
        
        add_touch( &t );
    }
}
 
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    /*for (int i=0; i<count; i++)
     {
     UITouch* touch = [touchArray objectAtIndex:i];
     unsigned int touch_id = (unsigned int) touch; // convert address to unsigned int
     CGPoint p = [touch locationInView:self.view]; // location of this touch in the current view, which is accessed as self.view because this method is in the ViewController
     // now do something to the touch
     }*/
    
    NSArray* touchArray = [touches allObjects];
    int count = touchArray.count;
    
    for( int i = 0; i < count; i++ )
    {
        UITouch* touch = [touchArray objectAtIndex:i];
        unsigned int touch_id = (unsigned int) touch;
        
        CGPoint touchLocation = [touch locationInView:touch.view];
        
        /* Update this screen touch if it exists */
        struct touch_t t;
        t.x = -(touchLocation.y-480);
        t.y = touchLocation.x;
        t.is_down = Yes;
        t.addr = touch_id;
        
        update_touch( &t );
    }
}
 
-(void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
#if 0
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:touch.view];
    struct touch_t t;
    
    /* Add a touch to the screen */
    t.x = -(touchLocation.y-480);
    t.y = touchLocation.x;
    t.is_down = No;
    
    add_touch( &t );
#endif
    
    NSArray* touchArray = [touches allObjects];
    int count = touchArray.count;
//    struct touch_t t;
    
    for( int i = 0; i < count; i++ )
    {
        UITouch* touch = [touchArray objectAtIndex:i];
        unsigned int touch_id = (unsigned int) touch;
        
        remove_touch( touch_id );
    }
}

 

My C-based wrapper code:

 

 
struct touch_t touches[6];  /* Six touches should be enough */
int touch_count = 0;        /* Number of touches */
 
void add_touch( struct touch_t* tdata )
{
    /* Copy touch data to the next unused slot */
    int i = 0;
    
    //if( touch_count < 6 )
    while( i < 6 )
    {
        if( touches[i].addr == 0 )
        {
            memcpy( &touches[i], tdata, sizeof( struct touch_t ) );
            touch_count++;
            break;
        }
        
        i++;
    }
}
 
void update_touch( struct touch_t* tdata )
{
    int i = 0;
    
    while( i < 6 )
    {
        if( touches[i].addr == tdata->addr )
        {
            memcpy( &touches[i], tdata, sizeof( struct touch_t ) );
            break;
        }
        
        i++;
    }
}
 
void clear_touches()
{
    /* Clear all touch slots */
    memset( touches, 0, sizeof( struct touch_t ) * touch_count );
    touch_count = 0;
}
 
void remove_touch( unsigned int touch_addr )
{
    int i = 0;
    
    /* Search for a touch with a matching ID/address, and clear it. Also
       decrement the touch count by 1. */
    
    while( i < 6 )
    {
        if( touches[i].addr == touch_addr )
        {
            /* Mark this touch for removal */
            touches[i].is_down = No;
            
            //memset( &touches[i], 0, sizeof( struct touch_t ) );
            //touch_count--;
            break;
        }
        
        i++;
    }
}
 
void remove_old_touches()
{
    /* Copy over the touches that are still active */
//    clear_touches();
    
    int i = 0;
    
    while( i < 6 )
    {
        if( touches[i].is_down == No && touches[i].addr != 0 )
        {
            ZeroMemory( &touches[i], sizeof( struct touch_t) );
            touch_count--;
        }
        
        i++;
    }
}
 
int get_touch( struct touch_t* tdata )
{
/* Return information on all touch points and 
     return the number of touches. */
/* For OSes without touch screens, we just use
     the mouse. */
    
#ifdef _WIN32
/* Return mouse input and return 1 touch */
if( mouse.change )
{
tdata->is_down = !mouse.state;
tdata->x = mouse.x;
tdata->y = mouse.y;
        
return 1;
}
#endif
    
#ifdef __APPLE__
    if( touch_count != 0 )
    {
        /* Assume we have a valid array of touches and copy the
         whole thing over, then return the number of touches
         we've accumulated */
        
        ZeroMemory( tdata, sizeof( struct touch_t ) * 6 );
        memcpy( tdata, touches, sizeof( struct touch_t ) * touch_count );
        
        return touch_count;
    }
#endif
    
/* No touches */
return 0;
}

 

And finally, the game's code:

 

;>

/*
 * Ingame input functions 
 */

int ti_throw()
{
    struct touch_t t[6];
    int touches = get_touch(t);
    int i = 0;
    
    if( pause_button_touch )
        return 0;
    
    if( touches )
    {
        while( i < 6 )
        {
            if( t[i].is_down )
            {
                struct Vector2 v1 = throw_button.p; //{ 50.0f, 270.0f };
                struct Vector2 v2 = { t[i].x, t[i].y };
                //float d = distance2d( &v1, &v2 );
        
                //if( d <= throw_button.radius )
                    //return 1;
                
                if( t[i].x > 240 && t[i].x < 480 && t[i].y > 0 && t[i].y < 320 )
                {
                    return 1;
                }
            }
            
            i++;
        }
    }
    
    return 0;
}

int ti_left()
{
    struct touch_t t[6];
    int touches = get_touch(t);
    int i = 0;
    static int lb_down = No;
    
    if( touches )
    {
        while( i < 6 )
        {
            struct Vector2 v1 = left_button.p; //{ 400.0f, 280.0f };
            struct Vector2 v2 = { t[i].x, t[i].y };
            float d = distance2d( &v1, &v2 );
                
            if( d <= left_button.radius )
            {
                lb_down = t[i].is_down;
                break;
            }
            
            i++;
        }
    }
    else
        lb_down = No;
    
    return lb_down;
}

int ti_right()
{
    struct touch_t t[6];
    int touches = get_touch(t);
    int i = 0;
    static int rb_down = No;
    
    if( touches )
    {
        while( i < 6 )
        {
            struct Vector2 v1 = right_button.p;//{ 440.0f, 280.0f };
            struct Vector2 v2 = { t[i].x, t[i].y };
            float d = distance2d( &v1, &v2 );
                
            if( d <= right_button.radius )
            {
                rb_down = t[i].is_down;
                break;
            }
            
            i++;
        }
    }
    else
        rb_down = No;
    
    return rb_down;
}

 

 

So, somewhere in there is the problem. Been at this for almost a month. Any ideas? Thanks.

Shogun

 

EDIT: Reformatted the OP because I screwed it up.;>


Edited by blueshogun96, 13 March 2013 - 07:35 PM.

Follow Shogun3D on the official website: http://shogun3d.net

 

blogger.png twitter.png tumblr_32.png facebook.png

 

"Yo mama so fat, she can't be frustum culled." - yoshi_lol


Sponsor:

#2 freakchild   Members   -  Reputation: 557

Like
0Likes
Like

Posted 14 March 2013 - 09:09 AM

Try removing the static keyword from static int rb_down = No; and the equivalent in your lb function.

 

Looks to me like it gets the touches regardless of whether any are down or not, so 'if (touches)' is always true which prevents the alternative 'else rb_down = No' from executing.  If the touch is outside the radius the subsequent setting of rb_down to Yes is missed.  While that wouldn't matter (given it sets to Yes', the point is that nothing is setting it to anything in that circumstance...and thus it will remain as 'Yes' from when the touch was within radius.

 

The problem is that there is basically nothing that sets this to 'No' after the first initialization to that with the static keyword.  Once it goes to yes, it stays yes...unless you lift all fingers up, in which case your 'if( touch_count != 0 )' triggered ZeroMemory call does the work, or you lift the finger in question (triggering touchesEnded, which will also do it).


Edited by freakchild, 14 March 2013 - 09:28 AM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS