the
gamedesigninitiative
at cornell university
Lecture 8
Component Design
Recall: Problem with Subclassing
ꢀ Games have lots of classes
ꢀ Each game entity is different
NPC
ꢀ Needs its own functionality
(e.g. object methods)
- Human
- Orc
ꢀ Want to avoid redundancies
ꢀ Makes code hard to change ꢀ Common source of bugs
Human Warrior
Human Archer
- Orc
- Orc
- Archer
- Warrior
ꢀ Might be tempted to subclass
ꢀ Common behavior in parents ꢀ Specific behavior in children
Redundant Behavior
the
gamedesigninitiative
Architecture Patterns
2
at cornell university
Recall: Problem with Subclassing
ꢀ Games have lots of classes
ꢀ Each game entity is different
NPC
ꢀ Needs its own functionality
(e.g. object methods)
- Warrior
- Archer
ꢀ Want to avoid redundancies
ꢀ Makes code hard to change ꢀ Common source of bugs
Human Warrior
- Orc
- Human
Archer
Orc
- Warrior
- Archer
ꢀ Might be tempted to subclass
ꢀ Common behavior in parents ꢀ Specific behavior in children
Redundant Behavior
the
gamedesigninitiative
Architecture Patterns
3
at cornell university
Alternative: Decorator Pattern
New
Functionality
Original Object
Reference to Original
base object
Functionality
Decorator
Object
Request
the
gamedesigninitiative
Architecture Patterns
4
at cornell university
Alternate: Delegation Pattern
Original Object
Reference to
Delegate
Request delegate
Object
Forward Request
Inversion of the Decorator Pattern
the
gamedesigninitiative
Architecture Patterns
5
at cornell university
Issues with Static Typing
Method in original class
Original
object class
obj.request(arg1,…, argn)ꢀ
Original Object
Reference to delegate
Delegate
Object
Request
Forward Request
the
gamedesigninitiative
Architecture Patterns
6
at cornell university
The Subclass Problem Revisited
Delegates?
NPC
Orc
Slot Slot Slot
Human
- Human
- Orc
NPC
Warrior
Archer
Human Warrior
Human Archer
- Orc
- Orc
- Archer
- Warrior
Redundant Behavior
the
gamedesigninitiative
Architecture Patterns
7
at cornell university
Component-Based Programming
Delegates
ꢀ Role: Set of capabilities
Role 1
ꢀ Class with very little data ꢀ A collection of methods
Slot
Role 2
ꢀ Add it to object as delegate
Slot
Entity
ꢀ Object gains those methods
Role 3 Role 4
Slot
ꢀ Acts as a “function pointer”
ꢀ Can-it: search object roles
ꢀ Check class of each role ꢀ Better than duck typing ꢀ Possible at compile time?
Field storing a single delegate or
a set of delegates
the
gamedesigninitiative
Architecture Patterns
8
at cornell university
Aside: Objective-C
ꢀDelegates are emphasized in Objective-C
ꢀ ObjC protocols function like Java interfaces ꢀ But implement with a delegate, not a subclass
ꢀOften leverages message passing
ꢀ Method call is considered a message ꢀ Can call any method on any object ꢀ Will get runtime error if method not supported ꢀ Heavily optimized in latest Apple compilers
the
gamedesigninitiative
Architecture Patterns
9
at cornell university
Aside: Objective-C
ꢀDelegates are emphasized in Objective-C
ꢀ ObjC protocols function like Java interfaces ꢀ But implement with a delegate, not a subclass
ꢀOften leverages message passing
ꢀ Method call is considered a message ꢀ Can call any method on any object ꢀ Will get runtime error if method not supported ꢀ Heavily optimized in latest Apple compilers
the
gamedesigninitiative
Architecture Patterns
10
at cornell university
Working With Static Typing
- Uniform Method
- Direct Access
ꢀ
if (o has role) {ꢀ o.doSomething(kitchenSink)ꢀ
extract role from oꢀ role.doSomething(info)ꢀ
}ꢀ
the
gamedesigninitiative
Architecture Patterns
11
at cornell university
Working With Static Typing
- Uniform Method
- Direct Access
ꢀ
if (o has role) {ꢀ o.doSomething(kitchenSink)ꢀ
extract role from oꢀ role.doSomething(info)ꢀ
}ꢀ
Problem:
Multiple capabilities
the
gamedesigninitiative
Architecture Patterns
12
at cornell university
Working With Static Typing
- Uniform Method
- Direct Access
ꢀ
if (o has role) {ꢀ o.doSomething(kitchenSink)ꢀ
extract role from oꢀ role.doSomething(info)ꢀ
}ꢀ
Problem:
Problem:
Big switch statements
Multiple capabilities
the
gamedesigninitiative
Architecture Patterns
13
at cornell university
Entities Need Both Is-a and Can-it ꢀ
- Table
- Chair
Objects share same capabilities in theory. But certain actions are preferred on each.
the
gamedesigninitiative
Architecture Patterns
14
at cornell university
Solving the Problem
- Can-It
- Is-A
ꢀ Indicated by object roles
ꢀ Component indicates role ꢀ Check type of each role ꢀ So again a typing solution
ꢀ Indicated by object class
ꢀ But could do more than that
ꢀ Keep a bag of types
ꢀ Contains of the descriptions that apply to this object
ꢀ “Formal duck typing”
ꢀ Example: table, heirloom
ꢀ Not limited to method name ꢀ Role type indicates action
ꢀ Why would we do this?
name, not a noun
the
gamedesigninitiative
Architecture Patterns
15
at cornell university
Fast Can-It Testing: Bit Vectors
ꢀGive each object a bit-vector to cover types
ꢀ Each role is a position in the bit vector
ꢀ Example:
0100101ꢀ
the
gamedesigninitiative
Architecture Patterns
16
at cornell university
Fast Can-It Testing: Bit Vectors
ꢀGive each object a bit-vector to cover types
ꢀ Each role is a position in the bit vector
ꢀ Example:
0100101ꢀ
Can Build
- Can Fight
- Can Heal
ꢀ Use array if more than 32/64 roles
the
gamedesigninitiative
Architecture Patterns
17
at cornell university
Fast Can-It Testing: Bit Vectors
ꢀGive each object a bit-vector to cover types
ꢀ Each role is a position in the bit vector
ꢀ Example:
0100101ꢀ
Can Build
- Can Fight
- Can Heal
ꢀ Use array if more than 32/64 roles
ꢀTest is quick logical operation.
ꢀ Example: vector & CAN_FIGHTꢀ
ꢀ Faster than dynamic typing (why?)
the
gamedesigninitiative
Architecture Patterns
18
at cornell university
Model-Controller Separation Revisited
- Model
- Controller
ꢀ Store/retrieve object data ꢀ Process interactions
ꢀ Preserve any invariants ꢀ Data may include delegates ꢀ Determines is-a properties
ꢀ Look at current game state ꢀ Look for “triggering” event ꢀ Apply interaction outcome
Components
- ?
- ?
ꢀ Process game actions
ꢀ Attached to a entity (model) ꢀ Uses the model as context ꢀ DeterAmrcihniteecsturceaPnat-tietrnps roperties
the
gamedesigninitiative
19
at cornell university
Model-Controller Separation Revisited
- Model
- Controller
ꢀ Store/retrieve object data ꢀ Process interactions
ꢀ Preserve any invariants ꢀ Data may include delegates ꢀ Determines is-a properties
ꢀ Look at current game state ꢀ Look for “triggering” event ꢀ Apply interaction outcome
Components
Is this always the best idea?
- ?
- ?
ꢀ Process game actions
ꢀ Attached to a entity (model) ꢀ Uses the model as context ꢀ DeterAmrcihniteecsturceaPnat-tietrnps roperties
the
gamedesigninitiative
20
at cornell university
Recall: Lab 3 in CS 3152
the
gamedesigninitiative
Architecture Patterns
21
at cornell university
Processing Actions in Lab 3
GameplayController.cs
Ship.cs
- ꢀ Decides whether to shoot
- ꢀ Waits until objects commit
ꢀ Checks intent in Ship object ꢀ Performs action for intent
ꢀ Stores intent in the object
ꢀ But DOES NOT shoot
the
gamedesigninitiative
Game Architecture
22
at cornell university
Processing Actions in Lab 3
GameplayController.cs
Attach components to controller?
Ship.cs
- ꢀ Decides whether to shoot
- ꢀ Waits until objects commit
ꢀ Checks intent in Ship object ꢀ Performs action for intent
ꢀ Stores intent in the object
ꢀ But DOES NOT shoot
the
gamedesigninitiative
Game Architecture
23
at cornell university
Related: Handling the View
ꢀ Way too much to draw
ꢀ Backgrounds ꢀ UI elements
Update Draw
ꢀ Individual NPCs ꢀ Other moveable objects
ꢀ Cannot cram all in Draw ꢀ Put it in game object?
ꢀ But objects are models
ꢀ Violates MVC again
the
gamedesigninitiative
Architecture Patterns
24
at cornell university
First Attempt: A Drawing Canvas
ꢀ Treat display as a container
ꢀ Often called a canvas ꢀ Cleared at start of frame ꢀ Objects added to container ꢀ Draw contents at frame end
Passed as reference
ꢀ Canvas abstracts rendering
ꢀ Hides animation details
void draw(Canvas c) {ꢀ
// Specify perspectiveꢀ // Add to canvas
}ꢀ
ꢀ Like working with widget
ꢀ Implement draw(c) in model
ꢀ Classic heavyweight model ꢀ No problems with extension
the
gamedesigninitiative
Architecture Patterns
25
at cornell university
Problem: Canvas Methods
Ideal
Model1
draw(canvas)ꢀ
Canvas
drawShape(…)ꢀ
Model2
draw(canvas)ꢀ
the
gamedesigninitiative
Architecture Patterns
26
at cornell university
Problem: Canvas Methods
In Practice
Model1
draw(canvas)ꢀ
Canvas
drawShape1(…)ꢀ drawShape2(…)ꢀ
Model2
draw(canvas)ꢀ
the
gamedesigninitiative
Architecture Patterns
27
at cornell university
Views and Components
Slot
Component1ꢀ
drawShape1(…)ꢀ
Slot Slot
Model1 Model2
Canvas
drawPrimitive(…)ꢀ
Slot Slot Slot
Component1ꢀ
drawShape1(…)ꢀ
the
gamedesigninitiative
Architecture Patterns
28
at cornell university
Views and Components
Primitive effects
Slot
Component1ꢀ
Slot
Model1
drawShape1(…)ꢀ
Slot
Complex,
Shape-specific rendering
Slot
Canvas
drawPrimitive(…)ꢀ
Component1ꢀ
drawShape1(…)ꢀ
Slot
Model2
Slot
the
gamedesigninitiative
Architecture Patterns
29
at cornell university
Components and AI
Alert!
ꢀ NPCs use sense-think-act cycle
ꢀ Sense: perceive the world ꢀ Think: choose an action ꢀ Act: update the game state
ꢀ Act is stored in components
ꢀ Capabilities given by roles
ꢀ Where are sense and think?
Yes
ꢀ In the component/role?
This is hard
ꢀ How do roles interact?
the
gamedesigninitiative
Game Architecture
30
at cornell university