game 1024: advanced game programming lesson 2: birth of a program by kain shin
Post on 25-Dec-2015
213 Views
Preview:
TRANSCRIPT
GAME 1024: Advanced Game ProgrammingLesson 2: Birth of a Program
By Kain Shin
Quiz1. What’s your full name
2. What does inheritance abuse mean to you?
3. Fill in the blank for Kain’s catchphrase: “Be a good ___ first, the ___ part will follow”
4. What is one good reason to have just a single global game object and no other globals?
5. What is a blob class?
6. What is one thing you can do to make the formation of a blob class less likely?
Bonus C++ Topic: Inheritance Abuse Makes code harder to manage Results in a lot of copy-and-paste implementation Propagates the chance of error to anything that gets affected
by the copy-and-paste mentality Solutions:
Keep class hierarchies flat and wide instead of tall and thin Use abstract interface classes with pure virtual functions Composition: Make member variables generic in nature … i.e.
GetItem(id) instead of GetPants() Composition: Consider encapsulating algorithms into member
variables that can be changed instead of a virtual function that is burned into code… i.e. GetAIBehavior() instead of DoAI()
Version Control Why Use Version Control?
History! Concurrent editing and merge conflicts Branches
What are our choices? Alienbrain, CVS, Perforce, and lots more SourceSafe sucks! Even Microsoft doesn’t use it! Perforce is the most likely one you’ll see at work. Atomic
check-ins rock! Make sure it runs before you check it in, or else, you’ll keep
other programmers from working!
More About Perforce Go to http://perforce.com and download Perforce on your
home machine. It’s free for up to two users! Use it with your class project! After two users, Perforce costs about $800 per user per year,
but that more than pays for itself in programmer time saved at work
Programmer time is saved because Perforce does atomic check-ins, meaning if any file in a group does not merge well, then none of those files get checked in
Perforce stores the history of ascii files as deltas to save storage space
Useful Programming Utilities Standard Template Library – for holding a map and list of
objects STLPort (http://stlport.org) is an excellent
implementation that includes hash_map, unlike Microsoft’s current implementation
std::map and std::list could be very useful for your class project
Boost (http://boost.org) – handy library of utilities smart pointers ward off memory leaks – boost::shared_ptr
Engine/Game Separation You want to separate game code from Engine code
because a studio’s chance of survival increases if they can easily reuse tech. Programmer time is one of the most expensive resources.
If you want to hide source code for a lib, then you provide only .h files in a folder and none of the cpp files because the lib takes care of that part. Middleware providers will do this.
Reuseable Code that is not game-specific should go in the engine
Organizing your files into a good directory structure Deliverable – should be a self-contained directory to run from
Contains data and exe This directory is what you send to non-programmers
Code – Everything in it should be static and not have temp files written to it when compiling The root of code should contain the sln file, but each vcproj file should
live in its own folder. This will make it easy to cleanly move projects around by folder to other games, such as the engine lib project
Game code, engine code, and thirdParty code all cleanly separated from each other
Temp – obj files and other temporary files are written here. Delete this directory for a clean build
Manager Class Definition A Manager is a class that manages some
meaningful encapsulated system in the game such as graphics, audio, physics, input, or AI
Kain wants you to make your manager classes public member variables of the singleton game class
Actor Class Definition An actor is a collection of manifestations from
various game managers (physics, graphics, sound, etc.) that represent a single dynamic entity within the game
An actor could be an animating character or it could be a rock that has some gameplay value
Games do their logic on actors The actor can be implemented as a class with
pointers to its representation within each manager class, such as a sound resource, graphics sprite, or physics object
The Event System Definition: A system intended to allow communication
between separate game systems that can essentially be unaware of each other.
Reasons for an event system: To allow concurrent development on different game systems by
different programmers without stepping on each other’s toes Decouples the “things happening” from the “things that react to those
happenings”… so a programmer can announce the event without worrying about reactions to that announcement
Make a codebase much more ready for online/network implementation
Analogous to the client/server model of computing, except this is inside one app instead of multiple computers on a shared network
Event System Details class cEventManager – the central hub. Analogous to a network server
void RegisterListener(pEventListener, eventID) void TriggerEvent(eventData)
class cEventID – unique to event type, used as a key for matching purposes. Analogous to a network packet ID Constructor: cEventID::cEventID(char*); Implicit uint conversion: operator unsigned int()const;
EventData – represents everything you’d want to know about the event, such as position or actorID. Inherit from an iEventData abstract class to make your own version of data per event cEventID& vGetID()const = 0;
class iEventListener – managers will inherit from this abstract class vHandleEvent(eventData) = 0;
*An alternate implementation of an event system is to register function pointers/functors instead of EventListener objects. The choice is yours.
Listener Analogy for Managers A manager class listens for events from the rest of
the application, and then acts on the event if it cares about the event
This is how you can easily get multiple programmers working in different areas without stepping on each other.
Doing this right should allow you to easily switch out middleware or engine tech if you ever had to (physics, graphics, sound, etc.)
Not all Managers need to be listeners. Use your judgement.
Puppet Analogy for Actors An Actor should not change state by itself unless
human or AI input changes it An actor can be thought of as an inert puppet whose
strings are being pulled by an “ActorController” class
This example of composition has two benefits Easy to switch out the controller of any actor to be either
AI-controlled, player-controlled, or even controlled by different types of AI
You don’t need to make a different version of the actor for human-controlled versus AI-controlled
Main.cpp suggestion Encapsulating all game functionality inside the cGame object will make it easier to port your
code to other platforms
int main(int argc, char *argv[]) {
cGame game;
bool playGame;do{
playGame = game.Update();}while( playGame );
return 1;}
Game.h Suggestion The Managers held by cGame do all the work. cGame itself does nothing except channel updates into managers
class cGame{public:
static cGame* GetInstance(){
assert(NULL!=s_pInstance && "a cGame object has not been created yet");return s_pInstance;
}
cGame();~cGame();
//returns false when it is time to exitbool Update();
//public globals...class cActorManager* m_pActorManager;class cAudioManager* m_pAudioManager;class cGraphicsManager* m_pGraphicsManager;class cInputManager* m_pInputManager;
private:static cGame* s_pInstance;
Other Classes You’ll Be Writing… cActorManager – holds an associative container of
cActor objects cActorController – the puppetmaster to your cActor cActor – manages a cActorController that can be
switched out during gameplay. Won’t do anything unless its controller tells it to
cInputManager – translates raw keys into game actions that will get sent out as events, also allows input actions to be polled for any logic done inside Update()
class cActor Suggestions Remember that an actor merely represents a conglomeration of the separate pieces from each game
system such as sound, graphics, and AI There is no reason to have an update function for the cActor class unless the actor is animating in some
way (advance frames in the update). Game logic that makes the actor do variable things should be handled by the puppetmaster of the cActor class, a.k.a. cActorController.
You can have useful queries in this cActor class such as “Is this xy coordinate inside my bounding box?” A cActor object is only borrowing the representations from other systems, such as GraphicsManager. It
does not actually own those representations. Graphics objects continue to live inside GraphicsManager so that GraphicsManager can draw its own collection of graphics objects. The cActor will manipulate the state of its borrowed graphics object as it sees fit. The idea is to architect your cActor class so that all game logic can take place even if there was no graphics system… or sound system… or physics system… etc.
cActor::cActor( ??? ){
m_pGraphicsObject = cGame::GetInstance()->m_pGraphicsManager->CreateGraphicsObject( ??? )m_pSound = cGame::GetInstance()->m_pAudioManager->CreateSoundBuffer( ??? )…
}
You Know Enough To Begin… An Event System that will serve as the
cornerstone of communication between separate game systems
An Actor system that creates actors and gives them life in your simulation
A Manager Class for every system you intend to make for this project. Make managers only as needed.
Afterthoughts… “There is no Silver Bullet” and “No plan survives contact with the
enemy” What you learn in this class are general guidelines and rules of thumb
to keep in mind as you grind through the chaos of actual development in the real world
Your best weapon against chaos is your own ability to intelligently adapt to new situations as they arise
Today’s lecture frontloads as much about the class project’s architecture as possible
You will have more questions. I will expect them. Your real learning begins as soon as you start on the class project detailed in the syllabus.
top related