【问题标题】:Marmalade SDK MultitouchMarmalade SDK 多点触控
【发布时间】:2013-03-18 13:33:00
【问题描述】:

我需要帮助。我为黑莓剧本制作游戏,但我在多点触控事件处理方面遇到了麻烦。我使用从示例中提取的 CInput 类来处理触摸事件,它可以工作(所有触摸都具有正确的坐标和触摸计数)但是当同时进行 2 次触摸和释放触摸时,CInput 不释放 1 事件并且所有错误都像我不释放一样触碰。我可以在模拟器或剧本中看到这个错误。这部分代码用于触摸工作。我该如何解决?感谢有人可以提供帮助。抱歉英语不好

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() 等等……它只是在游戏逻辑或主菜单中起作用。此函数必须在按下按钮时始终调用。

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;
}

这就是我检查按钮是否按下的方式

#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 类

#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();
}

【问题讨论】:

  • 我认为这不是剧本错误。我已经在使用果酱的剧本中使用了多点触控。尝试检查任何其他设备(可能是 Android)。
  • 即使在模拟器中也可能发生这种情况。只是更难重现这个错误
  • 这意味着代码有问题。让我看看。
  • 问题似乎出在 touch 局部变量上。您正在使用相同的变量来循环所有的触摸。尝试在循环中定义它。您也没有提到您的 checkbutton() 和 eventUP() 等方法的作用。在语句附近添加 cmets 进行解释,以便有人可以提供帮助。
  • 感谢您的回复。我失去了希望有人会回复。我在 CInput 类中定义的触摸变量。我在官方示例中找到了这个类,它可以工作,但是当大量触摸和触摸同时释放时,我得到了幽灵(未释放)的触摸。我的按钮卡住了。

标签: c++ multi-touch marmalade


【解决方案1】:

我找到了错误。函数 findTouch 甚至可以返回非活动触摸。所以修复看起来像

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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多