Professional Documents
Culture Documents
Lecture #15: Game Development: - Classes - Algorithms - Functions
Lecture #15: Game Development: - Classes - Algorithms - Functions
1
Header files Header files
• Header files should contain the minimum • Also, beware of this:
amount of code that still allows everything to
compile and to run // GameConst.h // Enemy.h
#ifndef GAMECONST_H_ #ifndef ENEMY_H_
• Move non-essential information out of the #define GAMECONST_H_ #define ENEMY_H_
header file into the implementation file
– Constants only used in the implementation, local #define GAMELEVELS 42 #include “GameConst.h”
structure definitions, etc… // … // …
• However, C++ does not provide for a very clear
#endif #endif
distinction in this
– We still need to define the private members of a class
in the header file
2
Header files Header files
// GameCamera.h
// GameCamera.h #include “GameEntity.h”
#include “GameEntity.h” class GamePlayer; // forward declaration
#include “GamePlayer.h”
class GameCamera : public GameEntity {
class GameCamera : public GameEntity { public:
public: GamePlayer* getPlayer();
GamePlayer* getPlayer(); private:
private: GamePlayer* player_;
GamePlayer* player_; };
};
// GameCamera.cpp
// GameCamera.cpp #include “GameCamera.h”
#include “GameCamera.h” #include “GamePlayer.h”
// Rest of GameCamera implementation // Rest of GameCamera implementation
// …
3
Precompiled headers The PIMPL pattern
Drawbacks: • Already following the previous guidelines
• Number of included headers grows should give you more self-sufficient
– Every file that uses the precompiled headers headers
automatically knows about all the files that are
part of the precompiled headers
• If you have many files, perhaps a
– If we add “windows.h” to the precompiled reorganization in some smaller self-
headers, possible compromise of multi- contained systems is a good idea
platform compatibility • A façade pattern can help in additional
• If we decide to compile without hiding of contents to the users
precompiled headers, greatly increased
compile time
4
The PIMPL pattern The PIMPL pattern
// GameCamera.cpp
#include “GameCamera.h” • We removed all includes related to private
#include “GamePlayer.h” implementation
#include “CameraLens.h”
#include <string>
• Reduction in dependencies between
headers
class GameCamera::PIMPL { • We have also removed all implementation
public: details from the header
CameraLens lens_;
std::string name_; • A little added complexity
GamePlayer* pPlayer_; • Minor performance cost for dynamic
};
// …
allocation and redirection
Libraries Libraries
• Class dependencies without libraries • Class dependencies with libraries
Class1 Class1
Class2
Class3
Class2
Class6 Class5
Class3 Class4
Class5
Class6 Class7
Class4
Class7
Class8
Class8
5
Libraries Configurations
• We can test each library in isolation, • We generally also compile the engine libraries
working our way from the bottom up and applications with different configuration
settings
• In-house tools can pick and choose the
– Debug configuration: no compiler optimizations, all
libraries they need debug information is included, not focused on
• It becomes easier to share already-built performance
code – Release configuration: all optimization is done, no
debug information is kept, performance is maximal,
• Separating engine and game-specific code but difficult to debug this version
becomes easier – Other configurations between these two extremes are
• We can take a modular approach to the possible (debug-optimized, different platforms…)
code
Asserts Asserts
• Check that a complicated algorithm is
working the way we expect
– “sanity check”
• Stop the program if a function fails and we
– Checking postconditions after performing the cannot recover
operations – A NULL pointer was returned when trying to
allocate some memory
void MsgQueue::processAll() {
// Do all the processing here. Maybe from – Generally the case that a major problem
// different queues, so this is not a occurs
// straightforward process
// …
6
Asserts Running the game
• When not to use asserts: • Unlike other applications, games are
– Trying to open or load a file that doesn’t exist sometimes run during 5, 10, 20 (or more!)
– Trying to load a file of the wrong format or an hours
older version – Tiny problems can become huge when not
– Entering “bad” data dealt with
– One of the objects didn’t load correctly • Difficult to trace and solve:
• Generally: anything dealing with factors – Memory leaks
exterior to the game engine should not be – Memory fragmentation
solved with asserts – Clock drift
– Error accumulation
7
Dealing with bad data Dealing with bad data
• Solution 3: A compromise
• Advantages: void Vector3D::normalize() {
– Functions become much more robust float fLength = sqrt(x*x + y*y + z*z);
#ifdef ASSERTBADDATA
– There is no need for asserts assert(fLength != 0);
• Disadvantages: #endif
if (fLength != 0) {
– By adding extra logic, performance dropped x /= fLength;
– Perhaps function was inline earlier Æ might y /= fLength;
not be possible anymore z /= fLength;
} else { // return a unit vector
– Function still returns incorrect data x = 1.0f; y = 0.0f; z = 0.0f;
}
}