200 likes | 366 Views
GAME 1024: Advanced Game Programming. Lesson 2: Birth of a Program By Kain Shin. Quiz. What’s your full name What does inheritance abuse mean to you? Fill in the blank for Kain’s catchphrase: “Be a good ___ first, the ___ part will follow”
E N D
GAME 1024: Advanced Game Programming Lesson 2: Birth of a Program By Kain Shin
Quiz • What’s your full name • What does inheritance abuse mean to you? • Fill in the blank for Kain’s catchphrase: “Be a good ___ first, the ___ part will follow” • What is one good reason to have just a single global game object and no other globals? • What is a blob class? • 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 exit bool 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.