2017-08-04 83 views
0

所以我正在开发塔防游戏。我需要选择一个用户点击鼠标的图块(现在我只是在图块周围绘制边框)。现在,我有时可以使用代码,但我不确定如何让它更好地工作。现在,当我点击一个区域时,代码会被选中,有时它会立即取消选择,而其他时间则不会。几乎就像我拿着鼠标,它只是“点击”鼠标。我需要的是,无论取消选择图块,无论鼠标按钮被按下多长时间,都可以选择该图块。我的鼠标输入级的设置是这样的:SDL C++鼠标输入处理切换效果

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

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

在我的游戏类我已经安装了mouseinput以及一个变量来存储被点击的图块的坐标。我也有一个变量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 

Mouse类更新()

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。否则它不会被绘制。此代码有时有效,有时不适用。为了得到我想要的效果,我必须快速点击鼠标。如果我不这样做,有时看起来好像我正在按住鼠标按钮并且正方形闪烁。

+0

不相关,但在'GetMouseButton'中我认为你的意思是'index> = 1',而不是'-1'。 – hnefatl

+0

你是对的。不知道为什么我有-1。这甚至没有意义哈哈。 – Vince

回答

0

问题是,“鼠标向下”事件就是这样一个事件。它应该发生一次,被处理,然后不会再发生,直到再次按下按钮。使用你的代码,一旦按下它就会将内部状态设置为“按下”,然后不会改变它,直到它被释放。没关系,除了轮询这个内部状态的代码把它看作是一个事件而不是状态,所以每当按下鼠标按钮时运行更新函数,它就会看到“新按钮按下”。

可能会帮助这(代码中使用一个按钮,显示只有一个按钮的按下的图像的想法简化版本),你想象它:

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成员(尽管我相信你可以想到更合适的名字)。 ButtonsJustPressed成员在每次拨打GetButtonStates时应重置为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,并且图片的状态保持不变。

+0

我明白你在这里说什么,但我仍然有问题。我设法能够让它切换。 (当用户按下鼠标时)。但是,当用户再次按下鼠标来切换时,我现在无法进行管理。 – Vince

+0

我想要做的是当用户单击鼠标时,它将显示可用于构建的塔。当用户再次点击鼠标时,它将消失。现在放弃你给出的例子,我必须按住鼠标才能显示塔,当鼠标释放时它们会消失。 – Vince

+0

@Vince你已经更改了你的更新函数代码,更符合'if(!pressed && mouseInput.GetMouseButtonJustPressed(1))'的命令行吗?在这种情况下,编辑您的帖子以包含您的更新代码(输入代码和“显示代码”),稍后我会看看它。 – hnefatl