Welcome to Code Forum!

Join a community that supports you and your coding journey from day one. We strive to be a friendly, supportive community that empowers everyone to be better developers. By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!
  • Tutorials listed in this section have not been reviewed nor are affliated by Code Forum. It is the sole responsbility of the authour to properly maintain and ensure information is accurate.

Unmaintained Introduction to coding - 6. Adding the character

Adding the character​

View attachment 610

The sprite and texture​

The texture:
C++:
sf::Texture playerTex;
playerTex.loadFromFile("resources/player.png");
The sprite:
C++:
sf::Sprite player;
player.setTexture(playerTex);
player.setPosition(400, 300);
player.setScale(3, 3);

Testing if a key is pressed​

The function 'sf:⌨️:isKeyPressed' returns true if the key received in argument is currently pressed. With SFML, the names of the keys start with 'sf:⌨️:'.

Here, we test if the key W is pressed:
C++:
if(sf::Keyboard::isKeyPressed(sf::Keyboard::W))
{
}

Mathematical operations​

To execute additions, subtractions, divisions and multiplications, we must use, in order, the symbols +, -, / and *.

If we define many variables of the same type, we can define them at the same time, by writing the type only once and separating the name of the variables by commas.

Let us define two variables of type 'float':
C++:
float var1, var2;
Let us assign them values:
C++:
var1 = 5.25;
var2 = 7.87;
Note that the following line of code does not change the value of neither of the two variables:
C++:
var1 + var2;
It only 'returns' the result of the operation. To change the value of one of the variables, we must write something like:
C++:
var1 = var1 + var2;
Or, here is an equivalent shortcut:
C++:
var1 += var2;

2D vector​

The class sf::Vector2f represents a 2 dimensional vector of type 'float'. It is basically a set of two variables of type 'float'. The variable type 'float' is used to represent real numbers (Numbers that may have digits after the decimal point).

We define a 2D vector:
C++:
sf::Vector2f vec;
We can access its coordinates like such:
C++:
vec.x = 12.345;
vec.y = 6.789;
By default, the coordinates of a vector are set to 0.

Making the character move​

We define a variable to represent the movement speed of the character:
C++:
float playerMovementSpeed = 200.0;
The class sf::Clock is used to measure time laps. We create an object of that class to handle the movements of the player in function of the time:
C++:
sf::Clock playerMovementClock;
An object of type sf::Clock, at its creation, starts at the time 0. The method 'restart' sets it back to 0.
C++:
playerMovementClock.restart();
Using the method 'getElapsedTime', we can retrieve the time that has elapsed since its creation or since the last time it has been restarted.
C++:
playerMovementClock.getElapsedTime();
By appending '.asSeconds()' after calling the method 'getElapsedTime', we retrieve the elapsed time in seconds, as a value of type 'float'.

In the game loop, we calculate the movement of the player by multiplying its movement speed by the number of seconds that has elapsed since the last time we handled its movement:
C++:
float mouv = playerMovementClock.getElapsedTime().asSeconds() * playerMovementSpeed;
If the time that has elapsed is 0.5 second, then, its movement is 100 pixels. If it is 1 second, then it is 200 pixels.

In the game loop, we define a vector representing the translation of the player:
C++:
sf::Vector2f trans;
If the key W is pressed, we subtract the movement from the X coordinate of the translation:
C++:
if(sf::Keyboard::isKeyPressed(sf::Keyboard::W))
    trans.y -= mouv;
We do something similar for the keys A, S and D.
C++:
if(sf::Keyboard::isKeyPressed(sf::Keyboard::S))
    trans.y += mouv;
if(sf::Keyboard::isKeyPressed(sf::Keyboard::A))
    trans.x -= mouv;
if(sf::Keyboard::isKeyPressed(sf::Keyboard::D))
    trans.x += mouv;
By calling the method 'getPosition' of a sprite, we can retrieve a vector representing its position.

We update the position of the sprite of the player, in function of the translation:
C++:
player.setPosition(player.getPosition().x+trans.x, player.getPosition().y+trans.y);
We restart the movement clock so the next time we handle the movement of the player, we can retrieve the time that has elapsed.
C++:
playerMovingClock.restart();

The code so far​

C++:
#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow win(sf::VideoMode(800, 600), "Introduction to coding", sf::Style::Close);

    // Grass

    sf::Texture grassTex;
    grassTex.loadFromFile("resources/grass.png");
    grassTex.setRepeated(true);

    sf::Sprite grass;
    grass.setTexture(grassTex);
    grass.setScale(5, 5);
    grass.setTextureRect(sf::IntRect(0,0,160,120));

    // Dirt tiles

    sf::Texture dirtTex;
    dirtTex.loadFromFile("resources/dirt.png");

    sf::Sprite dirtTiles[10];
    dirtTiles[0].setPosition(300, 60);
    dirtTiles[1].setPosition(660, 300);
    dirtTiles[2].setPosition(390, 480);
    dirtTiles[3].setPosition(660, 60);
    dirtTiles[4].setPosition(720, 420);
    dirtTiles[5].setPosition(180, 300);
    dirtTiles[6].setPosition(60, 180);
    dirtTiles[7].setPosition(60, 420);
    dirtTiles[8].setPosition(240, 420);
    dirtTiles[9].setPosition(480, 120);

    for(int c = 0; c < 10; c++)
    {
        dirtTiles[c].setTexture(dirtTex);
        dirtTiles[c].setScale(5, 5);
    }

    // Trees

    sf::Texture treeTex;
    treeTex.loadFromFile("resources/tree.png");

    sf::Sprite trees[8];
    trees[0].setPosition(50, 60);
    trees[1].setPosition(600, 150);
    trees[2].setPosition(630, 456);
    trees[3].setPosition(300, 600);
    trees[4].setPosition(720, 40);
    trees[5].setPosition(460, 500);
    trees[6].setPosition(20, 370);
    trees[7].setPosition(340, 240);

    for(int c = 0; c < 8; c++)
    {
        trees[c].setTexture(treeTex);
        trees[c].setScale(3, 3);
    }

    // Stones

    sf::Texture stoneTex;
    stoneTex.loadFromFile("resources/stone.png");

    sf::Sprite stones[3];
    stones[0].setPosition(304, 64);
    stones[1].setPosition(664, 304);
    stones[2].setPosition(180, 300);

    for(int c = 0; c < 3; c++)
    {
        stones[c].setTexture(stoneTex);
        stones[c].setScale(3, 3);
    }

    // Player

    sf::Texture playerTex;
    playerTex.loadFromFile("resources/player.png");

    sf::Sprite player;
    player.setTexture(playerTex);
    player.setPosition(400, 300);
    player.setScale(3, 3);

    float playerMovementSpeed = 200.0;
    sf::Clock playerMovementClock;

    // Game loop

    sf::Event event;

    while(win.isOpen())
    {
        while(win.pollEvent(event))
        {
            if(event.type == sf::Event::Closed)
                win.close();
        }

        // Player movements

        sf::Vector2f trans;
        float mouv =
        playerMovementClock.getElapsedTime().asSeconds() *
        playerMovementSpeed;

        if(sf:⌨️:isKeyPressed(sf:⌨️:W))
             trans.y -= mouv;
        if(sf:⌨️:isKeyPressed(sf:⌨️:S))
            trans.y += mouv;
        if(sf:⌨️:isKeyPressed(sf:⌨️:A))
            trans.x -= mouv;
        if(sf:⌨️:isKeyPressed(sf:⌨️:D))
            trans.x += mouv;

        player.setPosition(player.getPosition().x+trans.x, player.getPosition().y+trans.y);
        playerMovementClock.restart();

        // Rendering

        win.clear();

        win.draw(grass);

        for(int c = 0; c < 10; c++)
            win.draw(dirtTiles[c]);

        for(int c = 0; c < 8; c++)
            win.draw(trees[c]);

        for(int c = 0; c < 3; c++)
            win.draw(stones[c]);

        win.draw(player);

        win.display();
    }

    return 0;
}
 
Last edited by a moderator:
Back
Top Bottom