chapter1_gameappframework
TRANSCRIPT
-
8/6/2019 Chapter1_GameAppFramework
1/23
-
8/6/2019 Chapter1_GameAppFramework
2/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 1
Chapter1ASimpleFrameworkforaGameApplicationMotivationNovicegamedevelopers,inspiredbythelatestgamedevelopedbyCrytekorLionheadorEA,maywanttobeginprogramminggameplaywithoutthinkingaboutthedesignandarchitectureofthe
gameapplication.Theywant toworkoncode thatmakes thegame fun!Youmightbeable to
create a simple gamewithout considering the software design; however, ifyou try to build a
complexgamebyadding features toadhoccode,youwill find that thecost todevelopanew
featureincreasesovertime1.Further,thecodewilllikelybecomemorefragile,whichcanleadto
costoverrunsandprojectfailure.WewanttoteachyouhowtousetheGamebryosystem,while
atthesametimeillustratingsomeofthedesignelementsthatyoushouldconsiderwhenbuilding
yourgame.
You
may
be
interested
in
constructing
gameplay
prototypes,
developing
a
game
as
part
of
an
academicproject,ordevelopinghighqualitycommercialgames.Inanyofthesecases,whenyou
choosetobuildyourgameusingGamebryo,youarenotchoosingtomodanexistingshrinkwrap
gamebyaddingyourowncontentandtweakingAI.Youwillbebuildingyourowncustomgame
enginefromhighquality,robustcomponentsthathavebeendesignedtoallowyoutheflexibility
thatthemodcommunitydoesnotenjoy.Thegoalofthistutorialseriesistoteachyoutodevelop
gameplay featuresusingGamebryo, thecenterpieceofyourcustomgameengine.Eachchapter
will illustrate someGamebryo feature, showingyouhow to integrate itwith thirdpartyopen
sourceprojectsandyourowncode.
Chapter 1willbegin towalkyou through thedevelopmentof someof the softwareneeded to
assembleasimplegameengineusingGamebryoandotheravailablecomponents.The textwill
describeconceptsanddocumentthedevelopmentofasmallfragmentofagamethatimplements
theconcepts.Thecodedeveloped throughout this series ismeantonly tobe illustrative, fairly
easytoreadandcomprehend.Itisnotintendedtorepresentthecurrentbestofbreedpractices
inthegameindustry.Wewillprovidewitheachchapterasetofrecommendedreferenceswhere
youcanexploreother ideas.Thegamedevelopmentcommunity isquiteopen,and it iseasyto
1Notethatthegameplayfirstapproachtogamedevelopmentcanplayan importantrole inthe
successofalargeproject,forexamplewhenusedtobuildprototypesasapartofpreproduction.SporedeveloperMaxishasincorporatedgameplayprototypingintotheirdevelopmentprocessfor
manyyears,especiallyintheearlyphasesofdevelopment,andthepopularityoftheirpriorgames
isevidencethattheirapproachissuccessful.Themodcommunitiesthatgrowoutofthefanbase
ofmanyfirstpersonshootersarealsoabletoquicklybeginworkingongameplaywithoutconcern
for software architecture, In this case, somebody else created the architecture for them, and
thoughthisenablesgameproductiontobeginquickly,theabilitytoaddnewfeaturesislimited.
-
8/6/2019 Chapter1_GameAppFramework
3/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 2
learnfromotherdevelopersbyreadingtheproceedingsoftheGameDevelopersConferenceor
otherindustryconferencesthatoccureachyeararoundtheworld.So,withthat,letusbegin!
GameasaStateMachineTheconceptofafinitestatemachineappearsinmosteverygamedesign.Itisperhapsmostoftenassociatedwith artificial intelligence (AI), thoughdevelopersdonot implementAIusing state
machines exclusively and often use state machines for algorithms other than AI. The most
fundamentaluseofthestatemachineinagamehasnothingtodowithgameAI.TheWikipedia
pageforafinitestatemachinestatesthatAfinitestatemachine(FSM)isamodelofbehavior
composed of a finite number of states, transitions between those states, and actions. This
definitionmightseemratherabstract,butitiseasytomakesenseofthis.Considerthefollowing
characteristics,gamescreensinatypicalgame:
TheopeningsplashscreenthatappearswhenyoufirstputthegameCDintotheconsoleandturntheconsoleon:thegamesbootscreen(StartupSplash)
Themain gameuser interface screen that letsyou select anumberofoptions such asbeginanewgame,loadasavedgame,visitanonlinegaminglobby,browseaninventory
ofmagicspellsgatheredwhileplayingthegame,etc.(Home)
Thescreentobeginanewgamethatletsyouselectacharactertoplay,aleveltoload,andthedifficultylevel(StartNewGame)
An attract mode in which the game plays back a cinematic sequence, originallydevelopedforarcadegamestoattractplayerswho mightbestandingnearby(Attract)
The loading levelpleasewait screen that appearsafteryouhave selecteda level toplay(Loading)
Apopupwindowthatdisplayswhenthegameispaused(GamePaused) Themaingameplaywindow,whichdisplaysa3Dgameworld,theplayerscharacterand
NPCs,perhapsa small insetoverheadmapof the level,player statistics, inventory,and
selectedweaponry,etc.(MainGamePlay)
Allofthesegamescreensdisplaysomethingdifferenttotheplayer.Eachisindependent,andonly
one can be in control at any instant in time (thoughmore than onemightbe actively doing
something).Eachofthesegamescreensisagamestate,andsoitbeginstobeeasytoimaginea
finitestatemachinethatrepresentstheoverall flowofthemajorgamescreensofagame.Lets
lookatadiagramofthestatesdescribedabove.
-
8/6/2019 Chapter1_GameAppFramework
4/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 3
StartupSplash
MainGamePlay GamePaused
Loading
Attract
StartNewGame
Home
Here,anarrowhasbeendrawnbetweentheStartupSplashstatetotheHomestate.Thisindicates
aratherobvioustransition.TheStartupSplashstateisactiveonlyuntilsufficientgameassetsare
loadedtodisplaytheHomestate,themainopeninggameuserinterface.TheStartupSplashstate
isthefaceofthegameasitboots.Letsaddanothersetoftransitions.Ifnoplayerinteractswith
thegameforsomeperiodoftime,say60seconds,theHomestatewillinitiateatransitiontothe
Attract state.After some time,or if thegamedetects thataplayer isdoing somethingwith a
gamepad,theAttractstatewillinitiateatransitionbacktotheHomestate.Thefollowingfigure
showsthisnewpairoftransitions.
StartupSplash
MainGamePlay GamePaused
Loading
Attract
StartNewGame
Home
Without much difficulty, if you are familiar with games, you should be able to fill in the
remainingbasictransitions.Thefollowingfigureillustratesacompletedstatemachinetransition
diagram. (Though actually, there areother transitions thatmake sensehere.For example, the
playermightbe able to canceloutof theStartNewGame state, causing that state to transition
backtotheHomestate.)
-
8/6/2019 Chapter1_GameAppFramework
5/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 4
StartupSplash
MainGamePlay GamePaused
Loading
Attract
StartNewGame
Home
Thisverybasicintroductiontotheconceptofstatemachinesshouldconvinceyouthatatypical
game really,anygamethatgivestheplayeranyoptions canbebuiltaroundahighlevelfinite
statemachine.Withalittlebitofplanning,itisntdifficulttobuildthesetypesofstatesintoeven
thesmallestofgames,fromthebeginning.
ImplementingaSimpleGameApplicationusingGamebryoandaSimpleFiniteStateMachineTheremainderofthischapterwillassembleasimplegameapplicationframework,implementing
asubsetofthestatesdescribedabove.
StartupSplash
MainGamePlay GamePaused
StartNewGame
The way our initial set of 4 stateswillwork is extremely simple. It resembles a traditional
application thatdisplaysamainwindow,butcanchange theway theuser interactsbydisplay
popupdialogboxes,addingandremovingpanesandcontrols,etc.Onekeydifferencehereisthat,
thoughonlyonestatecanbeincontrolofthegameapplication,anynumberofsuspendedstates
has the opportunity to perform actions interactively in time. These suspended states are not
respondingtocontrollerinput,butareplayinganimationsorotherspecialeffects,decidingwhen
toautosavealevelinplay,etc.Thesimplicityofthisinitialdemowillmakeiteasierforyouto
seehowthisworks,howthingsfittogether,andhowyoucanexploitcertainGamebryofeatures
-
8/6/2019 Chapter1_GameAppFramework
6/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 5
withinthesegamestates.Hereisadescriptionofthespecificbehaviorswewillimplementinthe
4states.
StartupSplash1. Displayastaticfullscreenimageshowingthegametitleandinformationthatthe
gameisloading
2. Forourchapter1tutorialcode,simplywaitforafewsecondstomimicthedelayaplayerwillexperiencewhilegameassets loadingfromdisk.Thetutorialwill load
assets, but for now the assets arent so significant that the player would be
botheredbythedelay.
3. At theendof thewaitingperiod,remove the fullscreen imageand forceastatechangetoStartNewGame
StartNewGame1. Displayalistboxwiththenamesofallavailableplayablecharacters,andallowthe
usertoselectfromthelistboxwiththemouse
2. Displayalistboxwiththenamesofalltheavailablegamelevels.Forthischapter,onlyonegamelevelwillbeavailable,andtheuserwillnotbeabletochangethe
selection
3. Display a button titled BeginGame,whichwhen clickedwith the leftmousebuttonwill force a state change toMainGamePlay, thus beginning anew game
usingthecurrentlyselectedcharacterandlevel
4. Displaya3Danimatedviewofthecurrentlyselectedcharacteronaportionofthescreen.Thecharactershouldactivateanidleanimation.
5. Displaya3Dviewofthecurrentlyselectedgamelevelonaportionofthescreen.6. Whilewaiting for theuser tobeginagame,respond toselectionchanges in the
characterlistboxbychangingthe3Dcharacterviewtoreflectchangedselections
7. Updatetheactiveanimationofthecurrentlyselectedcharacterovertime MainGamePlay
1. Loadtheselectedlevelandselectedcharacter.Placethecharacteratthelocationof anamed spawn pointnode located in the game levels scene graph.Make a
cameranamedDefaultCameratheactivecamera.Thiscameraiscontainedinthe
levelscenegraph
2. Animatethecharacterinitsidlestateastimepasses3. Monitorthekeyboard.WhentheuserpressestheQkey,quittheapplicationwith
nomessagestotheplayer
4. Whentheuserpressesthe Pkey,temporarilyentertheGamePausedstate.NotethatthiscausesMainGamePlaytobecomesuspended.
5. Whilesuspended,donotrespondtokeyboardclicksorotheruserinterfaceactions6. While suspended,continue toupdate thecharacters idleanimation, so that the
gamelevelstillhaslifeeventhoughgameplayisnotcontinuing
7. Whenthestateisresumed,resumerespondingtothekeyboard GamePaused
-
8/6/2019 Chapter1_GameAppFramework
7/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 6
1. Display apopupwindowUIover aportionof the screen that contains a singlebuttonlabeledResumeGame
2. Respondtobuttonclicks,andwhentheuserselectstheResumeGamebutton,removethepopupwindowandremoveGamePausedfromthestatestack,causing
thegametoreentertheMainGamePlaystate.
StandardandOpenSourceComponentsThistutorialserieswillusetheNiApplicationframeworkthatispartofGamebryo.Usingthis
frameworkenablesus to focuson integrating a simple finite statemachine that is suitable for
managing high level game state transitions and implementing the four game stateswe have
selected.ThetutorialcodecreatesanewapplicationclasscalledGameObject,whichextendsthe
NiApplicationclassasshownintheclassdiagrambelow.
WearegoingtointegrateanopensourcestatemachinesystemcontributedbyJamesBoertothe
bookGame ProgrammingGems5, titled LargeScale StackBased StateMachines.Whenyoubrowsethesourcecode,takenoteofJamescopyrightandusagerightsthatareassignedwithin
hissourcecode.Thissimpleframeworkwasdesignedforthingslikehighlevelgamestate,andis
quiteeasytouse. It istheperfectchoice forgettingthe initialgamecodeupandrunning.The
tutorialusesBoersimplementationnearlyverbatimfromtheCDdistributedwiththebook.Only
thefollowingchangeswereapplied.Comments intheStateManager.handStateMachine.cppfiles
documentthesechanges.LookforthelabelEGTalongwithdescriptivetext.
The pure virtual state interface class, IBaseState, was updated to be a Gamebryoreferencecountedobject,e.g.,itisnowderivedfromtheNiRefObjectbaseclass.
The current simulation timewas added as aparameter to theIBaseState::Updatefunction,toenableconcretestateclassestoupdateanimations,timestatechanges,etc.
TheStateManagerclasswasupdatedtostoresmartpointerstoreferencecountedstateinstancesratherthanrawpointers,toaidinmemorycleanup.
TheStateManagerclasswasmodifiedtoincludethecurrentsimulationtimeincallstoIBaseState::Update ontheactiveandsuspendedstates.
Wewillbeusingoneadditionalexistingopensourcecomponent.Sincemostofthestatesrequire
agraphicaluser interface,weneedclassesthatcan implementwidgetssuchasbuttonsand list
NiApplication
GameObject
-
8/6/2019 Chapter1_GameAppFramework
8/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 7
boxes.EmergentdoesprovideaspartoftheGamebryodistributionasimpleuserinterfacelibrary,
theNiUI*classes;however,theprovidedGamebryolibraryincludesonlyaverylimitedselection
ofcontrols.WewillbeusingCrazyEddiesGUISystem(CEGUI).OneofEmergentssupportstaff
hastakenthetimetointegrateCEGUIwithGamebryo,andwewillexploitthisintegration.You
can find the original demo integration in theGamebryo support forum thread titled "CEGUI
Gamebryo integration" located in the "Community Code Swap" folder, currently part of the
Download forum.Thiscodetoo isused innearlypureform.Theonlychange istoensurethe
CEGUIsystemhasbeeninitializedatthetimeaCEGUIrenderclickisconstructed.Thesechanges
aredocumentedintheCEGUIRenderClick.cppfilewiththelabelEGTanddescriptivetext.
Dokeep inmind that theseopensourcecomponentsmaynotbe theonlyoptionsavailable to
you.Forcommercialprojects,youmaywish toconsiderusing librariesprovidedbyEmergents
commercialpartners,sincetoolsandsupportforcommercialoptionsareoftenmorecosteffective
androbustthanopensourcecode.
AnatomyofaStateAbove,wepresentedthebasicconceptofagamestate,andtheideaoftransitionsbetweenthem.
Here, we will look at the anatomy of a single state, how the state has the opportunity to
implementgameplay,andhowstatetransitionsareinitiated.
Anygivenstatecanbeeitheractiveorinactive.Allstatesthathavebeenregisteredwiththestate
managerareinactivebydefault,anddonothingastimepasses.Youcanthinkofthemasalibrary
ofstatesthatareavailableforusewhenyouneedthem.Theyarenotonthestatestack. Active
statesarethosethatareonthestatestack,andallofthesehavetheopportunitytodoavarietyof
tasks,including:
Loadsceneobjects Modifytheframerenderingsystemtodisplaydifferentoverlaysanduserinterfaces Modifyscenegraphstospawnnewobjects,respondtotriggers,etc. Displaystatespecificscreenoverlaysandcontrols Performartificialintelligenceorphysicscalculations Readfromuserinterfacedevices(suchasgamepads)toimplementplayerinteraction Updateanimationsandrenderingeffectssothatingamevisualsareproperlydisplayed
Note thata state that ismadeactivewillbecome inactiveonceagain if thegame removes the
statefromthestatestack.
States typicallydonotdo any rendering.They can change the frame rendering configuration,
adding, deleting, and modifying items. But the actual rendering is triggered within the
NiApplicationframeworkafterstateupdateshavecompletedforeachframe.
Anactivestatecanbesuspendedtemporarily,allowinganotherstatetotakeoverforawhile.An
exampleofthisistheMainGamePlaystate,whichissuspendedwhilethegameispaused.
-
8/6/2019 Chapter1_GameAppFramework
9/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 8
Once constructed and registeredwith a statemanager, each state object has 5 primary entry
points,whichoverridethefollowingbaseclassentrypoints:
IBaseState::OnEnter: the statemanager calls thismember functionwhenever thegameisenteringthestate,andbecomingactive.Itisherethatastatecanmodifyascene
graph, create a thread to do background loads, create a statespecific graphical user
interface(e.g.,apopupdialogbox)toberendered,etc.
IBaseState::OnExit: the state manager calls this member functionwhenever thegameisexitingthestate,andthestateisbecominginactive.Thefunctionshouldperform
cleanuptaskshere,freeingmemoryandunloadinganystatespecificscenegraphelements
orotherresources.
IBaseState::OnOverride: the statemanager calls thismember functionwheneveranother state is being pushed onto the state stack. The state remains active, but is
suspended.It isallowedtodoupdatesovertime,but it isnotthehighestprioritystate.
For example, the statemanagerwill call this entry point onMainGamePlaywhenever
GamePausedbecomestheactivestateatthetopofthestatestack.
IBaseState::OnResume:thestatemanagercallsthismemberfunctionwheneverthisstatemovestothetopofthestack,becomingthehighestprioritystate.Forexample,the
statemanagerwillcallthisentrypointonMainGamePlaywheneverGamePausedismade
inactive.
IBaseState::Update:Onceper frame,thestatemanagercallsthismember functiononallactivestates.Thisenablestheactivestatestoupdatethemselvesovertime.
Thecurrentgamestatecanbechangedmostanywhereinthegamecode,buttypicallythisoccurs
somewherewithinthehighestpriorityactivestate.Forexample,theStartupSplashstatewillforce
atransitiontotheStartNewGamestateinsideStartupSplash::Update,onceitisdonewith
bootstrapprocessing.TheStartNewGame statewill transition toMainGamePlaywhen theuser
pressesabutton,andMainGamePlaysuspendsitselfbypushingGamePausedontothestatestack
whentheuserperformssomeuserinterfaceactiontopausethegame.
State transitions are activated via the StateManager class, using the following member
functions.ThegameapplicationmuststoreasingleinstanceofStateManager,andmustmake
itavailabletoanygamestatethatneedstotransition.
StateManager::ChangeState: Call this function to change the current highestpriorityactivestate.Thisdoesnotchangeanylowerprioritystatesinthestatestack.
StateManager::PushState:Callthisfunctiontosuspendthecurrenthighestprioritystate,pushanewstateontothestack,andenterthenewstate.
StateManager::PopState:Callthisfunctiontoexitthehighestprioritystate,pop itfromthestack,andresumethenexthigherprioritystate.
-
8/6/2019 Chapter1_GameAppFramework
10/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 9
NiApplicationandGameInitializationWiththosepreliminarydesignnotesoutoftheway,letsuslookattheassemblyofcodeforthis
chapter.OurgameisbuiltaroundtheNiApplicationframeworkthatisusedbythetutorials
thatarepartoftheGamebryodistribution.Mostoftheinternalsofgameapplicationstartupare
handleddeepwithinNiApplication.Youcan findadetaileddescriptionof thatclass in the
Gamebryodocumentation.OurGameObjectclassderivesfromNiApplicationandoverrides
severaloftheNiApplicationmethodstosupportCEGUIintegrationandtosupportthestate
machineframework.TheGameObjectclassincludestwomembervariables:
GameObject::m_StateManager.Thestatemachinemanagerinstancethatcontrolsallstateupdates,thestatestack,andtransitionsbetweenstates.
GameObject::m_spGUIRenderClick.AsmartpointertotherenderclickobjectthatwilldisplayallCEGUIuserinterfaceelements.
MuchoftheGameObjectclassisboilerplate.ItsimplyoverridesvariousNiApplicationbase
classmethodstoaddsupportfortheCEGUIsystemandthestatemachinesystem:
GameObject::Initialize:Thismember functionoverrides thebase class function,adding initialization of the state manager by calling StateManager::Init and
registeringallofthegamestatesbycallingGameObject::RegisterBaseStates.
GameObject::Terminate.ThismemberfunctiondisablesthestatemanagerbycallingtheStateManager::Termmemberfunction,thendestroystheCEGUIrenderclick,and
finallycallsthebaseclassmethod. GameObject::CreateRenderer.Thismember function is largelyacopyof thebase
class method. It has been modified to force the renderer to bewindowedwhen the
applicationisaDEBUGbuild,andfullscreenwhentheapplicationisnotaDEBUGbuild. GameObject::UpdateFrame.Thismember functioncalls thebaseclassmethod,and
thenupdatestheactivestatesbycallingStateManager::Update.Thestatemanagerin
turn calls theUpdatemember functionon all active states, allowing them toperform
transientoperationssuchasstatespecificanimationsandtomakedecisionsasafunction
oftime. GameObject::CreateFrame. This member function calls the base class method to
createtherenderframefortheGamebryoframerenderingsystem,andthencallsanother
function, GameObject::InitializeGUIFramework, which initializes CEGUI and
integratesitintotheGamebryoframerenderingsystem.TwopiecesoftheGameObjectclassrequireabitmoreexplanation.
First, the GameObject::InitializeGUIFramework member function, called from
GameObject::CreateScene,isresponsibleforcreatingtheCEGUIrenderclick,whichisthe
objectthatactuallyrenderstheuserinterfaceelementsforthegame.Fordetailedinformationon
renderclicks,seeNiRenderClickorFrameRenderingSystemintheGamebryodocumentation.ThismethodalsoconfiguresthecoreCEGUIframework,tellingitwhereresourcesarecontained
-
8/6/2019 Chapter1_GameAppFramework
11/23
-
8/6/2019 Chapter1_GameAppFramework
12/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 11
GameUIState, isderived fromGameBaseState.Theclasses for the three states listedabove
thenderivefromGameUIState,asshownintheclassdiagrambelow.
Ouroneremainingstateforthischapter,MainGamePlay,doesnotimplementanyuserinterface
featuresotherthana3Drenderviewofthegamescene.InsteadofderivingfromGameUIState,
itderivesdirectlyfromGameBaseState.
ImplementationoftheBaseUserInterfaceStateLetus first look at theuser interfacebase state class,GameUIState.The constructor for the
GameUIState,andallderivedstates,containstwoparameters,pcGUIImageSetFilenameand
pcGUILayoutFilename. The first parameter is the name of a CEGUI asset file with the
extension.imageset.This file isanXMLfilethatpointstoan imagefile(*.jpg,*.tga,etc.)and
definesnamedrectangularareaswithin that image.Theuser interfacestatesofourapplication
use thenamed imagesetasadecorative image tobedisplayedon the screenwhen the state is
active.ThesecondparameteristhenameofaCEGUIassetfilewiththeextension.layout.This
isanXMLfilethatdefinesalayoutofuserinterfacecontrolsbuttons,listboxes,etc.,aswellasa
backgroundpanebasedonthedecorativeimageset.Thevisualappearanceofthecontrolsusedin
the layout isdefinedviaCEGUI schemes and looknfeelobjects,which reference imagesets and
definewhichnamedrectangularareasareassociatedwithaparticulartypeofcontrol,e.g.,which
rectangularsubimagesrepresentabuttonsupanddownstates.Theschemeand looknfeelalso
definehowaparticularcontrolismappedtoCEGUIlibrarycodethatrepresentsthebehaviorof
thecontrol.
NiRefObject
IBaseState
GameBaseState
GameUIState
StartNewGame GamePaused
MainGamePlay
StartupSplash
-
8/6/2019 Chapter1_GameAppFramework
13/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 12
During GameObject initialization, a number of schemes were loaded, and these schemes,
togetherwiththeimagesetandlooknfeelobjectsthattheyimplicitlyloaded,arealwaysavailable
forany states layout touse. Ifyouareusingcustomart, thenyourart team is responsible for
creatingallof thenecessaryCEGUIassets.The imagesusedby thedecorativebackgroundand
controlsalikecancontainalphachannels,enablingyourartiststopaintinterestinguserinterfaces
witharbitraryshapesandborders.YourartistsshouldtakenotethatimagesreferencedbyCEGUI
imagesetsmusthavedimensionsthatarepowersoftwo.
TheconstructorforGameUIStatedoesverylittle.Itsimplycachesthepassedin imagesetand
layout names into instance member variables. The creation of the CEGUI user interface is
implemented within the GameUIState::OnEnter and GameUIState::OnExit member
functions.
Whenever a user interface state is entered, and the statemanager calls the states OnEntermember function, thebaseclasswill first initialize the state (e.g., load thedecorative imageset
and
create
the
layout
from
file),
if
it
is
not
initialized,
and
then
it
will
append
the
state
specific
user interface layoutasachildof the transparentbackgroundwindow thatwascreatedby the
GameObject::InitializeGUIFrameworkmember function.There is a convenient artifact
that arises from appending the statespecific user interface layout. The statespecific layout
becomesthelastiteminalistoflayoutstoberendered,andsoitisrenderedontopofeverything
else.This isdesirable, sincewedexpectall suspended states tobeobscuredby thenew state.
Imagine that the MainGamePlay state contains user interface elements, and that the player
pressesagamepadbuttontocausethegametopause.Thepausestatewilladditsownlayoutthat
willberenderedontopoftheMainGamePlaylayoutjustasyouwouldexpectinapopupdialog
box.
Wheneverauserinterfacestateisexited,andthestatemanagercallsastatesOnExitmember
function, thebaseclasswill first remove the statespecific layout from theCEGUIbackground
window(thusrevealinganyotheractivestate layoutsthatwerehiddenbytheoneexiting),and
thenwilldestroythestatespecificlayoutandremoveitsimageset.Thecleanupcodeisawayof
reducingmemoryusageforstatesthatarenotactive.Caremustbetakenforstatesthatsharea
decorativeimageset.Thesamplecodedoesnothandlethiscase.
ImplementationoftheStartupSplashStateThis is the simplest of all the game states. Its layout displays a decorative background image
calledStartupSplashBackground.Therearenocontrolsatall.
Thebehaviorthatthisstateimplementsissimplytowaitforawhile,andthenforceatransition
to StartNewGame. The behavior is entirely implemented within the StartupSplashBack-
ground::Updatememberfunction,usingthecodeshownbelow:
if (fCurrentTime >= 1.0)
{
StateManager &rStateManager = GameObject::GetStateManager();
-
8/6/2019 Chapter1_GameAppFramework
14/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 13
rStateManager.ChangeState("StartNewGame");
}
Nothingcouldbesimpler.Here,fCurrentTime isthecurrentgamesimulationtime,which is
passed intothemethodasaparameter.Afterthesimulationtimereachesonesecond,thestate
usesthestatemanagertoexplicitlychangethestatetoStartNewGame.Theactualstatechange
willoccurduringthenextframe,whenthestatemanagerprocessesitsinternaleventqueue.(Ina
realgame,ofcourse,thesplashstatewouldtypicallydomorethansimplywaitforsomeperiodof
timebeforeenteringthenextstate.)
ImplementationoftheStartNewGameStateThisstateisabitmorecomplexthanStartupSplash.Thetwolistboxesandthebuttonarebuilt
intotheCEGUI layoutnamedStartNewGame.layout.Thedecorativebackgroundimagethatis
usedbythelayoutiscalledStartNewGameBackground.imageset.Thedecorativebackgroundin
thiscasecontainstwotransparentrectangularareaswherethe3Dviewsoftheselectedcharacter
andlevelaretobedisplayed.Thecontrolitemsinthelayoutarecreatedandpreparedfordisplay
asdescribedabove,bythebaseclass,GameUIState.
WiththisstatewecanlookintotheGamebryoframerenderingsysteminalittlemoredetail.The
NiApplicationboilerplateconfigurationcodecreatesanumberofrendersteps(inGamebryo
terms), including a shadow render step, amain render step intended to render 3D gameplay
views,andascreenspacerenderstep,intendedtorender2Doverlaysanduserinterfacecontrols.
In this state,wewill use themain and screen space render steps. Themain render stepwill
displaytworenderclicks.Thefirstrenderclickthatwewillcreaterenderstoasmallportionof
thegamewindow,aviewportthathasbeenallocatedspecificallytoshowananimatedviewofthe
currentlyselected3Dcharacter.Thischaracterviewisthefirstrenderclickthatwillberendered
tothescreen,asshownbelow.Thenumberintheupperleftcorneroftherenderclickindicates
theorder inwhichthatrenderclick isdrawntothescreen.The largegreyrectanglerepresents
thefullgameapplicationwindow.
-
8/6/2019 Chapter1_GameAppFramework
15/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 14
MainGameObject RenderStep
3DCharacterViewRender
Click
1
The second renderclick in themain render stepwill renderaviewofa second3D scene that
shows the selected levelusingadifferentcamera.Again, this renderclick renders intoa small
viewportwithinthegamewindowthathasbeenallocatedforthe3Dlevelview.
MainGameObject RenderStep
3DCharacterViewRender
Click
3DLevelViewRender
Click
1 2
-
8/6/2019 Chapter1_GameAppFramework
16/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 15
There are no more render clicks in the main render step. The next render step created by
NiApplication is the screen space render step. In theGameObject initialization code,we
attachedtheCEGUIuserinterfacerenderclicktothisstep,andsotheuserinterfacerenderclick
isdrawnon topof the two3Dview renderclicks.Theuser interface renderclickdraws to the
entiregamewindow,and so if its scenecontainsopaqueobjects thatcover theviewportareas
drawn by the 3D views, the user interface will occlude the 3D views. The following image
illustratesthedisplayoftheuserinterfacerenderclickontopofthepriorrenderclicks.Here,the
renderclickrectanglehasbeendrawnslightlysmallerthantheoutlineshown forthe fullgame
window,simplytotryandillustratethatitisbeingdrawnontop.
ScreenSpaceRenderStep
3DCharacterViewRender
Click
3DLevelViewRender
Click
1 2
CEGUIRenderClick3
Theviewabovedoesnotshowanyof thecontentsof theuser interfacerenderclick. Itmerely
illustratestheviewportandthefactthatitisdrawnontopofthepriorrenderclicksalayering
effect.Below, the figure illustrates theelementsoftheStartNewGamestatesuser interface: the
decorativebackgroundimage,thelistboxforcharacterselection,thelistboxforlevelselection,
andtheBeginGamebutton.Theseareillustratedasthoughtheyweredrawnatthesametime,
but in fact they too are drawn in sequence, as defined by the CEGUI layout. See theCEGUI
documentation
for
more
information
on
layering
of
CEGUI
elements.
-
8/6/2019 Chapter1_GameAppFramework
17/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 16
ScreenSpaceRenderStep
CEGUIRenderClick3
3DCharacterViewRender
Click
3DLevelViewRender
Click
1 2
CharacterListBox LevelListBox
BeginGame
Notethat,inthefigureabove,the3Dviewsshowthroughtheuserinterface.Thisillustratesthe
fact that thebackground imagesetusedbyStartNewGamehas transparent regions in thealpha
channelofitstexture,designedtorevealwhateverwasrenderedunderneath.
Now, lets look athow this configurationof the frame rendering system is accomplished.The
StartNewGame class overrides the GameUIState::OnEnter method in order to do state
specificinitialization:
Register a callback function, StartNewGame::ButtonClick, that will be calledwhenevertheuserclickstheBeginGamebutton.
Generate a 3Dviewof the selected character, andpopulate the listbox containing thenamesoftheselectablecharacters.This isaccomplished inaseparatemember function,
StartNewGame::ConfigureSelectedCharacterView.
Generate a 3Dviewof the selected level, andpopulate the levelname listbox.This isaccomplished in a separate method, StartNewGame::ConfigureSelected-
LevelView.
Creationofthe3Dviewoftheselectedcharacterandlevelaresomewhatinvolved.Itisnecessary
toloadGamebryoassetsandcreatenewrenderviewstodisplaythe3Dobjects.Themethodsto
createthecharacterviewandlevelviewareverysimilar,sosimilarthatthisdiscussionwillonly
describethecharacterviewsetup.
The StartNewGame::ConfigureSelectedCharacterViewmember function is the entry
pointusedtocreatethecharacterview.Itaccomplishesseveralthings:
-
8/6/2019 Chapter1_GameAppFramework
18/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 17
UsestheGamebryoobjectstreamingsystemtoloadaGamebryoNiSceneasset(a*.gsafile created by theGamebryo SceneDesigner application) using the NiEntity library.
Thischaracterselectionscenecontainsalloftheselectablecharactersandacamerathat
looksateachofthem
Configuresacameraviewporttofitintherectangularareaassociatedwiththecharacterview
Calls another member function, StartNewGame::ConfigureAvailable-Characters,toparsethecharacterNiSceneanddiscoverthenamesofalltheplayable
characters
Calls another method, StartNewGame::SelectCharacterImpl, to activate thecamera for the initially selected character and to activate that camera within the
appropriateviewport
Updatestheinitialcameraviewportandaspectratiotomatchtherectangularareawherecharactersarebeingdisplayed
Creates
a
new
render
view
and
render
click
to
use
the
camera
to
render
the
character
sceneintheappropriateplaceonscreen
Within thismethod, for chapter 1, theGamebryo scene filename ishardcoded. Similarly, the
rectangularareaallocated forcharacters ishardcodedbasedonpixelcoordinates thatarebuilt
intothedecorativeimagesetforthisstate.Inlaterchapters,wewilllookatwaystousemoredata
drivenconfigurations,usingruntimescripts.
The StartNewGame::ConfigureAvailableCharacters function iterates through the
entitiescontainedinthecharacterselectionscene,searchingforentitiesthathaveamasterentity
thathavethetext[Characters]inthename. Itistheresponsibilityofyourcodeandartteamstoagreeonnamingconventionsandstandardsforassets,toensurethatgamelogicisabletoproperlyparseassets. In thiscase, foreachdiscoveredselectablecharacterentity,themethodcreatesanewentryinthecharacterselectionlistbox,whichiscalled"StartNewGame/CharacterSel"inthe
CEGUIlayoutfileforthisstate.Thecodepopulatesalistboxwiththenamesofthecharactersit
finds, and initially selects the first character in the list. Themethod does onemore thing. It
registers a callback function, StartNewGame::SelectCharacter, which will be called
whenevertheplayerselectsadifferentcharacter.
TheStartNewGame::SelectCharacterImplfunctionfindsthecurrentlyselectedcharacter
intheStartNewGame/CharacterSellistandlocatesthecameraassociatedwiththatcharacterin
thescene.Thecodeassumesthatforeverycharacter,thereisacamerathathasthesamenameas
thecharacterbutwith the text Camappended.So, for the Dragonmancharacter, thecode
expectstofindacameranamedDragonmanCamthathasbeenarrangedwithinSceneDesignerto look at the characternamed Dragonman.Here again is an exampleof code that requires
coordinationbetweencode and art teams. If a camera is found, thecodeadjusts thecameras
viewportandaspectratiotomatchtheuser interfaceareawheretheselectedcharacterisbeing
displayed.
-
8/6/2019 Chapter1_GameAppFramework
19/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 18
TheStartNewGame::SelectCharactercallbackfunction,whichiscalledwhenevertheuser
clicks a different character name in the list box, simply calls through to StartNewGame::
SelectCharacterImpltochangethecameraview.
Thatcompletesconfigurationoftheselectedcharacterview.Configurationfortheselectedlevel
issimilar;however,forthischapteronlyonelevelisavailableandthecodeisabitsimplerthan
forcharactersno iteration thoughavailable levelsandnocallbacktohandleachange in level
selection.
The remainingcode forthisclassconcernsupdating thestateovertimeandresponding to the
buttonclickthatbeginsthegame.
TheStartNewGame::Updatefunctioniscalledbythestatemanageronceperframe.Thecode
israthersimple:itcallstheUpdatefunctionontheNiSceneobjectsassociatedwithcharacters
andlevels.Forthecharacters,thesecallsplaywhateveranimationcyclewasselectedwithinSceneDesigner.Ifthecameraassociatedwiththecharacterwasanimated,thiscallwouldalsoupdate
thecameraalong itspath.Similarly,anyanimationsthatexistforthe levelselectscenearealso
playedhere.Your art team is free todevelop interesting effects that theywould like tobebe
displayedandanimatedwithinthecharacterandlevelselectscreen.
TheStartNewGame::ButtonClickfunctionrespondswhentheuserclickstheBeginGame
button.TheonlyresponseistochangethestatetoMainGamePlay.Thestatemanagerwillcallthe
statesOnExitmethodduringthenextupdate,justpriortocallingMainGamePlay::OnEnter.
The StartNewGame::OnExit function performs cleanup tasks, first removing the custom
render clicks associatedwith the character and level 3Dviews, then calling the base class to
performstandarduserinterfacecleanup.Thismethoddoesoneotherimportanttask:itretrievesapointertotheMainGamePlaystatefromthestatemanager,andcallsamethodinthatstateto
tellthestatewhichcharacterandwhichleveltouseforthegame.
ImplementingtheMainGamePlayStateForthischapter,theMainGamePlaystateissimple,atleastwhencomparedwithStartNewGame.
Ultimately, itdoes littlemore thandisplay theselected level,createan instanceoftheselected
characterataprescribedspawnpointthatislocatedinthelevelscenegraph,thenviewthescene
graphusing aprescribed camera.AswithStartNewGame, the code andart/design teamsmust
agreeonexactlyhowthescenewillbepresentedduringgameplay.
Prior to the game entering the MainGamePlay state, the StartNewGame state will call
MainGamePlay::BeginLevelon the inactive instanceofMainGamePlay,whichcaches the
NiSceneobjectfortheselectedlevelandapointertoacopyoftheselectedcharacterentity.The
character copy is created using MainGamePlay::SpawnCharacter, a function that
instantiatesacloneofagivencharacter,andplacesitatanamedspawnpoint.(Inlaterchapters,
theStartNewGamestatemightloadasimplifiedversionofthelevelfordisplaypriortothegame
start,and in thiscase theMainGamePlaystatewouldneed tobedelayedwhile the full level is
-
8/6/2019 Chapter1_GameAppFramework
20/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 19
loaded.An intermediate state, such as the Loading state describednear the beginning of this
chapter,wouldbeappropriatehere.)
The MainGamePlay::OnEnter function appends a render click to the GameObjectsmain
renderstep.Sincetherearenootherscenesbeingrendered,andbecausethereis(currently)no
userinterface,thisrenderclickistheonlyonethatwillrenderanythingwhileMainGamePlayis
at the top of the state stack. Thenew render click fills the applicationwindowwith a single
viewportthatdisplaystheselectedlevel.Thisisthegameplaywindow.Thefunctionalsosearches
forandactivatesacamerainthescenenamedDefaultCamera.
When the player begins the game, the StartNewGame state calls the
MainGamePlay::SpawnCharacter function, which clones the character that the player
selected.Bycloningthecharacter,whichwasloadedintomemoryforthecharacterselection,the
gamecanavoidaccessingthemodel fromdisk.Ifyoustudy the functioncarefully,youwillsee
that it clones the master entity of the players selected character, rather than the selected
character
itself.
The
reason
why
it
is
inappropriate
to
clone
the
selected
character
is
that
the
selected charactermay have a custom translation and orientation that pose and animate the
character as an artist intended it to beviewed during character selection, and this may be
different from the ingame pose. The ingame character needs to be based on a canonical
characterstatethatplacesthecharacteratthe levelorigin,facingthenegativeydirection,with
feetontheground.Gamelogiccan,therefore,veryeasilyplacetheclonewhereitneedstobein
the game level. Themaster entity has the canonical state. Once themaster entity has been
cloned, themethod changes thevalue of the Translation property to place the clone at the
spawnpointlocation,setstheappropriateactiveanimationsequence,andaddstheclonetothe
listofentitiesaffectedbythelightinthescene.Finally,thecloneisaddedtothescene.
The remainingcode for this statedealswithupdating thestateover time,and transitioning to
otherstates.
TheMainGamePlaystateclassimplementationoftheIBaseState::Updatevirtualmember
function is abitmorecomplex than the implementation in states.Aswith theStartNewGame
state, itcalls theUpdate functionon theappropriateNiSceneobject,which in turnupdates
renderingeffectsandanimations.Beyondthis,ifthestateisnotsuspended,itreadsthekeyboard
andhandlestwokeyboardcommands:
The Qkeywillcausethestateto issueastandardWindowsmessage toshutdowntheapplication, to quite the game immediately.More sophisticated behaviorwould be to
transitiontoanotherstateallowingtheusertheoptionofsavingthegame,resumingthe
game,orexitingtothemainmenu.
ThePkeywillcausethegametosuspendthisstate,pushingtheGamePausedstateontothestatestack.
Themethodalsocontainsplaceholdercommentsforavarietyofotherthingsthatcanhappenon
everyframeduringgameplay,including:
-
8/6/2019 Chapter1_GameAppFramework
21/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 20
artificialintelligencetaskssuchaspathfinding physicstasksthatmightnotbehandledautomatically(withinanyanimationupdates) scriptingtasks andotherstatespecifictasks
Wewillfillintheseotherperframetasksaswebuildthisgameupoverthechapterstocome.
Aswiththeotherstates,theMainGamePlay::OnExitfunctionperformscleanuptasks.Inthis
case,theexplicitcleanupcodeissimplytoremovetherenderclickthatwasaddedtorenderthe
level. The method also dereferences the levels NiScene object,which might cause it to be
destructed (if it isnot referencedelsewhere).Thesceneowns theclonedcharacter,and so the
nonsmartpointertothecharacter isset tozerotoavoidpotentialuseofanobjectthatmight
havebeendestructed.
ImplementingtheGamePausedStateGamePausedisthelaststatethatweareimplementingforchapter1.
It is a user interface state, and so its class derives fromGameUIState and utilizes aCEGUI
*.layoutfiletoobtainitscontrols.Thisstatehasasinglecontrol,abuttonthattheusercanpress
to resume the game. Its GamePaused::Initialize function registers a callback function,
GamePaused::ButtonClick,thattheCEGUIsystemwillcallwheneverthebuttonisclicked.
Thatcallbackfunctionsimplypopsthestateoffofthestatemanagersstack,causingthestateto
exit,andcausingthepriorstatetoresume.Inthiscase,theonlystatethatcanenterGamePaused
is MainGamePlay. So, when GamePaused responds to the button click, at the next
GameObject::UpdateFrame callperformedbyNiApplication, thegamewill resume the
game.
FinalRemarksandLessonstobeLearnedfromtheChapter1DemoCodeNowthatthe4gamestatesarefullyimplemented,thegameisreadytorun!Althoughsomeofthe
configurationcodecanbeabittedious,itislargelyboilerplateandeasilywrittenonceinabase
class,thenreusedforever.Forexample,ourGameUIStatebaseclassmanagesalluserinterface
layouts fordisplay, andmanages cleanupwhen a state goes inactive.Thederived classesonly
need to register statespecific callbacks for control interactions, and then respond to those
controls.Thecodeforthischapterisrathersimple,andpresentsonlyoneapproachtomanaging
highlevelstatesinagame.Hopefully,asyouobservedthecodedevelopedhere,andlearnedhow
the pieces work together, you began to better understand how to think about software
architectureandstructureasyoudesignyourowngame.
Werecommendthatyounowtakethetimetorunthecodeindebugmode,withbreakpointsset
at the topof theOnEnter,OnExit,OnOverride,andOnResume functionsofeach state,as
well as on lines of code that call StateManager::ChangeState,
StateManager::PushState, and StateManager::PopState. This will enable you to
experience the state diagram transitions directly, and may deepenyour appreciation for the
-
8/6/2019 Chapter1_GameAppFramework
22/23
ImplementingGameplayElementsUsingGamebryo
Chapter1:ASimpleFrameworkforaGameApplication 21
simplicityofthesystem.Also,youmaybeinterested inbrowsingtheHTMLdocumentationfor
thechapterscode.OpentheHTMLfile,index.html,locatedintheChapter1/docs/htmlfolder,to
viewthedocumentation.
Oneimportantlessonyoushouldlearnfromthischapteristhatitisvitallyimportantfortheart
team(includingdesigners)andcodeandscriptdeveloperstocometoanagreementonnamingconventions and organizational conventions for all art assets. Establishing these conventions
must be one of the first thingsyou do during preproduction, regardless ofwhetheryou are
workingonanAAAtitleorastudentorhobbygameproject!Ifyoufailtoestablishconventions,
andusethem,youwilleventuallywasteasignificantamountoftimecorrelatingcode,script,and
assets.Sotakeheed!
FileDirectoryStructurefortheTutorialCodeTheclassesdescribedaboveloadvariousCEGUIandGamebryoassets,fromtimetotime.Allof
theassetsarelocatedinahierarchyofsubfoldersundertheassetsfolder,whichmustbedirectly
underneath the applicationworking folder. Following is a summary of the hierarchy of assetfoldersusedbythischapterscode.
CEGUI_Integration Objects that integrate CEGUI into Gamebryo
Chapter1 Root folder for the Chapter 1 demo code
The configuration file for doxygen, used to
generate source code documentation, is contained
here. The Visual Studio project builds the
game executable files into this folder, and
this is the working folder when running the
game in debug mode, since the assets are
directly underneath
SourceWin32 Source files for main game app and base classesThe project solution file and project file for
Visual Studio 2005 .NET are here
States Source files for concrete game state classes
Utilities Source files for various utility functions
Docs Output folder for doxygen, this folder contains
formatted documentation for the source code
Assets Root folder for game runtime assets
Characters Root folder for game character assets
Dragonman Folder containing the Dragonman character and
animations
Phoenix Folder containing the Phoenix character and
animations
Models Folder containing general game models
Scenes Folder containing game scene files, created
with the Gamebryo SceneDesigner. These scenes
reference items in the characters and models
folders
UI Root folder for all CEGUI user interface assets
Configs CEGUI config schema files
-
8/6/2019 Chapter1_GameAppFramework
23/23
ImplementingGameplayElementsUsingGamebryo
Fonts CEGUI font files
Imagesets CEGUI image sets
Layouts CEGUI layouts. Layouts define the look and layout
of user interface controls for those states that
display user interfaces. The layouts can be
created using the CEGUI tool, CELayoutEditor.
Looknfeel CEGUI look-n-feel files
Schemes CEGUI scheme files
OtherResourcesandReferencesEmergentGameTechnologies, Introduction to theFrameRenderingSystem in theGamebryo
Documentation
EmergentGameTechnologies,IntroductiontoNiApplicationintheGamebryoDocumentation
EmergentGameTechnologies,NiEntityIntroductionintheGamebryoDocumentation
CrazyEddiesGUISystemWebsite:http://www.cegui.org.uk/wiki/index.php/Main_Page
Boer,James,LargeScaleStackBasedStateMachines,GameProgrammingGems5,CharlesRiverMedia,2005.
Exercises1. Howwouldyoumodifythehighlevelgamestatemachineillustratedabovetoincludean
onlinegamelobby?
2. Howwouldyouextendtheexampleapplicationtorepresentthe fullcollectionofstatesillustratedabove?
3. Howwouldyouaddaningameminigametothestatemachine?