- SFML Game Development
- Artur Moreira Henrik Vogelius Hansson Jan Haller
- 893字
- 2021-08-13 17:11:13
Entities
An entity denotes a game element in the world. In our game, possible entities are friendly and enemy airplanes, bullets, missiles, or pickups that increase the player's strength. Entities interact with each other: enemy airplanes can fire missiles, the player's airplane may evade them, and the missiles may explode if they hit the player's plane, dealing damage to it. The player's aircraft can touch a pickup to collect it, as a result of which it gets a new ability. The possibilities are nearly unlimited, and they may occur between almost any pair of entity types.
In our code, we represent entities using the traditional approach of an entity hierarchy. We have a base class called Entity
, which contains the data and functionality that all different kinds of entities have in common. We have multiple classes that derive from Entity
, and that implement specific functionality. These derived classes could represent airplanes, projectiles (such as missiles), or pickups. One commonality between different entities is that they can move in our world with a certain velocity.
We implement the velocity attribute in the base class Entity
, so each concrete entity has it. The velocity is represented using a two-dimensional vector. In addition to the member variable, we provide the get
and set
functions to access the velocity from outside the class. The setVelocity()
method is overloaded to take either a vector or two separate floats. The header Entity.hpp
contains the following class definition:
class Entity { public: void setVelocity(sf::Vector2f velocity); void setVelocity(float vx, float vy); sf::Vector2f getVelocity() const; private: sf::Vector2f mVelocity; };
After initialization, we want the velocity to be zero. Since the class sf::Vector2f
has a default constructor, which initializes the vector to a zero vector, we need not define our own constructor; the compiler-generated one works fine.
The function definitions in the file Entity.cpp
are not terribly surprising:
void Entity::setVelocity(sf::Vector2f velocity) { mVelocity = velocity; } void Entity::setVelocity(float vx, float vy) { mVelocity.x = vx; mVelocity.y = vy; } sf::Vector2f Entity::getVelocity() const { return mVelocity; }
Aircraft
Using the example of the aircraft, we need to define a concrete entity class. We derive it from Entity
. Since we have different airplanes in our game, it would be nice to have a data type that can store them. An enumeration comes in handy; we call it Type
and make it a member of the Aircraft
class. Therefore, we can now refer to it as Aircraft::Type
, which is quite expressive when we see it in the code. Up to now, we have two distinct airplanes, we call them Eagle
and Raptor
. Each type of aircraft corresponds to an enumerator in our enum.
Furthermore, we declare a constructor for the aircraft that takes its current type as parameter. We also declare a member variable for the type in the following code:
class Aircraft : public Entity { public: enum Type { Eagle, Raptor, }; public: explicit Aircraft(Type type); private: Type mType; };
The constructor's definition is straightforward; we let it initialize our mType
member variable:
Aircraft::Aircraft(Type type): mType(type) { }
Now this is the fundament for our Aircraft
class. During this book, we will continuously extend it and add new functionality.
Alternative entity designs
You should be aware that a class hierarchy is not the only option to model game entities. There are always different possibilities to design a piece of software, all of which have its own advantages and drawbacks.
The hierarchy-based approach gets to its limits when we introduce many, slightly different entity types. Imagine a complex game with different kinds of vehicles, such as tanks, ships, submarines, airplanes, and more. Every entity type has different capabilities, such as flying, transporting people, carrying weapons, and diving. It may be tempting to create corresponding base classes TransportEntity
, ArmedEntity
, DivingEntity
that all derive from Entity
. A submarine could then inherit ArmedEntity
and DivingEntity
; an armed freighter could inherit TransportEntity
and ArmedEntity
. On one hand, this design leads hand to the so-called diamond of death, where the base class Entity
is indirectly inherited multiple times, requiring virtual inheritance. On the other hand, the hierarchy becomes very deep and rigid. In order to reuse functionality for different entities, it is moved to base classes. This makes classes towards the root of the hierarchy a lot heavier than they should be. This in turn results in derived classes which inherit a lot of functions and data they never need. Eventually, objects become overly large, hence slower to process and more difficult to maintain.
In such a case, component-based design would be an alternative, meaning that abilities are aggregated as components in the single entities, instead of base classes. Each entity would then hold the abilities as members. But as you might expect, this approach is not the silver bullet, either. Components often depend more on each other than theory would like them to, and they need an efficient and flexible way to communicate with each other. While component-based approaches are certainly an option to consider for large-scale games, they are rather complex for the first game to develop. In our basic aircraft shooter, the typical problems of entity hierarchies do not show, so we chose this approach for the sake of simplicity.
If you are interested in a more detailed explanation on the topic of component-based game design, we recommend reading the article series on the following website:
- JavaScript從入門(mén)到精通(微視頻精編版)
- ASP.NET Core 5.0開(kāi)發(fā)入門(mén)與實(shí)戰(zhàn)
- 我的第一本算法書(shū)
- 21天學(xué)通C++(第6版)
- 你必須知道的204個(gè)Visual C++開(kāi)發(fā)問(wèn)題
- Unity 5 for Android Essentials
- 前端HTML+CSS修煉之道(視頻同步+直播)
- Android系統(tǒng)原理及開(kāi)發(fā)要點(diǎn)詳解
- Windows Phone 7.5:Building Location-aware Applications
- Julia for Data Science
- 區(qū)塊鏈國(guó)產(chǎn)化實(shí)踐指南:基于Fabric 2.0
- IoT Projects with Bluetooth Low Energy
- Tableau Desktop可視化高級(jí)應(yīng)用
- Mastering Embedded Linux Programming
- Deep Learning for Natural Language Processing