【问题标题】:Dragging a sprite in sfml在 sfml 中拖动精灵
【发布时间】:2021-01-09 15:21:07
【问题描述】:

我现在正在做一个任务,为此,我需要将棋子拖到棋盘上,问题是我不知道如何使这项工作不止一个棋子。我可以计算鼠标位置,我只能移动一块,但代码只适用于那一块。我的问题是我如何点击一个片段,让它成为活动片段,直到我释放鼠标按钮。如果我只检查它是否与一件相交,这将不起作用,因为那时它不是动态的。我的代码因为我尝试不同的东西而一团糟,但这里有一些相关的部分。

这是精灵的设置:

// load the texture and setup the sprite for the logo
void Game::setupSprite()
{
    sf::IntRect pieceRect(m_wking.getPosition().x, m_wking.getPosition().y, 128, 128);

    if (!m_boardTexture.loadFromFile("ASSETS\\IMAGES\\board.png"))
    {
        // simple error message if previous call fails
        std::cout << "problem loading board" << std::endl;
    }
    m_boardSprite.setTexture(m_boardTexture);
    m_boardSprite.setPosition(0.0f, 0.0f);


    //pieces
    if (!m_wkingTex.loadFromFile("ASSETS\\IMAGES\\PIECES\\wking.png"))
    {
        // simple error message if previous call fails
        std::cout << "problem loading piece" << std::endl;
    }
    m_wking.setTexture(m_wkingTex);
    m_wking.setPosition(0.0f, 0.0f);
    sf::IntRect wkingRect(pieceRect);
}

如果鼠标按钮按下

void Game::processMouseButtonDown(sf::Event t_event)
{
    if (sf::Mouse::isButtonPressed(sf::Mouse::Button::Left)) {
        std::cout << "Mouse button pressed\n";
        sf::Vector2f mouse = m_window.mapPixelToCoords(sf::Mouse::getPosition(m_window));
        if (isSpriteClicked() && !m_holdingPiece) {

            m_holdingPiece = true;
        }
    }
}

鼠标按钮向上:

void Game::processMouseButtonUp(sf::Event t_event)
{
    m_holdingPiece = false;
    sf::IntRect pieceRect(m_wking.getPosition().x, m_wking.getPosition().y, 128, 128);
    m_wking.setTextureRect(pieceRect);
}

如果精灵被点击

bool Game::isSpriteClicked()
{
    sf::Vector2f mouse = m_window.mapPixelToCoords(sf::Mouse::getPosition(m_window));
    sf::FloatRect bounds(mouse.x, mouse.y, 1.0f, 1.0f);
    if (bounds.intersects(wkingRect.I dont know what Im doing)) {

        std::cout << "King has Been clicked!\n";
        return true;
    }
    else {
        return false;
    }
}

最后是移动精灵:

void Game::move()
{
    if (m_holdingPiece) {
        sf::Vector2f mouse = m_window.mapPixelToCoords(sf::Mouse::getPosition(m_window));
        m_wking.setPosition(mouse);
    }
}

对不起,如果这看起来像很多代码,但我觉得这一切都与问题有关。

【问题讨论】:

  • 发布一个最小的可重现示例。您的示例可能很小,但不可重现。我无法将您的代码复制并粘贴到我的编辑器中以运行它。
  • 可能您的问题的答案是使用 OOP 为具有移动功能的每个部分创建一个对象。
  • @GaryNLOL 复制和粘贴此代码不会做任何事情,因为它不起作用。我正在尝试找出一种能够将某些精灵标记为可拖动的方法。所以代码检测到我点击的实际上是一个精灵,它也是一个可拖动的精灵,然后它拖动那个精灵直到我释放鼠标按钮,我的代码没有这样做,所以复制它不会帮助
  • 解决问题本身无济于事,但会给我们一个重现问题的基础并帮助您解决问题。由于您的帖子现在是我们必须从头开始创建所有基础并且将更难为您提供帮助。
  • @GaryNLOL 我不能提供任何最小的东西,因为我被要求处理多个文件的跨度,但我可以提供项目的粘贴箱。 Main.cpp:pastebin.com/6CxkmycPGame.cpp:pastebin.com/UEvcUadsGame.h:pastebin.com/9ELwSmG6

标签: c++ sfml


【解决方案1】:

问题:

您已经对所有变量进行了硬编码,因此即使您创建一个列表并对其进行迭代以运行 Game::move(),它也会移动所有部分而不是仅移动一个,因为变量 m_holdingPiece 对于所有部分都是相同的。

解决方案:

您应该使用更多面向对象的方法为棋子创建一个类,而Game 类可能应该只控制游戏何时开始、何时结束并检查移动是否合法。解释 Stack Overflow 过于宽泛的所有内容,这是您必须完成的工作的一部分,因此我将仅举一个示例,说明基本的 chessPiece 类如何使片段变得可拖动。

示例:

这是一个示例,说明如何使一组片段可拖动。

#include <SFML/Graphics.hpp>
#include <string>

class chessPiece: public sf::Drawable, public sf::Transformable
{
private:
    sf::RenderWindow& window;
    sf::Texture texture;
    sf::Sprite sprite;
    bool moving;
public:
    chessPiece(sf::RenderWindow& windowRef, const std::string& fileName): window(windowRef)
    {
        if(!texture.loadFromFile(fileName))
            exit(0);
        this->sprite.setTexture(this->texture);
        this->moving = false;
        this->sprite.setScale(128/this->sprite.getGlobalBounds().width,128/this->sprite.getGlobalBounds().height);
    }
    chessPiece(chessPiece&& rval): window(rval.window)
    {
        this->texture = std::move(rval.texture);
        this->sprite.setTexture(this->texture);
        this->sprite.setScale(rval.sprite.getScale());
        this->moving = std::move(rval.moving);
    }
    chessPiece(const chessPiece& lval): window(lval.window)
    {
        this->texture = lval.texture;
        this->sprite.setTexture(this->texture);
        this->sprite.setScale(lval.sprite.getScale());
        this->moving = lval.moving;
    }
    void draw(sf::RenderTarget& target, sf::RenderStates states) const
    {
        states.transform *= this->getTransform();
        target.draw(this->sprite,states);
    }
    void move(bool& movingAPiece)
    {
        sf::Vector2f mousePosition = window.mapPixelToCoords(sf::Mouse::getPosition(window));
        if(this->moving)
        {
            this->setPosition(mousePosition.x - this->sprite.getGlobalBounds().width/2,mousePosition.y - this->sprite.getGlobalBounds().height/2);
            if(!sf::Mouse::isButtonPressed(sf::Mouse::Button::Left))
            {
                this->moving = false;
                movingAPiece = false;
            }
        }
        else
        {
            if(sf::Mouse::isButtonPressed(sf::Mouse::Button::Left) && mousePosition.x > this->getPosition().x &&
               mousePosition.y > this->getPosition().y && mousePosition.x < this->getPosition().x + this->sprite.getGlobalBounds().width &&
               mousePosition.y < this->getPosition().y + this->sprite.getGlobalBounds().height && !movingAPiece)
            {
                this->moving = true;
                movingAPiece = true;
            }
        }
    }
};

int main()
{
    sf::RenderWindow window(sf::VideoMode(1000,500),"Window");
    std::vector<chessPiece> pieces = {chessPiece(window,"white-king.png"),chessPiece(window,"white-pawn.png")};
    pieces[0].setPosition(400,400);
    bool movingAPiece = false;
    while(true)
    {
        sf::Event event;
        if(window.pollEvent(event))
            if(event.type == sf::Event::Closed)
                window.close();
        for(unsigned int i = 0; i < pieces.size(); i++)
            pieces[i].move(movingAPiece);
        window.clear();
        for(unsigned int i = 0; i < pieces.size(); i++)
            window.draw(pieces[i]);
        window.display();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-19
    • 2019-03-10
    • 2017-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-09
    • 1970-01-01
    相关资源
    最近更新 更多