Adding the character

Location
  1. Tutorials

    /

  2. Introduction to coding

    /

  3. Adding the character

Grass, dirt, trees, stones and the character

The sprite and texture

The texture:

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

The sprite:

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

Testing if a key is pressed

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

Here, we test if the key W is pressed:

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':

float var1, var2;

Let us assign them values:

var1 = 5.25; var2 = 7.87;

Note that the following line of code does not change the value of neither of the two variables:

var1 + var2;

It only 'returns' the result of the operation. To change the value of one of the variables, we must write something like:

var1 = var1 + var2;

Or, here is an equivalent shortcut:

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:

sf::Vector2f vec;

We can access its coordinates like such:

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:

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:

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.

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.

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:

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:

sf::Vector2f trans;

If the key W is pressed, we subtract the movement from the X coordinate of the translation:

if(sf::Keyboard::isKeyPressed(sf::Keyboard::W)) trans.y -= mouv;

We do something similar for the keys A, S and D.

1
2
3
4
5
6
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:

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.

playerMovingClock.restart();

The code so far

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#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::Keyboard::isKeyPressed(sf::Keyboard::W)) trans.y -= mouv; 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; 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; }