为什么我的按钮类项共享相同的lambda函数?

时间:2019-03-22 08:22:08

标签: c++ class sfml

我正在尝试在SFML中创建自己的可重用按钮类。这将允许我创建一个按钮并向其中添加一个回调函数,以使创建按钮更加容易。

这是我的hpp文件:

#ifndef Button_hpp
#define Button_hpp

#include <stdio.h>
#include <SFML/Graphics.hpp>
#include "View.hpp"
#include "State.hpp"
#include "Window.hpp"
namespace kge {
  class Button: public View{
  private:
    sf::RectangleShape* _buttonOutline;
    sf::RenderWindow* _window;
    sf::Clock _clock;
    std::string _textString;
    sf::Text* _text;
  public:
    Button(Window*, std::string);
    ~Button();
    virtual void update(float td);
    std::function<void(void)> callback;
    void setPosition(float x, float y);
  };
}
#endif /* Button_hpp */

这是我生成按钮的地方:

_restartButton = new kge::Button(_window, "Restart");
_restartButton->setPosition(getCenterOfScreen().x-((11*fontSize)/2), 300);
_restartButton->callback = ([this](){
  State::instance().currentView = new GameView(this->_window);
  this->_window->setView(State::instance().currentView);
});
_exitButton = new kge::Button(_window, "Quit");
_exitButton->setPosition(getCenterOfScreen().x-((11*fontSize)/2), 500);
_exitButton->callback = ([this](){
  this->_window->close();
});

最后,我告诉按钮进行更新,并在我的窗口更新button->update(td)

中进行检查

我所有的按钮似乎都执行上一次设置的回调的操作。在这种情况下,我的重新启动按钮将执行退出代码。

为什么会这样,我该如何解决?

修改

这是我的世代代码:

#ifndef GameOver_hpp
#define GameOver_hpp

#include <stdio.h>
#include "View.hpp"
#include "Button.hpp"
#include "GameView.hpp"
#include "State.hpp"

namespace kge{
  class View;
};

class GameOver: public kge::View{
private:
  sf::Text* _text;
  kge::Button* _restartButton;
  kge::Button* _exitButton;

  void restartFunction(void){

  }
public:
  GameOver(kge::Window* screen) : View(screen){
    int fontSize = 50;
    _text = new sf::Text();
    _text->setFont(kge::AssetManager::mainBundle().getFontNamed("mainfont"));
    _text->setString("Game Over");
    _text->setCharacterSize(fontSize);
    _text->setPosition(getCenterOfScreen().x-((9*fontSize)/2), 100);
    _text->setFillColor(sf::Color(255,0,0));

    _restartButton = new kge::Button(_window, "Restart");
    _restartButton->setPosition(getCenterOfScreen().x-((11*fontSize)/2), 300);

    _exitButton = new kge::Button(_window, "Quit");
    _exitButton->setPosition(getCenterOfScreen().x-((11*fontSize)/2), 500);

    _restartButton->callback = ([this](){
//      State::instance().currentView = new GameView(this->_window);
//      this->_window->setView(State::instance().currentView);
      puts("Restart");
    });

    _exitButton->callback = ([this](){
//      this->_window->close();
      puts("Restart");
    });


    this->addItemToView(_text);
    this->addItemToView(_restartButton);
    this->addItemToView(_exitButton);
  }

  void update(float td){
    _restartButton->update(td);
    _exitButton->update(td);

  }

  ~GameOver(){
    delete _text;
    delete _restartButton;
  }
};

#endif /* GameOver_hpp */

注意,kge :: View只是一个自定义sf :: Drawable类(我如何创建自己的“视图”)

编辑2 按钮更新功能:

  void Button::update(float td){
    if(_clock.getElapsedTime().asMilliseconds() < 400) return;
    if(!sf::Mouse::isButtonPressed(sf::Mouse::Left)) return;
    if(mouseIsIn(*_buttonOutline, _window)){
      callback();
      _clock.restart();
    }
  }

请注意:_clock是sf :: Clock,它私下存储在按钮类中。

1 个答案:

答案 0 :(得分:1)

此问题已通过聊天解决。总而言之,@ iProgram发布的OneToOne函数无法正确检查冲突,导致多个按钮同时触发。

原始功能:

mouseIsIn

固定功能:

bool mouseIsIn(sf::RectangleShape shape, sf::RenderWindow* window){
    sf::FloatRect shapeBounds = shape.getGlobalBounds();
    sf::Vector2i mousePos = sf::Mouse::getPosition(*window);
    sf::FloatRect mouseRect = sf::FloatRect(mousePos.x, mousePos.y, mousePos.x+shapeBounds.width, mousePos.y+shapeBounds.height);
    return mouseRect.intersects(shapeBounds);
}