CSCE 590E Spring 2007

CSCE 552 Fall 2012
Language and Programming
By Jijun Tang
Methodologies: Code and Fix





Unfortunately very common
Little or no planning
Always reacting to events
Poor quality and unreliability of finished
product
“Crunch” time normal
Methodologies: Waterfall





Very well-defined steps in development
Lots of planning ahead of time
Great for creating a detailed milestone
schedule
Doesn't react well to changes
Game development is too unpredictable
for this approach
Methodologies: Iterative

Multiple development cycles during a
single project
Each delivering a new set of functionality
 Refinements are needed



The game could ship at any moment
Allows for planning but also for changes
Methodologies: Agile Methods





Deal with the unexpected
Very short iterations: 2-3 weeks
Iterate based on feedback of what was
learned so far
Very good visibility of state of game
Difficult for publishers or even
developers to adopt because it's
relatively new
Languages





C/C++
Java
Script: Flash, Python, LISP, etc.
C#
XNA for PC and Xbox
Lua Example
MSTS Example
Choose a Scripting Languages






Consider whether you need one at all
What features do you need?
What kind of performance do you need?
What debugging facilities does the
language have?
On what platforms does it need to run?
What resources and expertise are
available?
Programming Fundamentals
Data Structures: Array

Elements are adjacent in memory (great cache
consistency)


They never grow or get reallocated



Use dynamic incremental array concept
GCC has a remalloc function
In C++ there's no check for going out of bounds



Requires continuous memory space
Use vector if possible
Keep in mind of checking boundaries
Inserting and deleting elements in the middle is
expensive
List



Very cheap to add/remove elements.
Available in the STL (std::list)
Every element is allocated separately,
not placed contiguously in memory
Lots of little allocations
 Bad cache awareness, but can use arrays
to hold pre-allocated items


Single/Double linked list
Lists
Dictionaries





Maps a set of keys to some data.
std::map, std::hash, etc
Very fast access to data
Perfect for mapping IDs to pointers, or
resource handles to objects
May waste space, need to design
comparison operators
Hash Table
Others

Stacks
First in, last out
 std::stack adaptor in STL


Queues
First in, first out
 std::deque
 Priority queue is useful in game to schedule
events

Stack/Queue/Priority Queue
Bit packing





Fold all necessary data into a smaller number of
bits
Bool in C++ may use up to 4 bytes, thus is very
expensive
Very useful for storing boolean flags: pack 32 in an
integer
Possible to apply to numerical values if we can give
up range or accuracy
Very low level trick


Use shifts to handle the operation or use assembly
Only use when absolutely necessary
Bits
Inheritance




Models “is-a” relationship
Extends behavior of existing classes by
making minor changes
Do not overuse, if possible, use component
systerm
UML diagram representing inheritance
Enemy
Boss
SuperDuperBoss
Polymorphism



The ability to refer to an object through a
reference (or pointer) of the type of a
parent class
Key concept of object oriented design
C++ implements it using virtual functions
Multiple Inheritance





Allows a class to have more than one base
class
Derived class adopts characteristics of all
parent classes
Huge potential for problems (clashes,
casting, dreaded diamond, etc)
Multiple inheritance of abstract interfaces is
much less error prone (virtual inheritance)
Java has no multiple inheritance
Dreaded Diamond


It is an ambiguity that
arises when two classes B
and C inherit from A, and
class D inherits from both
B and C.
If a method in D calls a
method defined in A (and
does not override the
method), and B and C
have overridden that
method differently, then
from which class does it
inherit: B, or C?
Component Systems

Component system organization
GameEntity
Name = sword
RenderComp
CollisionComp
DamageComp
PickupComp
WieldComp
Object Factory



Creates objects by name
Pluggable factory allows for new object
types to be registered at runtime
Extremely useful in game development
for passing messages, creating new
objects, loading games, or instantiating
new content after game ships
Factory Pattern
Simple Sample Factory - I
Simple Sample Factory - II
Singleton



Implements a single instance of a class
with global point of creation and access
For example, GUI
Don't overuse it!!!
Singleton
static Singleton & GetInstance();
// Regular member functions...
static Singleton uniqueInstance;
Singleton Example
Adapter



Convert the interface of a class into
another interface clients expect.
Adapter lets classes work together that
couldn't otherwise because of
incompatible interfaces
Real interface
Adapter Pattern
Adapter Example - I
Adapter Example - II
Observer


Allows objects to be notified of specific
events with minimal coupling to the
source of the event
Two parts

subject and observer
Observer Pattern
Composite


Allow a group of objects to be treated as
a single object
Very useful for GUI elements,
hierarchical objects, inventory systems,
etc
Composite Pattern
Composite Pattern Example - I
Add many more inherited classes
The Five Step
Debugging Process
1. Reproduce the problem consistently
2. Collect clues
3. Pinpoint the error
4. Repair the problem
5. Test the solution
Expert Debugging Tips












Question assumptions
Minimize interactions and interference
Minimize randomness
Break complex calculations into steps
Check boundary conditions, use assertions
Disrupt parallel computations
Exploit tools in the debugger (VC is good, purify)
Check code that has recently changed
Explain the bug to someone else
Debug with a partner (A second pair of eyes)
Take a break from the problem
Get outside help (call people)
Game Architecture
Overall Architecture

The code for modern games is highly
complex




The Sims: 3 million lines of code
Xbox HD DVD player: 4.7 million lines
MS Train Simulator has 1GB installed, with only
10MB executable
With code bases exceeding a million lines of
code, a well-defined architecture is essential
Overall Architecture

Main structure
Game-specific code
 Game-engine code


Both types of code are often split into
modules, which can be static libraries,
DLLs, or just subdirectories
Overall Architecture

Architecture types





Ad-hoc (everything accesses everything)
Modular
DAG (directed acyclic graph)
Layered
Options for integrating tools into the
architecture



Separate code bases (if there's no need to share
functionality)
Partial use of game-engine functionality
Full integration
Ad-hoc
Modular
DAG
Layered
Overview:
Initialization/Shutdown


The initialization step prepares
everything that is necessary to start a
part of the game
The shutdown step undoes everything
the initialization step did, but in reverse
order
Initialization/Shutdown

Resource Acquisition Is Initialization



A useful rule to minimalize mismatch errors in the
initialization and shutdown steps
Means that creating an object acquires and
initializes all the necessary resources, and
destroying it destroys and shuts down all those
resources
Optimizations


Fast shutdown
Warm reboot
Overview:
Main Game Loop




Games are driven by a game loop that
performs a series of tasks every frame
Some games have separate loops for
the front and the game itself
Other games have a unified main loop
Must finish a loop within 0.017 second
Tasks of Main Game Loop








Handling time
Gathering player input
Networking
Simulation
Collision detection and response
Object updates
Rendering
Other miscellaneous tasks
Sample Game Loop
Main Game Loop

Structure




Hard-coded loops
Multiple game loops: for each major game state
Consider steps as tasks to be iterated through
Coupling



Can decouple the rendering step from simulation
and update steps
Results in higher frame rate, smoother animation,
and greater responsiveness
Implementation is tricky and can be error-prone
Execution Order of Main Loop





Most of the time it doesn't matter
In some situations, execution order is
important
Can help keep player interaction
seamless
Can maximize parallelism
Exact ordering depends on hardware