(vscode) C + +, SFML write game applet ----- note1

Keywords: C++ Visual Studio Code

  1. Call the SFML class and draw several small shapes to the window. (window class, shape class)
#include <SFML/Graphics.hpp>
int main()
{    
     //create a window
     sf::RenderWindow window(sf::VideoMode(640, 480), "SFML Application");
     //create a circle shape
     sf::CircleShape cShape;
     cShape.setRadius(40.f);
     cShape.setPosition(100.f, 100.f);
     cShape.setFillColor(sf::Color::Cyan);
    //create a Rectangle shape
     sf::RectangleShape rShape;
     sf::Vector2f v1(165.f, 240.f);
     rShape.setSize(v1);
     rShape.setPosition(v1);
     rShape.setFillColor(sf::Color::Magenta);

     while (window.isOpen())
      {
       sf::Event event;
       while (window.pollEvent(event))
       {
           if (event.type == sf::Event::Closed)
             window.close();
       }
       window.clear();
       window.draw(rShape);
       window.draw(cShape);
       window.display();
      }
}
  1. Rewrite the above program into written in class and object mode
class Game
{
public:
               Game();
               void run();

private:
               void processEvents(); // processEvents() is responsible for player input
               void update();
               void render();

private:
               sf::RenderWindow mWindow;
               sf::CircleShape mPlayer;
};
//Constructor of composite class, initial value list
Game::Game()
    : mWindow(sf::VideoMode(640, 680), "SFML APPlication") //mWindow object of combined class RenderWindow class
    , mPlayer()                                           //The object Mlayer of the composite class CircleShape class
    {          //Class member function calls private members
               mPlayer.setRadius(40.f);
               mPlayer.setPosition(100.f,100.f);
               mPlayer.setFillColor(sf::Color::Cyan);
    };
void Game::run(){
    //Class member function calls private members
    while(mWindow.isOpen())
    {
        processEvents(); //Processing window input
        update();
        render();
    }
}
void Game::processEvents()
{
    //Life cycle of control program
    //It keeps iterating to keep the program alive
    //It tells the program when it should stop
    sf::Event event;
    while(mWindow.pollEvent(event))
    {
        if (event.type==sf::Event::Closed)
             mWindow.close();
    }
}
void Game::update()
{
    //Used to add new features to the game
}
void Game::render()
{
    //During the iteration, we receive and process the information from the screen, and then present it to the screen
    //Render function to render the game to the screen
    //First, clean the screen with a certain color; Then, our shape is finally presented to the screen
    mWindow.clear();
    mWindow.draw(mPlayer);
    mWindow.display();
}
int main(){
    Game game;
    game.run();
    return 0;
}
  1. There is a loop in the program, iterating and refreshing the program.
    In this process, users can interact with the game through the window. The user presses the keyboard, the user crosses out the window... These operations of the user will be passed to the operating system. SFLM learns these events from the operating system and transmits them to the program in a unified way, that is, ef::event.
    Once the system detects the occurrence of some input events, these input events will be saved to an event object. The program detects all event objects and responds to them.
    SFML supports many types of events, including keypressed and keyreleased.
    According to the above, the processEvents() window event receiving and processing function and the update function processEvents() have been modified. Let's control the circular movement in the picture through the keyboard.
#include"SFML/Graphics.hpp"
#include"SFML/Window/Event.hpp"

bool mIsMovingDown=false;
bool mIsMovingUp = false;
bool mIsMovingLeft = false;
bool mIsMovingRight = false;

class Game
{
public:
               Game();
               void run();
               void handlePlayerInput(sf::Keyboard::Key key, bool isPressed);

private : void processEvents(); // processEvents() is responsible for player input
               void update();
               void render();

private:
               sf::RenderWindow mWindow;
               sf::CircleShape mPlayer;
};
//Constructor of composite class, initial value list
Game::Game()
    : mWindow(sf::VideoMode(640, 680), "SFML APPlication") //mWindow object of combined class RenderWindow class
    , mPlayer()                                           //The object Mlayer of the composite class CircleShape class
    {          //Class member function calls private members
               mPlayer.setRadius(40.f);
               mPlayer.setPosition(100.f,100.f);
               mPlayer.setFillColor(sf::Color::Cyan);
    };
void Game::run(){
    //Class member function calls private members
    while(mWindow.isOpen())
    {
        processEvents(); //Processing window input
        update();
        render();
    }
}
void Game::processEvents()
{
    //Life cycle of control program; It keeps iterating to keep the program alive; It tells the program when it should stop
    /*window There may be multiple events, and several types of events we detect*/ 
    sf::Event event;
    while(mWindow.pollEvent(event)) //What happened to the pollEvent function? Is it to grab the event of the window to the event object
    {
        switch(event.type)
        { 
        //keypressed is an enumerated variable of the Event class
        //If event.type=sf::Event::keypressed
        case sf::Event::KeyPressed :
            handlePlayerInput(event.key.code, true); //(which buttons are moved and how are they moved)
            break;
        //If event.type=sf::Event::keyReleased
        case sf::Event::KeyReleased :
            handlePlayerInput(event.key.code, false);
            break;
        }
    }
}
void Game::handlePlayerInput(sf::Keyboard::Key key, bool ispressed)
{
    //Save the information transmitted from the keyboard and save it in the variable mIsMoving series
    if(key==sf::Keyboard::W)
         mIsMovingUp=ispressed;
    else if (key == sf::Keyboard::S)
         mIsMovingDown = ispressed;
    else if (key == sf::Keyboard::A)
         mIsMovingLeft = ispressed;
    else if (key == sf::Keyboard::D)
         mIsMovingRight= ispressed;
}
void Game::update()
{
    //Update the game screen
    /*In each cycle of refresh substitution, the information transmitted from the keyboard is received,
    Next, the screen should be updated accordingly*/
    sf::Vector2f movement(0.f,0.f);
    if(mIsMovingUp) //How is this variable defined as a global variable?
        movement.y-=1.f;
    if (mIsMovingDown)
        movement.y += 1.f;
    if (mIsMovingRight) //How is this variable defined as a global variable?
        movement.x -= 1.f;
    if (mIsMovingLeft)
        movement.x += 1.f;
    mPlayer.move(movement);
}
void Game::render()
{
    //During the iteration, we receive and process the information from the screen, and then present it to the screen
    //Render function to render the game to the screen
    //First, clean the screen with a certain color; Then, our shape is finally presented to the screen
    mWindow.clear();
    mWindow.draw(mPlayer);
    mWindow.display();
}

int main(){
    Game game;
    game.run();
    return 0;
    sf::Keyboard a;

}

Disadvantages: it moves very fast.
Reason: in the while loop, one loop (one frame) is very fast, and mwindow.isepen calls very fast. It may cycle hundreds of times a second. The window input, update and rendering functions run hundreds of times during the time we press the key, so the shape flies out.

4. Solution: create a mobile that is not determined by the frame update frequency.

  • We receive a time for each call update
  • Calculation: distance to be moved per frame = time consumed per frame * moving speed. We can set the movement speed according to the distance we want.
    The time period from the previous frame to the middle of the frame is recorded as delta time.

How to get delta time?

There is a time Class in SFML, which can measure the time from its start s.
This is the clock class. It has a function restart(), which can return the time period from its start to restart, and reset the time point to zero.
SFML also has a data class time, which is very convenient for the conversion between s and ms.
time t.assecond() is to convert time type data into a number in s.

Posted by randydg on Sat, 20 Nov 2021 17:52:15 -0800