官术网_书友最值得收藏!

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 underlying sf::SoundBuffer objects which are used by sf::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.

主站蜘蛛池模板: 汉川市| 甘泉县| 沂南县| 邯郸市| 涟水县| 阿荣旗| 潞城市| 郎溪县| 新安县| 东山县| 南漳县| 三明市| 山西省| 边坝县| 禄丰县| 含山县| 班玛县| 德庆县| 安新县| 沅陵县| 准格尔旗| 稷山县| 舟山市| 西贡区| 六枝特区| 庆云县| 房产| 河南省| 遵义县| 邢台县| 海林市| 小金县| 河曲县| 东宁县| 恭城| 婺源县| 来凤县| 大洼县| 铜陵市| 巴林右旗| 常熟市|