-
Notifications
You must be signed in to change notification settings - Fork 1
Tutorial SFML
O projeto codeblocks possui o arquivo sfml.cpp que implementa várias funções para desenho de formas, tais como ellipse(), rect(), line(), point(), quad(), triangle(). Essas funções são implementadas usando os recursos da biblioteca SFML e visam facilitar a implementação do jogo. Esse tutorial é baseado no tutorial sobre desenvolvimento de jogos com p5.js, feito pelo Professor Orivaldo Santana.
Para começar, digite o código abaixo no seu arquivo main.cpp do projeto que você baixou aqui. (Se ainda não havia baixado o projeto nem configurado o codeblocks, siga o tutorial de configuração e após terminar retorne).
#include "sfml.h"
int main() {
//cria a janela com tamanho 640x480 pixels
SFML sfml(640,480,"Meu jogo!");
//define a cor de fundo como preto
sfml.background(0,0,0);
//início do laço principal do jogo
while (sfml.windowIsOpen()) {
//apaga o conteúdo da janela
sfml.clear();
//Desenha uma ellipse no centro da tela
sfml.ellipse(320-50, 240-50, 100, 100);
//mostra o conteúdo na janela
sfml.display();
}
return 0;
}
No caso do código acima, é desenhado um círculo de tamanho 100x100 no centro da tela (320,240). Para isso, usamos a função ellipse([coordenada_centro x],[coordenada_centro y], [largura], [altura]). O resultado da execução desse código aparece na imagem abaixo.
Podemos também brincar com a aparência dessas formas. No seu main.cpp, digite o código seguinte:
#include "sfml.h"
int main() {
//cria a janela com tamanho 640x480 pixels
SFML sfml(640,480,"Meu jogo!");
//define a cor de fundo como preto
sfml.background(0,0,0);
//início do laço principal do jogo
while (sfml.windowIsOpen()) {
//apaga o conteúdo da janela
sfml.clear();
//desativa o preenchimento
sfml.noFill();
//ativa a borda com cor azul
sfml.stroke(0, 0, 255);
//desenha uma ellipse sem preenchimento com borda
//azul, com centro no ponto (200,100)
sfml.ellipse(200-60, 100-30, 120, 60);
//desativa a borda
sfml.noStroke();
//ativa o preenchimento
sfml.fill(255, 0, 0);
//desenha um retângulo com preenchimento vermelho
//e sem borda, com centro no ponto(200,200)
sfml.rect(200-40, 200-40, 80, 80);
//ativa a borda
sfml.stroke(60, 150, 60);
//define a largura da borda como 3 pixels
sfml.strokeWeight(3);
//desenha uma linha com largura de 3 pixels
sfml.line(100, 300, 400, 400);
//mostra o conteúdo na janela
sfml.display();
}
return 0;
}
O resultado da compilação e execução do código acima é mostrado na imagem abaixo
A linha RenderWindow window()
cria uma janela com tamanho 640x480, e a linha background()
define sua cor de fundo. As funções fill() e stroke(), definem as cores de preenchimento e de contorno, respectivamente. Uma vez utilizadas essas funções, seus efeitos valerão para todas as formas declaradas abaixo. noFill() e noStroke() retiram o preenchimento e o contorno, respectivamente, e strokeWeight() define uma espessura para o contorno da forma. Essas funções são implementadas no arquivo draw.cpp usando os recursos da biblioteca SFML e visam facilitar a implementação do jogo.
Agora vejamos algo mais interessante...
O laço while(window.isOpen()){}
ficará se repetindo no decorrer da execução do programa. Nele poderemos fazer algo mudar seu valor ao longo do tempo. Um exemplo é a posição da ellipse, que pode ser alterada de acordo com a posição do mouse! Escreva o código abaixo no arquivo main.cpp para implementar esse comportamento.
#include "sfml.h"
int main() {
SFML sfml(640,480,"Meu jogo!");
sfml.background(255,255,255);
sfml.clear();
sfml.noFill();
sfml.stroke(0,0,0);
while (sfml.windowIsOpen()) {
//verifica se o usuário está pressionando o botão esquerdo do mouse
if (sfml.mouseLeftButtonIsPressed()) {
//desenha uma ellipse na posição do ponteiro do mouse
sfml.ellipse(sfml.mouseX()-50, sfml.mouseY()-50, 100, 100);
}
sfml.display();
}
return 0;
}
O teste if (Mouse::isButtonPressed(Mouse::Button::Left))
verifica se o usuário está pressionando o botão esquerdo do mouse. Caso esteja, é desenhado um círculo sem preenchimento e com borda preta, na posição corrente do mouse. Veja imagem abaixo.
A função random(min, max) também pode ser muito útil para diversas aplicações. O código abaixo desenha linhas com posições de início e fim aleatórias, enquanto o jogador mantém o botão esquerdo do mouse pressionado.
#include "sfml.h"
#include "util.h"
using namespace util;
int main() {
SFML sfml(640,480,"Meu jogo!");
sfml.background(255,255,255);
sfml.stroke(0,0,0);
sfml.clear();
while (sfml.windowIsOpen()) {
//verifica se o usuário está pressionando o botão esquerdo do mouse
if(sfml.mouseLeftButtonIsPressed()) {
//desenha uma linha com posição duas extremidades em posições aleatórias da tela
sfml.line(random(0,640),random(0,480),random(0,640),random(0,480));
}
sfml.display();
}
return 0;
}
O resultado do código acima é mostrado na imagem abaixo.
O código anterior desenha várias linhas loucamente enquanto o usuário mantém o botão esquerdo do mouse pressionado. Mas e se quisermos desenhar uma única linha a cada clique do mouse? Experimente executar o código abaixo e veja o que acontece ao clicar com o botão esquerdo do mouse.
#include "sfml.h"
#include "util.h"
using namespace util;
int main() {
SFML sfml(640,480,"Meu jogo!");
sfml.background(255,255,255);
sfml.stroke(0,0,0);
sfml.clear();
bool drawline = true;
while (sfml.windowIsOpen()) {
if(sfml.mouseLeftButtonIsPressed()) {
if(drawline) {
sfml.line(random(0,640),random(0,480),random(0,640),random(0,480));
//faz com que a linha seja desenhada novamente somente quando o usuário
//deixar de pressionar o botão esquerdo do mouse e pressionar novamente
drawline = false;
}
} else {
drawline = true;
}
sfml.display();
}
return 0;
}
Podemos usar variáveis para desenhar formas geométricas em posições diferentes. Basta usar variáveis para controlar as posições desses figuras. Veja o código abaixo.
#include "sfml.h"
int main() {
SFML sfml(640,480,"Meu jogo!");
sfml.background(0,0,0);
float x = 200;
while (sfml.windowIsOpen()) {
sfml.clear();
//Desenha uma ellipse com coordenada x definida pela variável x
sfml.ellipse(x, 240-50, 100, 100);
x += 2;
if(x > 690) {
x = -50;
}
sfml.display();
}
return 0;
}
A execução do código acima faz com que um círculo seja desenhado em diferentes posições, dando a impressão de movimento. No laço principal do jogo, verificamos se a posição x do círculo está dentro da nossa janela. Se sim, a variável x é incrementada fazendo com que o círculo ande pela tela na horizontal. Se o círculo sai da janela, a posição x volta para zero (0) e o ciclo recomeça. A janela está sendo limpada (sfml.clear()
) dentro do laço principal para evitar que o círculo deixe um rastro na tela; primeiro é pintado um fundo, depois o círculo é pintado em uma posição x, depois o fundo é pintado novamente e só então um novo círculo é pintado, em uma nova posição x. Experimente retirar a linha sfml.clear()
e veja o que acontece.
No código abaixo utilizamos entradas do teclado para alterar os valores das variáveis criadas. Isso é feito através da função keyIsDown(), que retorna true sempre que uma tecla com o mesmo código que foi passado como parâmetro na função estiver sendo pressionada, e false caso contrário. Exemplos de possíveis valores são: Backspace, Delete, Enter, Tab, Escape, LShift, LControl, Up, Down, Left, Right. Para conhecer mais valores de teclas, consulte o arquivo sfml.h.
#include "sfml.h"
int main() {
SFML sfml(640,480,"Meu jogo!");
sfml.background(0,0,0);
float x = 100;
float y = 100;
float speed = 5;
while (sfml.windowIsOpen()) {
sfml.clear();
if (sfml.keyIsDown(SFML::Key::Left)) {
x-=speed;
} else if (sfml.keyIsDown(SFML::Key::Right)) {
x+=speed;
} else if (sfml.keyIsDown(SFML::Key::Up)) {
y-=speed;
} else if (sfml.keyIsDown(SFML::Key::Down)) {
y+=speed;
}
sfml.ellipse(x, y, 50, 50);
sfml.display();
}
return 0;
}
A aleatoriedade é muito útil no desenvolvimento de jogos. Por exemplo, um inimigo pode aparecer em uma posição aleatória do mapa cada vez que você começa o jogo. Na nossa biblioteca, podemos sortear números aleatórios através da função util::random, da biblioteca util.h. No código abaixo, a função random foi utilizada para definir uma posição aleatória para um retângulo, dentro da nossa tela. Observe que passamos dois valores como parâmetro para random. Tais valores são interpretados como o valor mínimo e máximo e o número escolhido estará na faixa [mínimo, máximo]. Note que após o retângulo sair da área da nossa tela, devemos definir as posições novamente, para que ele volte a aparecer no começo da tela.
Nesse exemplo também fazemos uso do parâmetro ângulo que define um ângulo de rotação para o retângulo. Como o ângulo varia, o retângulo gira enquanto desliza pela tela.
#include "sfml.h"
#include "util.h"
using namespace util;
int main() {
SFML sfml(640,480,"Meu jogo!");
sfml.background(0,0,0);
int xo = -random(0,640);
int yo = random(0,480);
int angle = 0;
while (sfml.windowIsOpen()) {
sfml.clear();
xo += 3;
if(xo > 640) {
xo = -random(0,640);
yo = random(0,480);
}
sfml.rect(xo,yo,40,40, angle);
angle = (angle+2)%360;
sfml.display();
}
return 0;
}
Introduziremos agora o conceito de variáveis de estado. Utilizar variáveis de estado é muito útil para quando precisamos que algo aconteça no programa somente quando alguma outra ação estiver sendo realizada. Por exemplo, você só poderá fazer provas de C2 enquanto a variável "cursando C2" estiver ativada, uma vez que essa variável seja desligada você não poderá mais fazer provas de C2 a não ser que "cursando C2" seja ligada novamente ('-'). Para criar uma variável de estado utilizamos as variáveis booleanas, pois estas possuem dois estados, true e false, que são usados para representar ligado e desligado.
Vejamos um exemplo prático dessas variáveis de estado.
#include "sfml.h"
#include "util.h"
using namespace util;
int main() {
SFML sfml(640,480,"Meu jogo!");
sfml.background(0,0,0);
int yo = random(0,480);
int xo = 70;
bool podeMudar = true;
while (sfml.windowIsOpen()) {
sfml.clear();
if(!podeMudar){
xo += 5;
}
if(xo > 660){
podeMudar = true;
}
if(sfml.mouseLeftButtonIsPressed() && podeMudar) {
yo = random(0,480);
xo = 15;
podeMudar = false;
}
sfml.rect(xo,yo,40,40);
sfml.display();
}
return 0;
}
Aqui a variável de estado é podeMudar. O programa funciona da seguinte forma: quando o mouse é clicado, uma posição é definida para o retângulo que logo então começará a andar para a direita. Uma vez em movimento, o clique do mouse não conseguirá mais mudar sua posição até que ele saia da área da tela. Assim, quando o retângulo estiver fora de vista, podeMudar é se torna verdadeira e a posição poderá ser alterada com um clique do mouse. O retângulo então entra mais uma vez em movimento e podeMudar se torna falsa. Com isso o clique do mouse não funcionará até que o retângulo saia de vista novamente.
Em alguns casos, precisaremos escrever algo na nossa tela. Podemos fazer isso usando a função text(), desse modo:
#include "sfml.h"
#include <cstring>
int main() {
SFML sfml(640,480,"Meu jogo!");
sfml.background(0,0,0);
//Define o tamanho da fonte
sfml.textSize(16);
char frase[200];
int contagem = 0;
int posX = 0;
int posY = 200;
while (sfml.windowIsOpen()) {
sfml.clear();
//cria a frase que será desenhada no vetor de caracteres frase.
sprintf(frase,"Já passaram %d bolas",contagem);
//escreve a frase na tela
sfml.text(frase, 250, 15);
if (posX < 640){
posX = posX + 5;
}else{
contagem++;
posX = 0;
}
sfml.ellipse(posX, posY, 50, 50);
sfml.display();
}
return 0;
}
O resultado do código acima é mostrado na figura abaixo.
Outra função bastante utilizada é a dist(x1, y1, x2, y2) da biblioteca util.h, que retorna a distância entre duas posições informadas. Podemos utilizá-la de diversas formas, veremos um exemplo aqui.
#include "sfml.h"
#include "util.h"
#include <cstring>
using namespace util;
int main() {
SFML sfml(640,480,"Meu jogo!");
sfml.background(200,200,200);
sfml.fill(0,0,0);
sfml.textSize(18);
int x1 = 10;
int y1 = 90;
char frase[100];
while (sfml.windowIsOpen()) {
sfml.clear();
int x2 = sfml.mouseX();
int y2 = sfml.mouseY();
sfml.line(x1, y1, x2, y2);
sfml.ellipse(x1-4, y1-4, 8, 8);
sfml.ellipse(x2-4, y2-4, 8, 8);
//calcula a distância entre os pontos (x1,y1) e (x2,y2)
int d = dist(x1+4, y1+4, x2+4, y2+4);
sprintf(frase,"A distância entre os pontos é %d pixels.",d);
sfml.text(frase, 80, 400);
sfml.display();
}
return 0;
}
Saída:
A detecção de colisão está presente em boa parte dos jogos. Através dela objetos ou personagens podem interagir. Podemos usar a função dist(x1,y1,x2,y2) para detectar colisão entre objetos. Veja o exemplo abaixo.
#include "sfml.h"
#include "util.h"
using namespace util;
int main() {
SFML sfml(640,480,"Meu jogo!");
sfml.background(0,0,0);
float xplayer = 100;
float yplayer = 100;
int xenemy = -random(0,640);
int yenemy = random(0,480);
float speed = 5;
while (sfml.windowIsOpen()) {
sfml.clear();
bool isColliding = (dist(xplayer+25,yplayer+25,xenemy+25,yenemy+25) < 25+25) ? true : false;
if(!isColliding) {
xenemy += 1;
} else {
sfml.text("Colidiu!",10,10);
}
if(xenemy > 640) {
xenemy = -random(0,640);
yenemy = random(0,480);
}
if (sfml.keyIsDown(SFML::Key::Left)) {
xplayer-=speed;
} else if (sfml.keyIsDown(SFML::Key::Right)) {
xplayer+=speed;
} else if (sfml.keyIsDown(SFML::Key::Up)) {
yplayer-=speed;
} else if (sfml.keyIsDown(SFML::Key::Down)) {
yplayer+=speed;
}
sfml.ellipse(xplayer, yplayer, 50, 50);
sfml.rect(xenemy, yenemy, 50, 50);
sfml.display();
}
return 0;
}
No código acima, o jogador movimenta o círculo usando as setas direcionais do teclado. Caso o círculo se aproxime do retângulo, de modo que a distância seja menor do que a soma do raio do círculo mais metade da largura do retângulo, o retângulo para de se mover e é mostrada a mensagem "Colidiu!" no top esquerdo da tela, conforme mostra imagem abaixo.
A arte de um jogo é um fator diferencial para seu sucesso. Usando imagens podemos criar jogos mais bonitos e apelativos. Vamos aprender como desenhar imagens agora? Veja o código abaixo e note como é simples.
#include "sfml.h"
int main() {
SFML sfml(640,480,"Meu jogo!");
sfml.background(0,0,0);
Image image("zelda.png");
while (sfml.windowIsOpen()) {
sfml.clear();
sfml.image(image,320-125,240-125);
sfml.display();
}
return 0;
}
Nesse código, a linha Image image("zelda.png")
carrega uma imagem que está no mesmo diretório o projeto. No laço principal do jogo, desenhamos a imagem no centro da tela.
Além de imagens estáticas como a do exemplo anterior, é comum em jogos o uso de animações. Uma animação consiste no desenho de várias imagens em sequência, dando a impressão de ação/movimento. Também podemos implementar animação imprimindo partes de uma imagem maior. O código abaixo usa essa técnica. Veja.
#include "sfml.h"
int main() {
SFML sfml(640,480,"Meu jogo!");
sfml.background(0,0,0);
Image image("background.png");
int x = 0;
while (sfml.windowIsOpen()) {
sfml.clear();
sfml.image(image,0,0,x,0,640,480);
x = (x+1)%1280;
sfml.display();
}
return 0;
}
O programa acima carrega a imagem "background.png", cujas dimensões são 1920x480. Perceba que a altura é igual a altura da nossa tela e a largura é o triplo da largura da tela. Veja na imagem abaixo que o último terço da imagem backgroung.png (destacado e azul) é exatamente igual ao primeiro terço (destacado em vermelho). Assim, na linha sfml.image(image,0,0,x,0,640,480)
o programa vai fazendo recortes de tamanho 640x480 variando o início do recorte em x=0 até x=1280. Quando x atinge 1281, estamos no caso em que o recorte será exatamente igual ao primeiro terço da imagem. Assim podemos fazer x=0 novamente e começar o processo novamente. Chamamos esse efeito de scrolling.
Outra técnica de animação utiliza sprites: uma imagem divida em partes iguais, onde cada parte é uma fotografia diferente do mesmo objeto. Abaixo temos um exemplo de sprite que representa uma animação de uma explosão.
Essa imagem tem tamanho 900x900. Cada subimagem tem tamanho 100x100. Quando o usuário clica em alguma posição da tela, o código abaixo faz recortes dos sprites, da esquerda para a direta, de cima para baixo e os desenha na tela.
#include "sfml.h"
int main() {
SFML sfml(640,480,"Meu jogo!");
sfml.background(0,0,0);
Image image("explosion-sprite.png");
bool animating = false;
int i = 0;
int x, y;
int w = 100; //largura do objeto no sprite
int h = 100; //altura do objeto no sprite
while (sfml.windowIsOpen()) {
sfml.clear();
if(sfml.mouseLeftButtonIsPressed() && !animating) {
animating = true;
x = sfml.mouseX();
y = sfml.mouseY();
}
if(animating) {
sfml.image(image,x-w/2,y-h/2,(i%9)*w,(i/9)*h,w,h);
i++;
if(i == 81) {
animating = false;
i = 0;
}
}
sfml.display();
}
return 0;
}
Os recursos de áudio trazem mais emoção aos jogos. Tocar um áudio com a nossa biblioteca é fácil. Vamos adaptar o código anterior para tocar um áudio sempre que a animação da explosão iniciar. Veja o código adaptado abaio.
#include "sfml.h"
int main() {
SFML sfml(640,480,"Meu jogo!");
sfml.background(0,0,0);
Image image("explosion-sprite.png");
Sound sound("explosion.wav");
bool animating = false;
int i = 0;
int x, y;
int w = 100; //largura do objeto no sprite
int h = 100; //altura do objeto no sprite
while (sfml.windowIsOpen()) {
sfml.clear();
if(sfml.mouseLeftButtonIsPressed() && !animating) {
sound.play();
animating = true;
x = sfml.mouseX();
y = sfml.mouseY();
}
if(animating) {
sfml.image(image,x-w/2,y-h/2,(i%9)*w,(i/9)*h,w,h);
i++;
if(i == 81) {
animating = false;
i = 0;
}
}
sfml.display();
}
return 0;
}
Em jogos de plataforma é comum que o personagem salte. O código abaixo simula um salto quando o usuário aperta a seta para cima do teclado. Para tal usa-se a equação do espaço do lançamento vertical.
#include "sfml.h"
int main() {
SFML sfml(640,480,"Meu jogo!");
sfml.background(0,0,0);
float x = 100;
float y = 400;
bool saltando = false;
float speed = 5;
float t = 0; //tempo de duração do lançamento
int vy0 = 55; //velocidade inicial no lançamento vertical
int y0 = 400; //posição inicial no lançamento vertical. corresponde ao chão
int g = 9.8; //força da gravidade no lançamento vertical
while (sfml.windowIsOpen()) {
sfml.clear();
if (sfml.keyIsDown(SFML::Key::Left)) {
x-=speed;
} else if (sfml.keyIsDown(SFML::Key::Right)) {
x+=speed;
} else if (sfml.keyIsDown(SFML::Key::Up) && !saltando) {
saltando = true;
t = 0;
}
if(saltando) {
y = y0 - vy0*t + (g*t*t)/2.0; //atualiza y segundo a equação do lançamento vertical
if(y > y0) { // verifica se y já atingiu o chão. se atingiu o chão, o salto acabou
y = y0;
saltando = false;
}
t += 0.1;
}
sfml.line(0,450,640,450);
sfml.ellipse(x, y, 50, 50);
sfml.display();
}
return 0;
}
O lançamento de objetos ou projéteis é importante na maioria dos jogos. O código abaixo apresenta uma das formas de implementar o efeito de tiro ao apertar a tecla barra de espaço. A função sfml.convexPolygon(x,y,pontos,qtdPontos)
desenha um polígolo convexo definidos pelo vetor pontos
, centrado em (x,y).
#include "sfml.h"
#include<cmath>
struct Coordenada {
int x, y;
};
struct Nave {
Coordenada c;
bool atirando;
};
struct Tiro {
Coordenada c;
};
void desenhaNave(SFML& sfml, Nave nave) {
int points[][2] = {
{20,40},{0,-20},{-20,40},{0,20}
};
sfml.convexPolygon(nave.c.x,nave.c.y,points,4);
}
int main() {
//cria a janela com tamanho 640x480 pixels
SFML sfml(640,480,"Meu jogo!");
//define a cor de fundo como preto
sfml.background(0,0,0);
Nave nave;
nave.c.x = 320;
nave.c.y = 430;
nave.atirando = false;
Tiro tiro;
//início do laço principal do jogo
while (sfml.windowIsOpen()) {
//apaga o conteúdo da janela
sfml.clear();
//Desenha uma ellipse no centro da tela
if(sfml.keyIsDown(SFML::Key::Left)) {
nave.c.x -= 2;
}
else if(sfml.keyIsDown(SFML::Key::Right)) {
nave.c.x += 2;
}
else if(sfml.keyIsDown(SFML::Key::Space)) {
if(!nave.atirando) {
nave.atirando = true;
tiro.c.x = nave.c.x-2;
tiro.c.y = nave.c.y-2;
}
}
desenhaNave(sfml,nave);
if(nave.atirando) {
sfml.ellipse(tiro.c.x, tiro.c.y,4,4);
tiro.c.y -= 2;
if(tiro.c.y < 0-10) {
nave.atirando = false;
}
}
sfml.display();
}
return 0;
}
A maioria dos jogos usa algum tipo de persistência de dados para salvar o progresso ou pontuação de um jogo. O exemplo abaixo usa o biblioteca fstream da linguagem c++ para salvar o número de defesas feitas ao decorrer do jogo. Ao fechar e reabrir o jogo, a quantidade de defesas é recuperada do arquivo e mostrada no topo da tela.
#include "sfml.h"
#include "util.h"
#include <fstream>
using namespace util;
using namespace std;
struct coord {
int x, y;
};
int main() {
SFML sfml(640,480,"Meu jogo!");
sfml.background(0,0,0);
coord goleiro = {40,480/2};
coord bola = {800,480/2};
int velocidadeGoleiro = 5;
int velocidadeBola = 3;
int score;
char str[200];
ifstream in("defesas.txt",std::ifstream::in);
if(in.is_open()) {
in >> score;
} else {
score = 0;
}
while (sfml.windowIsOpen()) {
sfml.clear();
if (sfml.keyIsDown(SFML::Key::Up)) {
goleiro.y-=velocidadeGoleiro;
if(goleiro.y < 60) {
goleiro.y = 60;
}
} else if (sfml.keyIsDown(SFML::Key::Down)) {
goleiro.y+=velocidadeGoleiro;
if(goleiro.y > 410) {
goleiro.y = 410;
}
}
bola.x -= velocidadeBola;
bool isColliding = (dist(goleiro.x+25,goleiro.y+25,bola.x+10,bola.y+10) < 25+10) ? true : false;
if(isColliding) {
score++;
bola.x = random(640,1.5*640);
bola.y = random(60,380);
} else if(bola.x < 0) {
bola.x = random(640,1.5*640);
bola.y = random(60,380);
}
sprintf(str,"Defesas: %d",score);
sfml.line(0,40,640,40);
sfml.ellipse(goleiro.x, goleiro.y, 50, 50);
sfml.ellipse(bola.x, bola.y, 20, 20);
sfml.rect(20,60,10,400);
sfml.text(str,10,10);
sfml.display();
}
ofstream out("defesas.txt",std::ofstream::out);
out << score;
out.close();
return 0;
}
Nesse tutorial aprendemos a usar uma biblioteca de desenvolvimento de jogos simples que abstrai alguns recursos da biblioteca SFML. Agora você já possui habilidades básicas necessárias para desenvolver seu próprio jogo. Bons estudos.