Skip to content

Commit 2e6948f

Browse files
authored
Merge pull request #4 from mrdcvlsc/GameClass
Implemented a Game Class
2 parents d883210 + 0d81720 commit 2e6948f

File tree

14 files changed

+277
-221
lines changed

14 files changed

+277
-221
lines changed

src/bird.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
#include <SFML/Graphics/RectangleShape.hpp>
2-
#include <chrono>
3-
#include <ctime>
4-
5-
#include <SFML/Graphics/CircleShape.hpp>
62
#include <SFML/Graphics/Color.hpp>
73

84
#include "bird.hpp"

src/bird.hpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
#ifndef MRDCVLSC_BIRD_HPP
22
#define MRDCVLSC_BIRD_HPP
33

4-
#include <iostream>
5-
#include <algorithm>
6-
#include <chrono>
7-
#include <random>
84
#include <vector>
5+
#include <algorithm>
96

10-
#include <SFML/System/Vector2.hpp>
117
#include <SFML/Graphics/Drawable.hpp>
128
#include <SFML/Graphics/RenderTarget.hpp>
139
#include <SFML/Graphics/RectangleShape.hpp>
10+
#include <SFML/System/Vector2.hpp>
1411

1512
#include "config.hpp"
1613
#include "ffnn.hpp"

src/collision.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
#include <iostream>
2-
31
#include <SFML/Graphics/Rect.hpp>
4-
#include <SFML/System/Vector2.hpp>
52

63
#include "config.hpp"
74
#include "collision.hpp"

src/config.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <random>
66

77
#include <cstddef>
8+
#include <cstdint>
89
#include <cinttypes>
910

1011
static constexpr float VIEW_MOVE_DISTANCE = 2.f;

src/ffnn.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
#include <ios>
2-
#include <fstream>
3-
#include <array>
42

53
#include "ffnn.hpp"
64

src/ffnn.hpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,7 @@
33

44
#include <iostream>
55
#include <fstream>
6-
#include <chrono>
7-
#include <random>
86

9-
#include <stddef.h>
10-
11-
#include <cinttypes>
127
#include <cmath>
138

149
#include <Eigen/Core>

src/game.cpp

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
#include <string>
2+
#include <sstream>
3+
#include <iomanip>
4+
5+
#include <cmath>
6+
7+
#include <SFML/Graphics/Rect.hpp>
8+
#include <SFML/Graphics/View.hpp>
9+
#include <SFML/System/Clock.hpp>
10+
#include <SFML/System/Time.hpp>
11+
#include <SFML/Window/Event.hpp>
12+
13+
#include "game.hpp"
14+
15+
std::string lpad(std::string const &raw, char fillchar, size_t width)
16+
{
17+
static std::ostringstream ss;
18+
ss << std::right << std::setfill(fillchar) << std::setw(width) << raw;
19+
std::string padded = ss.str();
20+
ss.str(std::string());
21+
ss.clear();
22+
return padded;
23+
}
24+
25+
Game::Game(std::vector<std::string> const &args, size_t width, size_t height, std::string const &title, size_t fps) :
26+
window(sf::VideoMode(width, height), title),
27+
game_area({static_cast<float>(width), static_cast<float>(height)}),
28+
background(19, 235, 220),
29+
timePerFrame(sf::seconds(1.f / static_cast<float>(fps))),
30+
captured_frames(0),
31+
capture_frames(false),
32+
game_statistics(std::make_shared<GameStats>()),
33+
player_bird(),
34+
birds(),
35+
pipes(),
36+
genetic_algorithm()
37+
{
38+
// check CLI argument if there is a capture flag
39+
if (args.size() == 2) {
40+
if (std::string(args[1]) == "capture") {
41+
std::cerr << "frame capture flag enabled\n";
42+
capture_frames = true;
43+
capture_texture.create(width, height);
44+
}
45+
}
46+
47+
// initial window and view configuration.
48+
sf::View view(sf::FloatRect(0.f, 0.f, width, height));
49+
window.setView(view);
50+
window.setFramerateLimit(fps);
51+
52+
// initialize game area.
53+
game_area.setFillColor(sf::Color(0, 0, 0, 0));
54+
game_area.setOutlineColor(sf::Color::Black);
55+
game_area.setOutlineThickness(2.f);
56+
57+
// initialize player bird game color.
58+
player_bird.setOutlineColor(sf::Color::Red);
59+
player_bird.setFillColor(sf::Color::Yellow);
60+
61+
// load the previous fittest network.
62+
if (!birds.collection[0].neural_net.load_network("fittest.nn")) {
63+
std::cerr << "error loading the fittest network\n";
64+
} else {
65+
std::cerr << "the previous fittests network is loaded\n";
66+
}
67+
}
68+
69+
void Game::process_events()
70+
{
71+
sf::Event event;
72+
while (window.pollEvent(event)) {
73+
if (event.type == sf::Event::Closed) {
74+
genetic_algorithm.rank_fitness(birds);
75+
76+
if (birds.collection[0].neural_net.save_network("fittest.nn")) {
77+
std::cerr << "fittest network saved\n";
78+
} else {
79+
std::cerr << "failed to save the fittest network\n";
80+
}
81+
82+
window.close();
83+
}
84+
85+
if (event.type == sf::Event::KeyPressed) {
86+
auto game_view = window.getView();
87+
88+
// cam up
89+
if (event.key.scancode == sf::Keyboard::Scan::Up) {
90+
game_view.move(0.f, -VIEW_MOVE_DISTANCE);
91+
window.setView(game_view);
92+
}
93+
94+
// cam down
95+
if (event.key.scancode == sf::Keyboard::Scan::Down) {
96+
game_view.move(0.f, VIEW_MOVE_DISTANCE);
97+
window.setView(game_view);
98+
}
99+
100+
// cam left
101+
if (event.key.scancode == sf::Keyboard::Scan::Left) {
102+
game_view.move(-VIEW_MOVE_DISTANCE, 0.f);
103+
window.setView(game_view);
104+
}
105+
106+
// cam right
107+
if (event.key.scancode == sf::Keyboard::Scan::Right) {
108+
game_view.move(VIEW_MOVE_DISTANCE, 0.f);
109+
window.setView(game_view);
110+
}
111+
112+
// zoom in cam
113+
if (event.key.scancode == sf::Keyboard::Scan::Equal) {
114+
game_view.zoom(0.99f);
115+
window.setView(game_view);
116+
}
117+
118+
// zoom out cam
119+
if (event.key.scancode == sf::Keyboard::Scan::Hyphen) {
120+
game_view.zoom(1.01f);
121+
window.setView(game_view);
122+
}
123+
124+
// bird jumps
125+
if (event.key.scancode == sf::Keyboard::Scan::Space) {
126+
player_bird.jump();
127+
}
128+
}
129+
}
130+
131+
genetic_algorithm.get_inputs(birds, pipes);
132+
}
133+
134+
void Game::run()
135+
{
136+
sf::Clock clock;
137+
sf::Time timeSinceLastUpdate = sf::Time::Zero;
138+
while (window.isOpen()) {
139+
process_events();
140+
timeSinceLastUpdate += clock.restart();
141+
while (timeSinceLastUpdate > timePerFrame) {
142+
timeSinceLastUpdate -= timePerFrame;
143+
144+
// in the sfml book the also put another `process_events` call here, IDK if removing it
145+
// will have an effect in the game.
146+
// process_events()
147+
148+
update(timePerFrame);
149+
}
150+
render();
151+
end_of_frame();
152+
}
153+
}
154+
155+
void Game::update(sf::Time const &dt)
156+
{
157+
pipes.update(dt.asSeconds());
158+
birds.update(dt.asSeconds());
159+
player_bird.update(dt.asSeconds());
160+
161+
game_statistics->record_deaths(birds_collisions(birds, pipes));
162+
bird_collision(player_bird, pipes);
163+
}
164+
165+
void Game::render()
166+
{
167+
window.clear(background);
168+
169+
window.draw(game_area);
170+
window.draw(birds);
171+
172+
if (!player_bird.dead) {
173+
window.draw(player_bird);
174+
}
175+
176+
window.draw(pipes);
177+
window.draw(*game_statistics);
178+
179+
window.display();
180+
}
181+
182+
void Game::end_of_frame()
183+
{
184+
if (capture_frames) {
185+
capture_texture.update(window);
186+
capture_texture.copyToImage().saveToFile(
187+
"flappy-ffnn-ga-frame-" + lpad(std::to_string(captured_frames++), '0', 6) + ".jpg"
188+
);
189+
}
190+
191+
if (birds.population == 0ULL && player_bird.dead) {
192+
genetic_algorithm.rank_fitness(birds);
193+
194+
if (birds.collection[0].neural_net.save_network("fittest.nn")) {
195+
std::cerr << "fittest network saved\n";
196+
} else {
197+
std::cerr << "failed to save the fittest network\n";
198+
}
199+
200+
genetic_algorithm.apply_mutations(birds);
201+
202+
game_statistics->new_generation();
203+
pipes.reset();
204+
birds.reset();
205+
player_bird.reset();
206+
}
207+
208+
game_statistics->update();
209+
}

src/game.hpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#ifndef MRDCVLSC_GAME_HPP
2+
#define MRDCVLSC_GAME_HPP
3+
4+
#include <memory>
5+
6+
#include <SFML/Graphics/RenderWindow.hpp>
7+
#include <SFML/Graphics/Texture.hpp>
8+
#include <SFML/Window/VideoMode.hpp>
9+
10+
#include "config.hpp"
11+
#include "bird.hpp"
12+
#include "pipe.hpp"
13+
#include "gamestats.hpp"
14+
#include "collision.hpp"
15+
#include "genetic_algo.hpp"
16+
17+
std::string lpad(std::string const &raw, char fillchar, size_t width);
18+
19+
class Game
20+
{
21+
public:
22+
23+
Game(std::vector<std::string> const &args, size_t width, size_t height, std::string const &title, size_t fps = 60);
24+
25+
// uses fixed time steps.
26+
void run();
27+
28+
private:
29+
30+
void process_events();
31+
void update(sf::Time const &dt);
32+
void render();
33+
void end_of_frame();
34+
35+
private:
36+
37+
sf::RenderWindow window;
38+
sf::RectangleShape game_area;
39+
sf::Color background;
40+
sf::Texture capture_texture;
41+
sf::Time timePerFrame;
42+
size_t captured_frames;
43+
bool capture_frames;
44+
45+
// game entities
46+
std::shared_ptr<GameStats> game_statistics;
47+
48+
Bird player_bird;
49+
Birds birds;
50+
Pipes pipes;
51+
GeneticAlgorithm genetic_algorithm;
52+
};
53+
54+
#endif

src/gamestats.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#include <algorithm>
21
#include <string>
32

43
#include "gamestats.hpp"

src/gamestats.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
#define MRDCVLSC_STATS_HPP
33

44
#include <SFML/Graphics/Color.hpp>
5-
#include <SFML/Graphics/Drawable.hpp>
65
#include <SFML/Graphics/Font.hpp>
7-
#include <SFML/Graphics/RenderTarget.hpp>
86
#include <SFML/Graphics/Text.hpp>
97
#include <SFML/System/Clock.hpp>
108
#include <SFML/System/Time.hpp>

0 commit comments

Comments
 (0)