0

I need help. I make game for blackberry playbook, but i have trouble with multitouch event handling. I use CInput class taken from examples for handling touch events, it work(all touch have right coords and touch count right too) but when make 2 touch and release touch in same time CInput not release 1 events and all going wrong like i not release touch. I can see this bug in simulator or on playbook. this part code for work with touch. How i can fix it? thanks if someone can help. sorry for bad english

void touchUpdate()
{
    g_Input.Update();
    printf("count %d\n", g_Input.getTouchCount());
    if (g_Input.getTouchCount() != 0)
    {
        CTouch* touch;
        if (g_Input.isMultiTouch())
        {
            for (int i = 0; i < g_Input.getTouchCount(); i++)
            {
                touch = g_Input.getTouch(i);
                if (touch != NULL)
                {
                    if (!touch->active)
                    {
                        touch->x = -1;
                        touch->y = -1;
                        continue;
                    }
                    else if (checkButton(&btnAction, touch))
                    {
                        if (menu->isGameEnabled())
                        {
                            currentGame->eventAction();
                        }
                        else
                        {
                            currentGame = menu->eventAction();
                        }
                        continue;
                    }
                    else if (checkButton(&btnUp, touch))
                    {
                        if (menu->isGameEnabled())
                        {
                            currentGame->eventUp();
                        }
                        else
                        {
                            menu->eventUp();
                        }
                        continue;
                    }
                    else if (checkButton(&btnDown, touch))
                    {
                        if (menu->isGameEnabled())
                        {
                            currentGame->eventDown();
                        }
                        else
                        {
                            menu->eventDown();
                        }
                        continue;
                    }
                    else if (checkButton(&btnLeft, touch))
                    {
                        if (menu->isGameEnabled())
                        {
                            currentGame->eventLeft();
                        }
                        else
                        {
                            menu->eventLeft();
                        }
                        continue;
                    }
                    else if (checkButton(&btnRight, touch))
                    {
                        if (menu->isGameEnabled())
                        {
                            currentGame->eventRight();
                        }
                        else
                        {
                            menu->eventRight();
                        }
                        continue;
                    }
                    else if (checkButton(&btnPause, touch))
                    {
                        if (menu->isGameEnabled())
                        {
                            currentGame->eventPause();
                        }
                        continue;
                    }
                    else if (checkButton(&btnSound, touch))
                    {
                        //  off/on sound
                        continue;
                    }
                    else if (checkButton(&btnMenu, touch))
                    {
                        //  force drop to menu
                        if (menu->isGameEnabled())
                        {
                            currentGame->eventMenu();
                        }
                        continue;
                    }
                }
            }
        }
    }
}

currentGame->eventMenu(), currentGame->eventUp(), etc... it just functions in game logic or main menu. this functions must call always when button pressed.

struct roundButton
{
    int  x, y;
    int  radius;
    bool pressed;
};

bool checkButton(roundButton *button, CTouch *touch)
{
    if ((button->x - touch->x) * (button->x - touch->x) + (button->y - touch->y) * (button->y - touch->y) <= button->radius * button->radius)
    {
        button->pressed = true;
        return true;
    }
    return false;
}

this is how i check my buttons pressed or not

#ifndef SRC_INPUT_H_
#define SRC_INPUT_H_

#include "IwGeom.h"
#include "s3ePointer.h"

#define MAX_TOUCHES 2

struct CTouch
{
public:
    int  x, y;
    bool active;
    int  id;
};

class CInput
{
private:
    bool        Available;                                          // true if a pointer is present
    bool        IsMultiTouch;                                       // true if multitouch is enabled
    CTouch      Touches[MAX_TOUCHES];                               // List of potential touches
public:
    bool        isAvailable() const { return Available; }           // Returns availability of the pointer
    bool        isMultiTouch() const { return IsMultiTouch; }       // Returns multitouch capability
    CTouch*     getTouchByID(int id);                               // returns the touch identified by its id
    CTouch*     getTouch(int index) { return &Touches[index]; }     // Gets a specific touch
    CTouch*     findTouch(int id);                                  // Finds a specific touch by its id
    int         getTouchCount() const;                              // Get number of touches this frame
public:
    bool        Init();                                             // Initialises the input system (returns true if pointer is supported)
    void        Release();                                          // Releases data used by the input system
    void        Update();                                           // Updates the input system, called every frame
};

extern CInput g_Input;

#endif  // SRC_INPUT_H_

CInput class

#include "input.h"

CInput g_Input;

void HandleMultiTouchButtonCB(s3ePointerTouchEvent* event)
{
    CTouch* touch = g_Input.findTouch(event->m_TouchID);
    if (touch != NULL)
    {
        touch->active = event->m_Pressed != 0;
        touch->x = event->m_x;
        touch->y = event->m_y;
    }
}

void HandleMultiTouchMotionCB(s3ePointerTouchMotionEvent* event)
{
    CTouch* touch = g_Input.findTouch(event->m_TouchID);
    if (touch != NULL)
    {
        touch->x = event->m_x;
        touch->y = event->m_y;
    }
}

void HandleSingleTouchButtonCB(s3ePointerEvent* event)
{
    CTouch* touch = g_Input.getTouch(0);
    touch->active = event->m_Pressed != 0;
    touch->x = event->m_x;
    touch->y = event->m_y;
}

void HandleSingleTouchMotionCB(s3ePointerMotionEvent* event)
{
    CTouch* touch = g_Input.getTouch(0);
    touch->x = event->m_x;
    touch->y = event->m_y;
}

CTouch* CInput::findTouch(int id)
{
    if (!Available)
        return NULL;

    for (int t = 0; t < MAX_TOUCHES; t++)
    {
        if (Touches[t].id == id)
            return &Touches[t];
        if (!Touches[t].active)
        {
            Touches[t].id = id;
            return &Touches[t];
        }
    }

    return NULL;
}

CTouch* CInput::getTouchByID(int id)
{
    for (int t = 0; t < MAX_TOUCHES; t++)
    {
        if (Touches[t].active && Touches[t].id == id)
            return &Touches[t];
    }

    return NULL;
}

int CInput::getTouchCount() const
{
    if (!Available)
        return 0;

    int count = 0;
    for (int t = 0; t < MAX_TOUCHES; t++)
    {
        if (Touches[t].active)
            count++;
    }

    return count;
}

bool CInput::Init()
{
    Available = s3ePointerGetInt(S3E_POINTER_AVAILABLE) ? true : false;
    if (!Available)
        return false;

    for (int t = 0; t < MAX_TOUCHES; t++)
    {
        Touches[t].active = false;
        Touches[t].id = 0;
    }
    IsMultiTouch = s3ePointerGetInt(S3E_POINTER_MULTI_TOUCH_AVAILABLE) ? true : false;
    if (IsMultiTouch)
    {
        s3ePointerRegister(S3E_POINTER_TOUCH_EVENT, (s3eCallback)HandleMultiTouchButtonCB, NULL);
        s3ePointerRegister(S3E_POINTER_TOUCH_MOTION_EVENT, (s3eCallback)HandleMultiTouchMotionCB, NULL);
    }
    else
    {
        s3ePointerRegister(S3E_POINTER_BUTTON_EVENT, (s3eCallback)HandleSingleTouchButtonCB, NULL);
        s3ePointerRegister(S3E_POINTER_MOTION_EVENT, (s3eCallback)HandleSingleTouchMotionCB, NULL);
    }
    return true;
}

void CInput::Release()
{
    if (Available)
    {
        if (IsMultiTouch)
        {
            s3ePointerUnRegister(S3E_POINTER_TOUCH_EVENT, (s3eCallback)HandleMultiTouchButtonCB);
            s3ePointerUnRegister(S3E_POINTER_TOUCH_MOTION_EVENT, (s3eCallback)HandleMultiTouchMotionCB);
        }
        else
        {
            s3ePointerUnRegister(S3E_POINTER_BUTTON_EVENT, (s3eCallback)HandleSingleTouchButtonCB);
            s3ePointerUnRegister(S3E_POINTER_MOTION_EVENT, (s3eCallback)HandleSingleTouchMotionCB);
        }
    }
}

void CInput::Update()
{
    if (Available)
        s3ePointerUpdate();
}
art65536
  • 1
  • 2
  • I don't think it's a playbook bug. I've used multitouch in playbook using marmalade already. Try to check on any other device (Android probably). – 0xC0DED00D Mar 19 '13 at 15:29
  • this can happen even in emulator. just harder reproduce this bug – art65536 Mar 19 '13 at 16:50
  • That means there's some problem with the code. Let me have a look. – 0xC0DED00D Mar 19 '13 at 18:16
  • The problem seems to be with the touch local variable. You're using the same variable to loop through all of the touches. Try to define it in the loop. Also you didn't mention what your checkbutton() and eventUP() etc. method does. Add comments near the statements to explain, so that someone can help. – 0xC0DED00D Mar 19 '13 at 18:20
  • Thanks for your reply. I lost hope that someone will reply. my variable for touches defined in class CInput. This class i find in official examples, it work but when lot touch and touch release in same time, i got ghost(unreleased) touches. And my buttons stuck. – art65536 Mar 19 '13 at 20:49

1 Answers1

0

I find the bug. Function findTouch can return even not active touches. So fix looks like

CTouch* CInput::findTouch(int id)
{
    if (!Available)
        return NULL;

    for (int t = 0; t < MAX_TOUCHES; t++)
    {
        if (Touches[t].id == id)
        return &Touches[t];
    }
    for (int t = 0; t < MAX_TOUCHES; t++)
    {
        if (!Touches[t].active)
        {
            Touches[t].id = id;
            return &Touches[t];
        }
    }

     return NULL;
}
art65536
  • 1
  • 2