【问题标题】:SFML Shape Not Drawn after Move移动后未绘制 SFML 形状
【发布时间】:2017-07-13 17:17:58
【问题描述】:

遵循 SFML 教程。这段代码应该允许我在屏幕上移动一个青色圆圈。在不使用 mPlayer.move(movement) 的情况下绘制圆圈可以正常工作,但是当这条线在 game.update 中运行时,形状会从屏幕上消失,永远不会被重绘。我错过了什么?

Game.cpp 

   Game::Game()
    :mWindow(sf::VideoMode(1440, 900, 32),"yeeboi1!!!!!") , mPlayer()
    {
    mPlayer.setRadius(20.f);
    mPlayer.setPosition(100.f, 110.f);
    mPlayer.setFillColor(sf::Color::Cyan);
    }


    Game::~Game()
{
}

    void Game::run() {
    while (mWindow.isOpen()) {
        processEvents();
        update();
        render();
    }
}

    void Game::processEvents()
    {
        sf::Event event;
        while (mWindow.pollEvent(event))
    {
            switch (event.type)
        {
        case sf::Event::KeyPressed:
            HandleInput(event.key.code, true);
            break;
        case sf::Event::KeyReleased:
            HandleInput(event.key.code, false);
            break;
        case sf::Event::Closed:
            mWindow.close();
            break;
        }

    }
}

    void Game::update() {
    sf::Vector2f movement(0.f, 0.f);
    if (mMoveUp)
        movement.y -= 1.f;
    if (mMoveDown)
        movement.y += 1.f;
    if (mMoveLeft)
        movement.x-= 1.f;
    if (mMoveRight)
        movement.x += 1.f;

    mPlayer.move(movement);




}

    void Game::render() {
    mWindow.clear();
    mWindow.draw(mPlayer);
    mWindow.display();
}

    void Game::HandleInput(sf::Keyboard::Key key, bool isPressed) {
    if (key == sf::Keyboard::W)
        mMoveUp = isPressed;
    if (key == sf::Keyboard::S)
        mMoveDown = isPressed;
    if (key == sf::Keyboard::A)
        mMoveLeft = isPressed;
    if (key == sf::Keyboard::D)
        mMoveRight = isPressed;
}



Game.h 

    #pragma once
    #include <SFML/Graphics.hpp>
    class Game
    {
    public:
    Game();
    ~Game();


    void run();

    private:
    void processEvents();
    void update();
    void render();
    void HandleInput(sf::Keyboard::Key key, bool isPressed);
    bool mMoveUp, mMoveDown, mMoveLeft, mMoveRight = false;

    private:
    sf::RenderWindow mWindow;
    sf::CircleShape mPlayer;
};




Main.cpp

#include "Game.h"


    int main()
    {
    Game game;
    game.run();

    return 0;
    }

【问题讨论】:

  • Eeek。可怕的缩进。难以阅读。
  • 我把它弄到 Stack Overflow 的时候完全杀了它,后来发现我只能 ctrl+k
  • 这里是一个使用精灵的更新版本的粘贴...移动后仍然是同样的问题link

标签: c++ sfml


【解决方案1】:

为什么不转向基于时间的处理? 确保您也阅读了http://gameprogrammingpatterns.com/game-loop.html

我目前坐在火车上,所以请为这个简短的回答道歉,但我想你明白了。查看 Game::run 和 update(dtAsSeconds) 中的变化

Game.cpp
#include "Game.h"

Game::Game()
 :mWindow(sf::VideoMode(1440, 900, 32),"yeeboi1!!!!!") , mPlayer()
 {
 mPlayer.setRadius(20.f);
 mPlayer.setPosition(100.f, 110.f);
 mPlayer.setFillColor(sf::Color::Cyan);
 }


 Game::~Game()
{
}

 void Game::run() {
   sf::Clock m_Clock = sf::Clock();

 while (mWindow.isOpen()) {
    sf::Time dt = m_Clock.restart();

    // Count seconds since last process
    float dtAsSeconds = dt.asSeconds();

     processEvents();
     update(dtAsSeconds);
     render();
 }
}

 void Game::processEvents()
 {
     sf::Event event;
     while (mWindow.pollEvent(event))
 {
         switch (event.type)
     {
     case sf::Event::KeyPressed:
         HandleInput(event.key.code, true);
         break;
     case sf::Event::KeyReleased:
         HandleInput(event.key.code, false);
         break;
     case sf::Event::Closed:
         mWindow.close();
         break;
     }

 }
}

 void Game::update(float dtAsSeconds) {
 sf::Vector2f movement(0.f, 0.f);
 if (mMoveUp)
     movement.y -= 1.f * dtAsSeconds * 100;
 if (mMoveDown)
     movement.y += 1.f * dtAsSeconds * 100;
 if (mMoveLeft)
     movement.x-= 1.f * dtAsSeconds * 100;
 if (mMoveRight)
     movement.x += 1.f * dtAsSeconds * 100;

 mPlayer.move(movement);




}

 void Game::render() {
 mWindow.clear();
 mWindow.draw(mPlayer);
 mWindow.display();
}

 void Game::HandleInput(sf::Keyboard::Key key, bool isPressed) {
 if (key == sf::Keyboard::W)
     mMoveUp = isPressed;
 if (key == sf::Keyboard::S)
     mMoveDown = isPressed;
 if (key == sf::Keyboard::A)
     mMoveLeft = isPressed;
 if (key == sf::Keyboard::D)
     mMoveRight = isPressed;
}

Game.h

#pragma once
#include <SFML/Graphics.hpp>
class Game
{
public:
Game();
~Game();


void run();

private:
void processEvents();
void update(float dtAsSeconds);
void render();
void HandleInput(sf::Keyboard::Key key, bool isPressed);
bool mMoveUp, mMoveDown, mMoveLeft, mMoveRight = false;

private:
sf::RenderWindow mWindow;
sf::CircleShape mPlayer;
};

main.cpp

#include "Game.h"

int main()
{
Game game;
game.run();

return 0;
}

【讨论】:

    【解决方案2】:

    您的游戏正在尽可能快地运行(这意味着您的圆圈会在最轻微的输入时飞出屏幕)。尝试限制帧率:

    mWindow.setFramerateLimit(60);
    

    然后每次调用mWindow.display() 都会等待一段时间。

    编辑:确保您的对象不依赖于帧速率。您可以使用sf::Clock 执行此操作。

    class Game {
    ...
    sf::Clock mClock;
    }
    

    然后在您的更新函数中,将输出乘以 deltaTime:

    void Game::update(sf::Time dt) {
        sf::Vector2f movement(0.f, 0.f);
        if (mMoveUp)
            movement.y -= 1.f * dt.asSeconds();
        ...
        mPlayer.move(movement);
    }
    
    //Now you can call the function
    update(mClock.restart());
    

    【讨论】:

    • 我添加了 mWindow.setFramerateLimit(60);到游戏构造函数,但仍然遇到同样的问题。
    • 我忘了提及sf::Clock 及其用于消除对帧速率的依赖的用途。我已经相应地更新了我的回复。
    猜你喜欢
    • 1970-01-01
    • 2020-11-23
    • 2013-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多