Game Architecture Friday (Dave Weinstein of Red Storm) War/Horror Stories ------------------ Rainbow 6, young company, used "subclassing procedural" design. 3 subclasses of the simulation engine. Had problems with not passing new arguments to parents in class hierarchy. To switch simulations, had to destroy and recreate simulation object (and many things required a simulation object -- caused bugs during the transition). Single/multiplayer combo Everything derived from MFC classes Pass by CString Data in UI widgets rather than reflected by UI Scoping problems leading to name clashes Common names conflict with middleware 1600 character line with for, if, etc. -- dubplicated 4 times "Premature abstraction" bad; "insufficient abstraction" also bad complicated logical architecture Duplicated decision points #ifdef no view/logic separation -- Rainbow 6 won't run without a sound card Custom script with preprocessor: #define foo true #define foo false interpreted as #define true false custom script language without a debugger different tools that duplicate functionality, without sharing code no source control header dependencies poor factoring library inter-dependencies junk drawer syndrome -- physical sparation of files and directories helps Good Ideas ---------- Read & write in the same file; better if next to each other; even better the same function Debug: serialize and deserialize a default object as a test In debug build, serialize and deserialize are type safe (tag values with types). Better if debug and release builds are interoperable. Similar: 4 character code before each binary blob in debug mode. Keep separate game logic and engine Game logic can be in a higher level language ABC (abstract base classes): no concrete headers included in an interface .h. Went from 40 minute to 5 minute compile times. Use directories to enforce abstraction layers. Pluggable factory used in particle system -- went from supporting one type to many. Read Design Patterns. Abstract player input: it helps with debugging and being able to replay. Plan for debugging: save all data. Ex: Keep all hresults in a struct. Readable data format in debug mode Networking mistake: premature optimization. Use text initially then inspect the logs to find out what is using the bandwidth. Prototype the finite state machine with a tool Automated file format definition transformation into a GUI editting tool Configurable logging at runtime; ex: syslog Keep a list of all code areas with name, color, max memory, time/frame. Usefull for debugging, logging, profiling. Document the system structure. Build on another platform -- even when not a cross platform game. Build on a PC when making a console title: can share dev kits. Write on the console first since architectures are so different -- important to start with "suckier" platform Enforce memory polices -- ie. no memory allocation in main loop Lock memory manager in section to assert on memory allocation For internationalization: hash english text instead of String IDs, lead to readable code. Automated string table management good. Translators need context to resolve homynyms. They might translate "back" as in "previous" as "back" as in "dorsal side". Using LUA for front end helped with string translation. Don't parameterize strings if you can avoid it.