项目作者: Ethan13310

项目描述 :
Epitech Project
高级语言: C++
项目地址: git://github.com/Ethan13310/Arcade-Interfaces.git
创建时间: 2018-03-10T15:29:25Z
项目社区:https://github.com/Ethan13310/Arcade-Interfaces

开源协议:

下载


Game Loop

Here we’ll create a classic game loop :

  1. We handle all events that happened during the last frame,
  2. We update the game (physics, AI, etc.),
  3. And then we draw every necessary game object into the window.

Instantiation

We instantiate both game and render window :

  1. std::unique_ptr<arcade::Game> game{ /* Game */ };
  2. std::unique_ptr<engine::Window> window{ /* Window */ };

Window creation

Then we create a window with a render resolution of 640x480px :

  1. window->create("Arcade", engine::Vector2i{ 640, 480 }, engine::RenderSettings{ 640, 480, false });

Main loop

And there’s the main loop :

  1. while (window->isOpen()) {
  2. engine::Event evt;
  3. while (window->pollEvent(evt)) {
  4. // We delegate event handling to our Game class:
  5. game->handleEvent(evt);
  6. }
  7. if (game->isRunning()) {
  8. game->update();
  9. window->clear();
  10. game->render(window);
  11. window->display();
  12. }
  13. else {
  14. // If the game has terminated, we close the window:
  15. window->close();
  16. }
  17. }

It’s a very basic game loop. You’ll have to make some changes, especially to handle render engines switches.

Drawing

In the game loop above, you surely have noticed the line game->render(window);. Here, we pass as a reference the window to the game. It makes the game able to draw its components into the window.

Implementing the Game::draw() function

There’s basically nothing much to do. We call the Window::draw() function with the object we want to render as a parameter :

  1. class Pacman : public Game
  2. {
  3. public:
  4. void draw(std::unique_ptr<engine::Window> &window) const override
  5. {
  6. window->draw(m_text);
  7. window->draw(m_sprite);
  8. // ...
  9. }
  10. private:
  11. engine::Text m_text;
  12. engine::Sprite m_sprite;
  13. // ...
  14. };

Rendering

Now, things are going to get a little bit more harder. We need to make the Window::draw() function able to render any Drawable object.

The render target

The render target is basically the engine you will use to render objects to the screen (SFML, nCurses, OpenGL, etc.) :

  1. class RenderTarget
  2. {
  3. public:
  4. virtual void drawSprite(Sprite const &sprite) = 0;
  5. // ...
  6. };
  7. class SFMLRenderer : public RenderTarget
  8. {
  9. public:
  10. void drawSprite(Sprite const &sprite) override {}
  11. // ...
  12. };

At this time, we’re able to draw Sprites into the window, using SFML. You’ll have to implement at least one function for each Drawable object you want to render.

Be careful to NOT recreate the native handle (here, the couple sf::Spirte and sf::Texture) each time you call drawSprite() ! Think of a way to avoid this, or your game will run at 5 FPS.

The render window

Now that we have implemented the render target, we need to implement the render window, which will call Drawable::draw() function to do the rendering.

A Drawable class must implement a draw() function which take as a parameter a RenderTarget. It will allow to call the right RenderTarget member function. For instance, Sprite::draw() will call RenderTarget::drawSprite().

Here’s a basic implementation of the Window::draw() function :

  1. class RenderWindow : public Window
  2. {
  3. public:
  4. void draw(Drawable const &drawable)
  5. {
  6. drawable.draw(m_renderer);
  7. }
  8. private:
  9. SFMLRenderer m_renderer;
  10. };

Implementing a Drawable class

We’re talking about Drawable classes since earlier, but let’s see how to implement their draw() member function :

  1. class Sprite : public Transformable, public Drawable
  2. {
  3. public:
  4. void draw(RenderTarget &renderer) const override
  5. {
  6. renderer.drawSprite(*this);
  7. }
  8. };

Nothing more, nothing less. Our Drawable object passes itself as a parameter to the right RenderTarget‘s member function. This function is therefore capable to draw a sprite using SFML’s native handles (sf::Sprite and sf::Texture) by retrieving all the information it needs from our Sprite class.

Highscores

Now that we have both our game and renderer functional, it would be nice if we could load and save highscores for each game we have.

Back in our game loop, we can have something like that :

  1. // Load your highscores
  2. Game::Scores scores{ /* ... */ };
  3. game->loadHighscores(scores);
  4. while (window->isOpen()) {
  5. // ...
  6. }
  7. scores = game->highscores();
  8. // Then save them

Here, Game::Scores is a std::multimap<std::uint64_t, std::string>.

Events

In order to comply with all render engines, it’s recommended to make your games fully playable (including menus) with the keyboard. Indeed, some render engines may not implement joystick or mouse handling.

Entry Point

The entry point for each library MUST BE :

  1. extern "C"
  2. {
  3. void *instantiate()
  4. {
  5. return new /* Your class */;
  6. }
  7. }

There’s no need to declare it into a .hpp file.