- SFML Game Development
- Artur Moreira Henrik Vogelius Hansson Jan Haller
- 780字
- 2021-08-13 17:11:11
A typical use case
Now we have seen what kinds of different resources there are, but we do not know yet how to apply this knowledge to our game. While the approach you have seen in Chapter 1, Making a Game Tick, may work for simple examples, it does not scale well to a bigger project. As our game grows, we have to reflect about how the resources are going to be used. This is explained in the next sections.
Graphics
In our game, a crucial part will be the visual representation of the world and different objects in it. We need to think about how we get from an image on the hard disk to its visualization on the screen.
- Game entities such as the player's airplane, enemies, or the landscape are represented with sprites and possibly texts. They do not own the heavy textures and fonts; instead they use the front-end classes to refer to them.
- As a consequence, the resources (textures and fonts) need to be accessible by the entities. We must make sure that the resource objects stay alive as long as any front-end object refers to them, so we have to find an appropriate scope to declare the resources.
- A sprite in the airplane must somehow get a reference to the texture stored outside. Therefore, we have to transport this information via constructor parameter to the airplane class.
Audio
Another important resource is audio, which can be divided into sound effects and background music. We have to consider how to make both of them audible in the final application, when all we start with is a bunch of audio files in a directory:
- Sound effects are not tied to a specific game entity such as an airplane; they persist independently of the object that causes them. Imagine an airplane that explodes and creates an explosion sound. When we destroy the plane object, we still want the explosion to be audible for some time. As a result, we do not store
sf::Sound
instances in the game entities, but in an object which remains alive throughout a mission. The same applies to the underlyingsf::SoundBuffer
objects which are used bysf::Sound
. - For music themes, the semantics are similar. It may even occur that the same theme is played across multiple missions. Ideally, the
sf::Music
objects exist in a scope that outlives a single mission. - Although the game entities do not own sound effects, they are supposed to play them. As a consequence, we shall provide an interface that allows playing new sound effects.
Acquiring, releasing, and accessing resources
Once we have decided which resources are required by the application, the next step is to investigate how long and by whom they are used. This allows us to decide how the resources are stored in the application, as well as who is responsible of loading and releasing them.
- We want to load the resource in advance, for example, at the time the game starts or the player begins a new mission. In contrast to loading on demand (as soon as a resource is needed), this approach has the advantage that possible loading times occur in the beginning and not during a game. Therefore, the game itself remains fluent and is not interrupted because of resources.
- When resources are likely to not be needed anymore, we can release them and free the memory. This is usually the case at the end of a mission or when the application is quit. We do not want to release resources too early if we risk reloading them shortly after. For example, we do not release the explosion sound buffer as soon as the sound effect is over, because the next explosion may follow a few seconds later.
- There must be a possibility to get a reference to a certain resource after it has been loaded—using a resource identifier. This identifier (ID) could be the file path as a
std::string
. This has some disadvantages: all classes that use a resource must hardcode the path, so if it changes, a lot of code needs to be refactored. Strings are also quite error-prone regarding typographic or case errors. An alternative to strings are enums, where each enumerator denotes an ID. Since an enum has a predefined set of possible states, we get some compile-time safety, and we can handle the paths in a central place.
In conclusion, we have the heavy resource classes which shall be loaded when appropriate, but before the game. Throughout their lifetime, front-end classes such as sprites or sounds may reference them, so we must keep the resources alive. When they are not needed anymore, we can release them.
- jQuery從入門到精通 (軟件開發視頻大講堂)
- Hands-On Swift 5 Microservices Development
- 從0到1:Python數據分析
- 數據結構案例教程(C/C++版)
- PHP+Ajax+jQuery網站開發項目式教程
- Django實戰:Python Web典型模塊與項目開發
- Exploring SE for Android
- Application Development with Parse using iOS SDK
- Building a Media Center with Raspberry Pi
- 企業級Java現代化:寫給開發者的云原生簡明指南
- Android應用程序設計
- JBoss AS 7 Development
- Mastering PostgreSQL 11(Second Edition)
- Access 2016數據庫應用與開發:實戰從入門到精通(視頻教學版)
- TensorFlow.NET實戰