Нажмите кнопку логику с СФМЛ


Я написал некоторый функционал, который работает как предназначено для того, чтобы создать функциональный кликабельны прямоугольники. Я унаследовал от RectangleShape в СФМЛ и у меня есть несколько объектов (не только кнопки), которые наследуют от этого. Предполагаемая логика, чтобы проверить, если downpress и пары отпустите обе происходить внутри одного и того же объекта.

clickableRect.ч

#ifndef CLICKABLERECT
#define CLICKABLERECT

#include <SFML\Graphics.hpp>

class clickableRect : public sf::RectangleShape
{
public:
    clickableRect();

    bool click(const sf::RenderWindow & window, const sf::Event & ev);

    void reset();
private:
    bool m_mouseHeld;
    bool m_pressed;
    bool m_active;

    bool isInside(const sf::RenderWindow & window) const;
};
#endif // !CLICKABLERECT

и

clickableRect.cpp

#include "clickableRect.h"

clickableRect::clickableRect() :
    m_pressed(false),
    m_mouseHeld(false),
    m_active(false)
{
     //do nothing
}

bool clickableRect::click(const sf::RenderWindow & window, const sf::Event & ev)
{
    if (ev.type == sf::Event::MouseButtonPressed && isInside(window) && !m_mouseHeld)
    {
        m_pressed = true;
        m_mouseHeld = true;
    }
    else if (ev.type == sf::Event::MouseButtonPressed)
    {
        m_mouseHeld = true;
    }

    if (ev.type == sf::Event::MouseButtonReleased)
    {
        if (isInside(window) && m_pressed)
        {
            m_active = true;
        }
        m_pressed = false;
        m_mouseHeld = false;
    }

    return m_active;
}

void clickableRect::reset()
{
    m_active = false;
}

bool clickableRect::isInside(const sf::RenderWindow & window) const
{
    return sf::Mouse::getPosition(window).x > getPosition().x
        && sf::Mouse::getPosition(window).x < getPosition().x + getSize().x
        && sf::Mouse::getPosition(window).y > getPosition().y
        && sf::Mouse::getPosition(window).y < getPosition().y + getSize().y;
}

Я любил бы любую обратную связь по всем аспектам код, но запрос конкретно знать о:

  1. Это хорошее использование наследования и я все правильно делаю? Я должен использовать шаблон компонента?
  2. Я могу убирать самой логики внутри функции click. Кажется, немного сумбурно для меня, а также требует от меня, чтобы вызвать метод Reset на объекты сразу после возвращения истинного значения.


Комментарии
1 ответ


  • Компилировать со всеми предупреждениями

Если вы скомпилируете этот код со всеми предупреждениями (например -стены -Wextra -педантичный) компилятор скажет вам, что ваш инициализации вышел из строя.
Это просто означает, что вы инициализировать члены в другом порядке, чем они были объявлены. В вашем примере это не плохо, но если у вас есть члены, которые зависят от других, быть инициализирован прежде, чем им это может привести к проблемам.


  • & является частью типа в C++

Хотя это не ошибка, это может выглядеть как побитовое и с первого взгляда и быть потенциальным источником путаницы. Предпочитаю писать foo& bar вместо foo & bar.


  • Определяемые пользователем типы

Также несовершеннолетний придираться, но обычно определяемые пользователем типы начинаются с заглавной буквы, т. е. ClickableRect.
Поскольку вы наследуете от Shape Я думаю, было бы больше смысла, чтобы назвать свой класс ClickableShape но это просто личные предпочтения.


  • Дизайн

Вы выставляете window в вашем классе только получить доступ к мыши координаты. Если вы не планируете использовать окно в будущее, другое дело было бы лучше, чтобы скрыть эту информацию от вашего класса.
Простой подход к тестированию за клик в вашей формы может быть:

class ClickableShape : public sf::RectangleShape {
public:
bool click(const sf::Vector2i& mouse_pos) const {
return getGlobalBounds().contains(mouse_pos.x, mouse_pos.y);
}
};

Что тогда можно назвать:

ClickableShape cs{};
cs.setSize(sf::Vector2f(50, 50));
cs.setFillColor(sf::Color(0xffffffff));

И, наконец, в свой цикл обработки событий:

case sf::Event::MouseButtonPressed:
cs.click(sf::Mouse::getPosition(window));
break;

Таким образом, вы не подвергать ненужные данные на свой класс и все еще можете проверить, если форма была нажата.

Подход #2:

Я не уверен, что вы собираетесь делать с этим в будущем, но и другой подход к этому будет держать наследства короткий и прямоугольник в качестве члена.

class MyButton : public sf::Drawable {
public:
MyButton() {
shape.setSize(sf::Vector2f(50, 50));
shape.setFillColor(sf::Color(0xffffffff));
}

bool click(const sf::Event& event) const {
return shape.getGlobalBounds().contains(event.mouseButton.x, event.mouseButton.y);
}

void draw(sf::RenderTarget& target, sf::RenderStates states) const {
target.draw(shape);
}

private:
sf::RectangleShape shape;
};

3
ответ дан 26 марта 2018 в 04:03 Источник Поделиться