- SFML Game Development By Example
- Raimondas Pupius
- 617字
- 2021-07-23 14:55:05
Building the game class
We've done a good job at wrapping up the basic functionality of our window class, but that's not the only chunk of code in need of refactoring. In Chapter 1, It's Alive! It's Alive! – Setup and First Program, we've discussed the main game loop and its contents, mainly processing input, updating the game world and the player, and finally, rendering everything on screen. Cramming all of that functionality into the game loop alone is generally known to produce spaghetti code, and since we want to move away from that, let's consider a better structure that would allow this kind of behavior:
#include "Game.h" void main(int argc, void** argv[]){ // Program entry point. Game game; // Creating our game object. while(!game.GetWindow()->IsDone()){ // Game loop. game.HandleInput(); game.Update(); game.Render(); } }
The code above represents the entire content of our main.cpp
file and perfectly illustrates the use of a properly structured game class, which doesn't go beyond calling the proper methods in the right order in an endless loop until the window is closed. Just for the sake of clarity, let's take a look at a simplified version of the game class header:
class Game{ public: Game(); ~Game(); void HandleInput(); void Update(); void Render(); Window* GetWindow(); ... private: void MoveMushroom(); Window m_window; ... };
Note that the game class holds an instance of our window. It can be done differently, but for our current needs this will more than suffice.
Putting our code to work
We're now ready to re-implement the bouncing mushroom demo from Chapter 1, It's Alive! It's Alive! – Setup and First Program. Given how simple it is, we'll walk you through the entire process of adapting our previously written code to our new structure. Let's begin by setting up our window and graphics we'll be using:
Game::Game(): m_window("Chapter 2", sf::Vector2u(800,600)){ // Setting up class members. m_mushroomTexture.loadFromFile("Mushroom.png"); m_mushroom.setTexture(m_mushroomTexture); m_increment = sf::Vector2i(4,4); }
Because we have nothing to clean up, our game destructor will remain empty for now:
Game::~Game(){}
We have no need to check for input for this example, so let's leave that method alone for now. What we will be doing, however, is updating the position of our sprite each frame:
void Game::Update(){ m_window.Update(); // Update window events. MoveMushroom(); } void Game::MoveMushroom(){ sf::Vector2u l_windSize = m_window.GetWindowSize(); sf::Vector2u l_textSize = m_mushroomTexture.getSize(); if((m_mushroom.getPosition().x > l_windSize.x - l_textSize.x&&m_increment.x> 0) || (m_mushroom.getPosition().x < 0 &&m_increment.x< 0)){ m_increment.x = -m_increment.x; } if((m_mushroom.getPosition().y > l_windSize.y - l_textSize.y&&m_increment.y> 0) || (m_mushroom.getPosition().y < 0 &&m_increment.y< 0)){ m_increment.y = -m_increment.y; } m_mushroom.setPosition( m_mushroom.getPosition().x + m_increment.x, m_mushroom.getPosition().y + m_increment.y); }
Literally the first thing you'll probably notice is the update method call of our window class. We've already covered the importance of event processing in SFML, but it's still worthy to note that one more time. The rest of the code is pretty much the same, except we now have a separate method that is responsible for updating the position of the mushroom sprite. We used two local variables to hold the window and texture sizes in order to increase readability, but that's about it. Time to draw our sprite to the screen:
void Game::Render(){ m_window.BeginDraw(); // Clear. m_window.Draw(m_mushroom); m_window.EndDraw(); // Display. }
Once again, the code is fairly straight forward. Our window class does all the work, and all we have to do is call the Draw
method and pass in our sf::Drawable
right in between the wrapper methods for clearing the screen and displaying the changes.
Putting everything together and running it should produce the exact same bouncing mushroom we had back in Chapter 1, It's Alive! It's Alive! – Setup and First Program. However, you may have noticed that the sprite moves differently based on how busy your computer is. In this observation lies an important lesson about game development.
- 復(fù)雜軟件設(shè)計(jì)之道:領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)全面解析與實(shí)戰(zhàn)
- Rust實(shí)戰(zhàn)
- Designing Hyper-V Solutions
- Android NDK Beginner’s Guide
- Linux操作系統(tǒng)基礎(chǔ)案例教程
- C++新經(jīng)典
- Visual Foxpro 9.0數(shù)據(jù)庫(kù)程序設(shè)計(jì)教程
- Test-Driven Machine Learning
- QGIS Python Programming Cookbook(Second Edition)
- Python計(jì)算機(jī)視覺和自然語(yǔ)言處理
- iOS開發(fā)項(xiàng)目化入門教程
- Appcelerator Titanium:Patterns and Best Practices
- HTML5移動(dòng)Web開發(fā)
- XML程序設(shè)計(jì)(第二版)
- TypeScript全棧開發(fā)