【问题标题】:SDL C++ Mouse Input Handling Toggle EffectSDL C++ 鼠标输入处理切换效果
【发布时间】:2017-08-04 21:33:55
【问题描述】:

所以我正在开发一款塔防游戏。我需要选择一个用户单击鼠标的图块(现在我只是在图块周围画一个边框)。现在我的代码有时可以工作,我不知道如何让它更好地工作。现在,当我单击一个区域时,使用我拥有的代码,该图块被选中,有时它会立即取消选择,而其他时候则不会。几乎就像我按住鼠标一样,它只是不停地“点击”鼠标。我需要的是它选择瓷砖而不取消选择它,无论按下鼠标按钮多长时间。我的鼠标输入类是这样设置的:

鼠标输入.h

#pragma once

#include <SDL.h>

class MouseInput
{
public:
    MouseInput();
    ~MouseInput();

    void Update();

    bool GetMouseButton(int index);
    SDL_Event GetEvent();

    bool GetPressed();
    bool GetReleased();

private:
    void GetButtonStates();

private:
    bool mouseArray[3];
    int x, y;
    bool justReleased;
    bool justPressed;
    SDL_Event e;
};

鼠标输入.cpp

#include "Input.h"

MouseInput::MouseInput()
    :
    x(0),
    y(0),
    justReleased(false),
    justPressed(false)
{
    SDL_PumpEvents();

    for (int i = 0; i < 3; i++)
    {
        mouseArray[i] = false;
    }
}

MouseInput::~MouseInput()
{

}

void MouseInput::Update()
{
    SDL_PollEvent(&e);

    justReleased = false;
    justPressed = false;

    if (e.type == SDL_MOUSEBUTTONDOWN && e.button.button == SDL_BUTTON_LEFT)
        justPressed = true;
    else if (e.type == SDL_MOUSEBUTTONUP && e.button.button == SDL_BUTTON_LEFT)
        justReleased = true;
}

bool MouseInput::GetPressed()
{
    return justPressed;
}

bool MouseInput::GetReleased()
{
    return justReleased;
}

bool MouseInput::GetMouseButton(int index)
{
    if (index <= 3 && index >= 1)
    {
        return mouseArray[index - 1];
    }

    return false;
}

SDL_Event MouseInput::GetEvent()
{
    return e;
}

void MouseInput::GetButtonStates()
{
    SDL_PollEvent(&e);

    if (e.type == SDL_MOUSEBUTTONDOWN)
    {
        // 1 = Left; 2 = Center; 3 = Right
        mouseArray[e.button.button - 1] = true;
    }

    if (e.type == SDL_MOUSEBUTTONUP)
    {
        mouseArray[e.button.button - 1] = false;
    }
}

在我的游戏类中,我设置了鼠标输入以及一个变量来存储被点击的瓷砖的坐标。我还有一个变量pressed 来检查鼠标是否被按下。在我的更新功能中,我检查是否未按下鼠标。如果鼠标没有被按下,那么我检查鼠标是否被按下,游戏可以获得鼠标位置的坐标。我知道这听起来很疯狂,所以这是我的一些代码:

std::pair<int, int> coords; // Will store the coordinates of the tile position that the mouse rests in
bool pressed; // If the mouse was pressed (i should call it toggle because it's true if the mouse was pressed once, then false if the mouse was pressed again, then true...ect.)

更新功能

鼠标类

bool clicked; // In my custom Mouse.h file and set to false in constructor
MouseInput input; // In my custom Mouse.h file

鼠标类Update()

input.Update(); // Calls the MouseInput updating

if (input.GetPressed() && !clicked)
{
    clicked = !clicked;
    printf("OK");
}
//else if (clicked && input.GetReleased())
else if (clicked && input.GetPressed()) // Somewhat works. It works almost like before. If I click the mouse it shows up then sometimes when I click again it works, and other times I have to click a couple times
{
    clicked = !clicked;
}

在我的游戏类中,我只是检查鼠标点击是否为真,然后画出我需要的东西

if (mouse.GetClicked())
{
    // Draw what I need here.
    // Currently is only drawn when I hold down the mouse
    // And not drawn when I release the mouse.
}

然后当我在瓷砖周围绘制正方形时,我只在pressed = true 时绘制它。否则不绘制。此代码有时有效,有时则无效。为了得到我想要的效果,我必须真正快速地点击鼠标。如果我不这样做,有时看起来好像我正在按住鼠标按钮并且方块只是闪烁。

【问题讨论】:

  • 不相关,但在GetMouseButton 我认为您的意思是index &gt;= 1,而不是-1
  • 你说得对,哈哈。不知道为什么我有-1。这甚至没有意义哈哈。

标签: c++ sdl


【解决方案1】:

问题在于“鼠标按下”事件就是这样 - 一个事件。它应该发生一次,被处理,然后直到再次物理按下按钮才发生。使用您的代码,一旦按下它就会将内部状态设置为“按下”,然后在它被释放之前不会更改它。没关系,除了您的代码轮询此内部状态时将其视为事件,而不是状态,因此每次在按下鼠标按钮时运行更新函数时,都会看到“按下新按钮”。

这(使用一个按钮的代码的简化版本以及仅在按下按钮时显示图像的想法)可能会帮助您将其可视化:

bool buttonPressed = false;
bool imageShown = false;
while (true)
{
    SDL_Event e;
    SDL_PollEvent(&e);
    if (e.type == SDL_MOUSEBUTTONDOWN)
        buttonPressed = true;
    else if (e.type == SDL_MOUSEBUTTONUP)
        buttonPressed = false;

    if (!imageShown && buttonPressed)
        imageShown = true;
    else if (buttonPressed)
        imageShown = false;
}

您是否看到每次循环运行时,即使本次迭代没有触发任何事件,状态仍然存在?这将导致imageShown 变量在每次迭代时保持打开和关闭,直到触发“按钮向上”事件以重置状态。

您可能应该重新设计一些输入控制器 - 您需要公开一种方法来区分“按钮被按下现在”和“按钮被按下一段时间”。

一个想法是提供例如。 ButtonsPressedButtonsJustPressed 成员(虽然我相信你能想到更合适的名字)。每次调用 GetButtonStates 时,ButtonsJustPressed 成员都应重置为 false,因此它们只是 true,如果在循环的特定迭代中,它们已被按下,而 ButtonsPressed 成员是正是你现在正在做的事情。

考虑到这一点的上述调整版本:

bool buttonJustPressed = false;
bool buttonJustReleased = false;
bool imageShown = false;
while (true)
{
    // As far as we know, this iteration no events have been fired
    buttonJustPressed = false;
    buttonJustReleased = false
    SDL_Event e;
    SDL_PollEvent(&e);
    if (e.type == SDL_MOUSEBUTTONDOWN)
        buttonJustPressed = true;
    else if (e.type == SDL_MOUSEBUTTONUP)
        buttonJustReleased = true;

    if (!imageShown && buttonJustPressed)
        imageShown = true;
    else if (imageShown && buttonJustReleased)
        imageShown = false;
}

查看此版本如何仅在按钮被按下/释放时更改图像的可见性 - 如果按钮被按住,则不会触发事件,因此状态保持 false,并且图像的状态保持不变。

【讨论】:

  • 我明白你在说什么,但我仍然遇到问题。我设法让它打开。 (当用户按下鼠标时)。但是当用户再次按下鼠标关闭时,我现在很难管理。
  • 我想要做的是,当用户点击鼠标时,它会显示可以建造的塔。当用户再次单击鼠标时,它会消失。现在离开你给出的例子,我必须按住鼠标才能显示塔,释放鼠标时它们会消失。
  • @Vince 您已将更新功能代码更改为更符合if (!pressed &amp;&amp; mouseInput.GetMouseButtonJustPressed(1)) 的行吗?在这种情况下,请编辑您的帖子以包含您更新的代码(输入代码和“显示代码”),我稍后会查看它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-21
  • 1970-01-01
  • 1970-01-01
  • 2017-05-25
  • 2020-08-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多