0% found this document useful (0 votes)
628 views

Uncharted 2 State Scripting

This document discusses state-based scripting used in Naughty Dog's Uncharted 2 video game. It describes how state scripts allow extending the game's object model by adding finite state machine behavior. State scripts are comprised of attributes, states that define object behavior through script code run on events, and transitions between states. They can be attached to game objects, trigger regions, or used as standalone objects to orchestrate other entities.

Uploaded by

jaennirin
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
628 views

Uncharted 2 State Scripting

This document discusses state-based scripting used in Naughty Dog's Uncharted 2 video game. It describes how state scripts allow extending the game's object model by adding finite state machine behavior. State scripts are comprised of attributes, states that define object behavior through script code run on events, and transitions between states. They can be attached to game objects, trigger regions, or used as standalone objects to orchestrate other entities.

Uploaded by

jaennirin
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 162

State-Based Scripting in

Jason Gregory
Generalist Programmer
Naughty Dog, Inc.
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
1
Agenda
Introduction to game scripting
Extending the game object model
State script syntax
Case studies from
Uncharted 2: Among Thieves
Implementation discussion
Summary and some tips
Monday, April 6, 2009
Introduction to State Scripts
4
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Brief History of State Scripts
Script system on Uncharted: Drakes Fortune originally developed
for in-game cinematics (IGCs)
Evolved into general gameplay scripting system
5
Monday, April 6, 2009
UDF IGC system revamped for heavy
use on Uncharted 2: Among Thieves
Inspirations:
! GOAL language used on Crash and Jak series
! State objects from God of War engine
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Brief History of State Scripts
6
78
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Why Script?
Scripting languages used in games since Quake C
Primary benets of script:
! Takes pressure off engineering team
! Code becomes datarapid iteration
! Empowers content creators
! Key enabler of mod community
9
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Why Script?
Scripting languages used in games since Quake C
Primary benets of script:
! Takes pressure off engineering team
! Code becomes datarapid iteration
! Empowers content creators
! Key enabler of mod community
9
I fee| empowered!
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Scripting Language Characteristics
Two kinds of game scripting languages:
! data denition languages
! runtime languages
Runtime scripting languages typically:
! interpreted by virtual machine (VM)
! simple and smalllow overhead
! accessible to designers and other non-programmers
! powerfulone line of code = big impact
:
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Choice of Language
At Naughty Dog, we make heavy use of both data denition
and runtime script
! Both based on PLT Scheme (a Lisp variant)
Key benets of Lisp-like languages:
! Easy to parse
! Data def and runtime code can be freely intermixed
! Powerful macro systemeasy to dene custom syntax
! Naughty Dog has a rich Lisp heritagecomfortable
;
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Choice of Language
Of course you dont have to use Lisp!
Data denition languages:
! custom text format,
! Excel comma-separated values (.csv),
! XML, ...
Runtime languages:
! Python, Lua, Pawn (Small C), OCaml, F#, ...
Many popular engines already provide a scripting language:
! Quake C, UnrealScript, C# (XNA), ...
3
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Extending the Game Object Model
<2
Every game engine has some kind of game object model
! Denes all object types in game world
! Often (but not always) written in an object-oriented language
Scripting language often used to extend the native object model
Many ways to accomplish this...
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Game Object Model References
Rob Fermier, Creating a Data Driven Engine, GDC, 2002
Scott Bilas, A Data-Driven Game Object System, GDC, 2002
(http://www.drizzle.com/~scottb/gdc/game-objects.ppt)
Alex Duran, Building Object Systems: Features, Tradeoffs and
Pitfalls, GDC, 2003
Doug Church, Object Systems, presented at a game development
conference in Seoul, Korea, 2003
(http://chrishecker.com/images/6/6f/ObjSys.ppt)
Jason Gregory, Game Engine Architecture, AK Peters, 2009
(http://gameenginebook.com)
<<
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Unreals Approach
UnrealScript tightly integrated with C++ object model
! Single-root class hierarchy with some add-on components
! Classes dened in UnrealScript (.uc)
! C++ header le (.h) automatically generated
! Implementation in C++ or entirely in UnrealScript
<1
awn.h
awn.cpp
generate
|mp|ement
awn.uc
|mp|ement
Actor
Info awn |ckup
Scout Veh|c|e
...
...
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Property-Centric / Componentized Designs
Property-centric design used on Thief, Dungeon Siege, Age of
Mythology, Deus Ex 2 and others
! Game object just a unique id (UID)
! Decorated with various properties
(health, armor, weaponry, etc.)
! Property encapsulates data + behavior
<4
Cb[ect
(UID)
nea|th: 200
Armor: L|ght
AI: |ayerA||y
Weapon: 8IG
Weapon: |sto|
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Uncharted Engines Object Model
Uncharted class hierarchy:
! relatively shallow, single-root
! host of add-on components
<5
rocess
Ssrocess rocessGameCb[ect CameraContro|
Character S|mp|eLnnty
...
...
DynL|ght Ss1rackGrouprocess
...
Monday, April 6, 2009
=>?$0@,
@A"@ B*C"@$
)'$+ D#$
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Uncharted Engines Object Model
Uncharted class hierarchy:
! relatively shallow, single-root
! host of add-on components
<5
rocess
Ssrocess rocessGameCb[ect CameraContro|
Character S|mp|eLnnty
...
...
DynL|ght Ss1rackGrouprocess
...
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Uncharted Engines Object Model
Uncharted class hierarchy:
! relatively shallow, single-root
! host of add-on components
<5
rocess
Ssrocess rocessGameCb[ect CameraContro|
Character S|mp|eLnnty
...
...
DynL|ght Ss1rackGrouprocess
...
=>?$0@,
EF@A @+".,/)+#
".C #$,A
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Uncharted Engines Object Model
Uncharted class hierarchy:
! relatively shallow, single-root
! host of add-on components
<5
rocess
Ssrocess rocessGameCb[ect CameraContro|
Character S|mp|eLnnty
...
...
DynL|ght Ss1rackGrouprocess
...
G",$ 0(",, /)+
"(( 0A"+"0@$+,
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Uncharted Engines Object Model
Uncharted class hierarchy:
! relatively shallow, single-root
! host of add-on components
<5
rocess
Ssrocess rocessGameCb[ect CameraContro|
Character S|mp|eLnnty
...
...
DynL|ght Ss1rackGrouprocess
...
HF#*($
".F#"D.I
)>?$0@
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Uncharted Engines Object Model
Uncharted class hierarchy:
! relatively shallow, single-root
! host of add-on components
<5
rocess
Ssrocess rocessGameCb[ect CameraContro|
Character S|mp|eLnnty
...
...
DynL|ght Ss1rackGrouprocess
...
8"."I$, " H@"@$
H0+F*@ F.,@".0$
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Uncharted Engines Object Model
Uncharted class hierarchy:
! relatively shallow, single-root
! host of add-on components
<5
rocess
Ssrocess rocessGameCb[ect CameraContro|
Character S|mp|eLnnty
...
...
DynL|ght Ss1rackGrouprocess
...
8"."I$, "
0AB.J )/
+B..F.I ,0+F*@
0)C$
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Uncharted Engines Object Model
Uncharted class hierarchy:
! relatively shallow, single-root
! host of add-on components
<5
rocess
Ssrocess
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Uncharted Engines Object Model
Uncharted class hierarchy:
! relatively shallow, single-root
! host of add-on components
<5
rocess
Ssrocess
SsInstance
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Uncharted Engines Object Model
Uncharted class hierarchy:
! relatively shallow, single-root
! host of add-on components
<5
rocess
rocessGameCb[ect
SsInstance DrawContro| An|mContro|
...
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Charter
World editor for
Uncharted is called
Charter
! Place game objects
! Edit object
properties
! Control level
streaming
<6
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Uncharted State Scripts
State scripts similar in many respects to property-centric model...
! adds nite state machine (FSM) support
! not specically tied to properties
! coarser-grained (one script per object)
More like scripted extension to existing entity type...
! ... or a director that orchestrates actions of other entities
<9
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Anatomy of a State Script
A state script is comprised of:
! attributes
! states
States dene objects behavior via runtime script code:
! response to events
! natural behavior over time (update event)
! transitional actions between states (begin/end events)
<:
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
<;
Anatomy of a State Script
State Scr|pt 1
H@"@$ K
L"+F">($,
H@"@$ G
State Scr|pt 2
H@"@$ -
L"+F">($,
On Update
On Event1
On Begin On Event4
On Begin
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
<;
Anatomy of a State Script
State Scr|pt 1
H@"@$ K
L"+F">($,
H@"@$ G
M'$.@<
State Scr|pt 2
H@"@$ -
L"+F">($,
On Update
On Event1
On Begin On Event4
On Begin
Monday, April 6, 2009
I) @)
H@"@$ G
!"#$ &$'$()*$+, -)./$+$.0$ 1223
<;
Anatomy of a State Script
State Scr|pt 1
H@"@$ K
L"+F">($,
H@"@$ G
M'$.@<
State Scr|pt 2
H@"@$ -
L"+F">($,
On Update
On Event1
On Begin On Event4
On Begin
Monday, April 6, 2009
I) @)
H@"@$ G
!"#$ &$'$()*$+, -)./$+$.0$ 1223
<;
Anatomy of a State Script
State Scr|pt 1
H@"@$ K
L"+F">($,
H@"@$ G
M'$.@<
State Scr|pt 2
H@"@$ -
L"+F">($,
M'$.@5
On Update
On Event1
On Begin On Event4
On Begin
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Instantiating a State Script
<3
Game
Cb[ect
State Scr|pt 1
Attached to a native (C++) game object:
! designers extend or modify native
C++ object type
! dene entirely new object types
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Instantiating a State Script
Attached to a trigger region:
! convex volume
! detects enter, exit and occupancy
<3
Game
Cb[ect
State Scr|pt 1
1r|gger keg|on
State Scr|pt 2
Attached to a native (C++) game object:
! designers extend or modify native
C++ object type
! dene entirely new object types
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Instantiating State Scripts
Placed as stand-alone object:
! director orchestrates actions of
other objects (e.g. IGC)
12
Ssrocess
State Scr|pt 3
(stand-a|one)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Instantiating State Scripts
Placed as stand-alone object:
! director orchestrates actions of
other objects (e.g. IGC)
12
1ask A
1ask 81 1ask 82
1ask C
1ask D
State Scr|pt 4
Ssrocess
State Scr|pt 3
(stand-a|one)
Associated with a task:
! task = check point
! script manages associated task
! orchestrates AI encounters
! controls player objectives
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Instantiating State Scripts
Placed as stand-alone object:
! director orchestrates actions of
other objects (e.g. IGC)
12
1ask A
1ask 81 1ask 82
1ask C
1ask D
State Scr|pt 4
Ssrocess
State Scr|pt 3
(stand-a|one)
Associated with a task:
! task = check point
! script manages associated task
! orchestrates AI encounters
! controls player objectives
Spawned by another state script
Monday, April 6, 2009
State Script Syntax
1<
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
11
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
State Script Syntax
State script dened as follows:
! Dont let Lisp syntax throw you!
! Lisp syntax is all (parentheses)
! Think C/C++ { } blocks
Parenthesized blocks highly
context-sensitive in Lisp/Scheme
14
(dene-state-script ("kickable-gate")
(state ("locked")
...
)
(state ("opening")
...
)
(state ("open")
...
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
State Script Syntax
State script dened as follows:
! Dont let Lisp syntax throw you!
! Lisp syntax is all (parentheses)
! Think C/C++ { } blocks
Parenthesized blocks highly
context-sensitive in Lisp/Scheme
14
(dene-state-script ("kickable-gate")
(state ("locked")
...
)
(state ("opening")
...
)
(state ("open")
...
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
State Script Syntax
State script dened as follows:
! Dont let Lisp syntax throw you!
! Lisp syntax is all (parentheses)
! Think C/C++ { } blocks
Parenthesized blocks highly
context-sensitive in Lisp/Scheme
14
(dene-state-script ("kickable-gate")
(state ("locked")
...
)
(state ("opening")
...
)
(state ("open")
...
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
State Script Syntax
State script dened as follows:
! Dont let Lisp syntax throw you!
! Lisp syntax is all (parentheses)
! Think C/C++ { } blocks
Parenthesized blocks highly
context-sensitive in Lisp/Scheme
14
(dene-state-script ("kickable-gate")
(state ("locked")
...
)
(state ("opening")
...
)
(state ("open")
...
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Event Handler Blocks
Each state contains zero or more
event handler blocks
15
(dene-state-script ("kickable-gate")
(state ("locked")
(on (event "kick")
... ;; handle "kick" event
)
(on (begin)
... ;; do when state entered
)
(on (update)
... ;; do every frame
)
(on (end)
... ;; do when state exited
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Event Handler Blocks
Each state contains zero or more
event handler blocks
15
(dene-state-script ("kickable-gate")
(state ("locked")
(on (event "kick")
... ;; handle "kick" event
)
(on (begin)
... ;; do when state entered
)
(on (update)
... ;; do every frame
)
(on (end)
... ;; do when state exited
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Event Handler Blocks
Each state contains zero or more
event handler blocks
15
(dene-state-script ("kickable-gate")
(state ("locked")
(on (event "kick")
... ;; handle "kick" event
)
(on (begin)
... ;; do when state entered
)
(on (update)
... ;; do every frame
)
(on (end)
... ;; do when state exited
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Event Handler Blocks
Each state contains zero or more
event handler blocks
15
(dene-state-script ("kickable-gate")
(state ("locked")
(on (event "kick")
... ;; handle "kick" event
)
(on (begin)
... ;; do when state entered
)
(on (update)
... ;; do every frame
)
(on (end)
... ;; do when state exited
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Event Handler Blocks
Each state contains zero or more
event handler blocks
15
(dene-state-script ("kickable-gate")
(state ("locked")
(on (event "kick")
... ;; handle "kick" event
)
(on (begin)
... ;; do when state entered
)
(on (update)
... ;; do every frame
)
(on (end)
... ;; do when state exited
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Runtime Script Code
Runtime script code inside (on ...)
blocks
Simplied Scheme/Lisp
! Most commands are native calls
into C++ code
! Conditional expressions
! Simple looping via label/goto
16
(state ("locked")
(on (begin)
[print-string "Starting idle!"]
[animate "self" "locked-idle"]
)
(on (event "kicked")
[when [lock-broken?]
[print-string "BAM!"]
]
[if [task-complete? "wave2"]
[print-string "Complete!"]
[print-string "NOT!!!"]
]
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Runtime Script Code
Runtime script code inside (on ...)
blocks
Simplied Scheme/Lisp
! Most commands are native calls
into C++ code
! Conditional expressions
! Simple looping via label/goto
16
(state ("locked")
(on (begin)
[print-string "Starting idle!"]
[animate "self" "locked-idle"]
)
(on (event "kicked")
[when [lock-broken?]
[print-string "BAM!"]
]
[if [task-complete? "wave2"]
[print-string "Complete!"]
[print-string "NOT!!!"]
]
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Runtime Script Code
Runtime script code inside (on ...)
blocks
Simplied Scheme/Lisp
! Most commands are native calls
into C++ code
! Conditional expressions
! Simple looping via label/goto
16
(state ("locked")
(on (begin)
[print-string "Starting idle!"]
[animate "self" "locked-idle"]
)
(on (event "kicked")
[when [lock-broken?]
[print-string "BAM!"]
]
[if [task-complete? "wave2"]
[print-string "Complete!"]
[print-string "NOT!!!"]
]
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Runtime Script Code
Runtime script code inside (on ...)
blocks
Simplied Scheme/Lisp
! Most commands are native calls
into C++ code
! Conditional expressions
! Simple looping via label/goto
16
(state ("locked")
(on (begin)
[print-string "Starting idle!"]
[animate "self" "locked-idle"]
)
(on (event "kicked")
[when [lock-broken?]
[print-string "BAM!"]
]
[if [task-complete? "wave2"]
[print-string "Complete!"]
[print-string "NOT!!!"]
]
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
User-Dened Functions
Script functions can be dened
and called by script programmer
19
(defun verbose-anim ((anim string))
[print-string "Starting " anim]
[animate "self" anim]
)
(dene-state-script ("kickable-gate")
(state ("locked")
(on (begin)
[verbose-anim "locked-idle"]
)
)
...
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
User-Dened Functions
Script functions can be dened
and called by script programmer
19
(defun verbose-anim ((anim string))
[print-string "Starting " anim]
[animate "self" anim]
)
(dene-state-script ("kickable-gate")
(state ("locked")
(on (begin)
[verbose-anim "locked-idle"]
)
)
...
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
User-Dened Functions
Script functions can be dened
and called by script programmer
19
(defun verbose-anim ((anim string))
[print-string "Starting " anim]
[animate "self" anim]
)
(dene-state-script ("kickable-gate")
(state ("locked")
(on (begin)
[verbose-anim "locked-idle"]
)
)
...
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
User-Dened Functions
Script functions can be dened
and called by script programmer
19
(defun verbose-anim ((anim string))
[print-string "Starting " anim]
[animate "self" anim]
)
(dene-state-script ("kickable-gate")
(state ("locked")
(on (begin)
[verbose-anim "locked-idle"]
)
)
...
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
User-Dened Functions
Script functions can be dened
and called by script programmer
19
(defun verbose-anim ((anim string))
[print-string "Starting " anim]
[animate "self" anim]
)
(dene-state-script ("kickable-gate")
(state ("locked")
(on (begin)
[verbose-anim "locked-idle"]
)
)
...
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
The Self Argument
Any command operating on a game object takes its unique id
(UID) as its rst argument
Magic UID "self" refers to the object to which script is attached
1:
Game
Cb[ect
State Scr|pt 1
I"@$N<:
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
The Self Argument
Any command operating on a game object takes its unique id
(UID) as its rst argument
Magic UID "self" refers to the object to which script is attached
1:
Game
Cb[ect
State Scr|pt 1
(on (begin)
[animate "self" "locked-idle"]
)
,$(/
I"@$N<:
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
The Self Argument
Any command operating on a game object takes its unique id
(UID) as its rst argument
Magic UID "self" refers to the object to which script is attached
1:
Game
Cb[ect
State Scr|pt 1
I"@$N<: (on (begin)
[animate "gate-17" "locked-idle"]
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
The Self Argument
Any command operating on a game object takes its unique id
(UID) as its rst argument
Magic UID "self" refers to the object to which script is attached
1:
Game
Cb[ect
State Scr|pt 1
I"@$N<:
Game
Cb[ect
()0JN9
(on (begin)
[animate "lock-6" "fall-off"]
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Changing States
Transitions to other states via
(go "state-name") command
State transitions cause current
states (on ...) blocks to be
aborted
Use (on (exit) ...) block for
clean-up
1;
(dene-state-script ("kickable-gate")
(state ("locked")
...
(on (event "kicked")
[when [lock-broken?]
[go "opening"]
]
)
)
(state ("opening")
(on (begin)
...
)
...
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Changing States
Transitions to other states via
(go "state-name") command
State transitions cause current
states (on ...) blocks to be
aborted
Use (on (exit) ...) block for
clean-up
1;
(dene-state-script ("kickable-gate")
(state ("locked")
...
(on (event "kicked")
[when [lock-broken?]
[go "opening"]
]
)
)
(state ("opening")
(on (begin)
...
)
...
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Changing States
Transitions to other states via
(go "state-name") command
State transitions cause current
states (on ...) blocks to be
aborted
Use (on (exit) ...) block for
clean-up
1;
(dene-state-script ("kickable-gate")
(state ("locked")
...
(on (event "kicked")
[when [lock-broken?]
[go "opening"]
]
)
)
(state ("opening")
(on (begin)
...
)
...
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Tracks
(on ...) blocks contain one or more tracks
A track is a bit like a thread or ber
Tracks can be put to sleep
! Wait for duration
e.g., wait 5 seconds,
wait until frame 23, ...
! Wait for an action to be done
duration-agnostic
Tracks can be synchronized via signals
13
Monday, April 6, 2009
H@"@$ O,A"J$NA".C,O
=. G$IF.
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Tracks
42
7+"0J
P
7+"0J
H
,N"NE
*N"NE
(state ("shake-hands")
(on (begin)
(track ("player"))
[wait-move-to "player" "waypoint7"]
[signal "player-at-waypoint"]
[wait-for-signal "sully-at-waypoint"]
[wait-animate "player" "shake-sullys-hand"]
)
(track ("sullivan"))
[wait-move-to "sullivan" "waypoint7"]
[signal "sully-at-waypoint"]
[wait-for-signal "player-at-waypoint"]
[wait-animate "sullivan" "shake-drakes-hand"]
)
)
)
Monday, April 6, 2009
H@"@$ O,A"J$NA".C,O
=. G$IF.
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Tracks
42
7+"0J
P
7+"0J
H
,N"NE
*N"NE
(state ("shake-hands")
(on (begin)
(track ("player"))
[wait-move-to "player" "waypoint7"]
[signal "player-at-waypoint"]
[wait-for-signal "sully-at-waypoint"]
[wait-animate "player" "shake-sullys-hand"]
)
(track ("sullivan"))
[wait-move-to "sullivan" "waypoint7"]
[signal "sully-at-waypoint"]
[wait-for-signal "player-at-waypoint"]
[wait-animate "sullivan" "shake-drakes-hand"]
)
)
)
7+"0J
P
7+"0J
H
Monday, April 6, 2009
H@"@$ O,A"J$NA".C,O
=. G$IF.
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Tracks
42
7+"0J
P
7+"0J
H
,N"NE
*N"NE
(state ("shake-hands")
(on (begin)
(track ("player"))
[wait-move-to "player" "waypoint7"]
[signal "player-at-waypoint"]
[wait-for-signal "sully-at-waypoint"]
[wait-animate "player" "shake-sullys-hand"]
)
(track ("sullivan"))
[wait-move-to "sullivan" "waypoint7"]
[signal "sully-at-waypoint"]
[wait-for-signal "player-at-waypoint"]
[wait-animate "sullivan" "shake-drakes-hand"]
)
)
)
Monday, April 6, 2009
H@"@$ O,A"J$NA".C,O
=. G$IF.
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Tracks
42
7+"0J
P
7+"0J
H
,N"NE
*N"NE
(state ("shake-hands")
(on (begin)
(track ("player"))
[wait-move-to "player" "waypoint7"]
[signal "player-at-waypoint"]
[wait-for-signal "sully-at-waypoint"]
[wait-animate "player" "shake-sullys-hand"]
)
(track ("sullivan"))
[wait-move-to "sullivan" "waypoint7"]
[signal "sully-at-waypoint"]
[wait-for-signal "player-at-waypoint"]
[wait-animate "sullivan" "shake-drakes-hand"]
)
)
)
Monday, April 6, 2009
H@"@$ O,A"J$NA".C,O
=. G$IF.
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Tracks
42
(state ("shake-hands")
(on (begin)
(track ("player"))
[wait-move-to "player" "waypoint7"]
[signal "player-at-waypoint"]
[wait-for-signal "sully-at-waypoint"]
[wait-animate "player" "shake-sullys-hand"]
)
(track ("sullivan"))
[wait-move-to "sullivan" "waypoint7"]
[signal "sully-at-waypoint"]
[wait-for-signal "player-at-waypoint"]
[wait-animate "sullivan" "shake-drakes-hand"]
)
)
)
7+"0J
P
7+"0J
H
*N"NE
,N"NE
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Track Execution Over Time
4<
Rules for execution of code within a track:
! Greedily consume instructions sequentially...
! ... until a [wait* ...] command encountered...
! ... then relinquish control until the action is complete
NOTE: A [wait* ...] command doesnt have to wait; for example:
! [wait-seconds 0]
! [wait-npc-move-to "pos-4"] when shes already there
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Options and Variable Declarations
Options declared at top of
script:
! initial state
! variable declarations
! debugging options
41
(dene-state-script ("kickable-gate")
:initial-state "closed"
:declarations (decl-list
(var "num-attempts" :type int32)
(var "is-locked" :type boolean :default #t)
)
(state ("kicked")
...
)
...
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Options and Variable Declarations
Options declared at top of
script:
! initial state
! variable declarations
! debugging options
41
(dene-state-script ("kickable-gate")
:initial-state "closed"
:declarations (decl-list
(var "num-attempts" :type int32)
(var "is-locked" :type boolean :default #t)
)
(state ("kicked")
...
)
...
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Options and Variable Declarations
Options declared at top of
script:
! initial state
! variable declarations
! debugging options
41
(dene-state-script ("kickable-gate")
:initial-state "closed"
:declarations (decl-list
(var "num-attempts" :type int32)
(var "is-locked" :type boolean :default #t)
)
(state ("kicked")
...
)
...
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
44
(dene-state-script ("kickable-gate")
:initial-state "closed"
:declarations (decl-list
(var "num-attempts" :type int32)
(var "is-locked" :type boolean :default #t)
)
(state ("kicked")
(on (begin)
[when [get-boolean "is-locked"]
[set-int32 "num-attempts"
[+ 1 [get-int32 "num-attempts"]]
]
[wait-animate "self" "kick-failure"]
[go "closed"]
]
;; else...
[wait-animate "self" "kick-success"]
[go "open"]
)
)
...
Manipulating Variables
Simple commands for reading
and writing variables
Lisp/Scheme uses prex notation
(a.k.a. Polish notation)
! [+ a b] calculates (a + b)
! [set "x" [+ 1 [get "x"]]]
increments variable x
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
44
(dene-state-script ("kickable-gate")
:initial-state "closed"
:declarations (decl-list
(var "num-attempts" :type int32)
(var "is-locked" :type boolean :default #t)
)
(state ("kicked")
(on (begin)
[when [get-boolean "is-locked"]
[set-int32 "num-attempts"
[+ 1 [get-int32 "num-attempts"]]
]
[wait-animate "self" "kick-failure"]
[go "closed"]
]
;; else...
[wait-animate "self" "kick-success"]
[go "open"]
)
)
...
Manipulating Variables
Simple commands for reading
and writing variables
Lisp/Scheme uses prex notation
(a.k.a. Polish notation)
! [+ a b] calculates (a + b)
! [set "x" [+ 1 [get "x"]]]
increments variable x
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
44
(dene-state-script ("kickable-gate")
:initial-state "closed"
:declarations (decl-list
(var "num-attempts" :type int32)
(var "is-locked" :type boolean :default #t)
)
(state ("kicked")
(on (begin)
[when [get-boolean "is-locked"]
[set-int32 "num-attempts"
[+ 1 [get-int32 "num-attempts"]]
]
[wait-animate "self" "kick-failure"]
[go "closed"]
]
;; else...
[wait-animate "self" "kick-success"]
[go "open"]
)
)
...
Manipulating Variables
Simple commands for reading
and writing variables
Lisp/Scheme uses prex notation
(a.k.a. Polish notation)
! [+ a b] calculates (a + b)
! [set "x" [+ 1 [get "x"]]]
increments variable x
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
44
(dene-state-script ("kickable-gate")
:initial-state "closed"
:declarations (decl-list
(var "num-attempts" :type int32)
(var "is-locked" :type boolean :default #t)
)
(state ("kicked")
(on (begin)
[when [get-boolean "is-locked"]
[set-int32 "num-attempts"
[+ 1 [get-int32 "num-attempts"]]
]
[wait-animate "self" "kick-failure"]
[go "closed"]
]
;; else...
[wait-animate "self" "kick-success"]
[go "open"]
)
)
...
Manipulating Variables
Simple commands for reading
and writing variables
Lisp/Scheme uses prex notation
(a.k.a. Polish notation)
! [+ a b] calculates (a + b)
! [set "x" [+ 1 [get "x"]]]
increments variable x

Monday, April 6, 2009


!"#$ &$'$()*$+, -)./$+$.0$ 1223
44
(dene-state-script ("kickable-gate")
:initial-state "closed"
:declarations (decl-list
(var "num-attempts" :type int32)
(var "is-locked" :type boolean :default #t)
)
(state ("kicked")
(on (begin)
[when [get-boolean "is-locked"]
[set-int32 "num-attempts"
[+ 1 [get-int32 "num-attempts"]]
]
[wait-animate "self" "kick-failure"]
[go "closed"]
]
;; else...
[wait-animate "self" "kick-success"]
[go "open"]
)
)
...
Manipulating Variables
Simple commands for reading
and writing variables
Lisp/Scheme uses prex notation
(a.k.a. Polish notation)
! [+ a b] calculates (a + b)
! [set "x" [+ 1 [get "x"]]]
increments variable x
Monday, April 6, 2009
All game objects have
properties (key-value pairs)
! Property values edited in
Charter
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Conguration Parameters
45
Monday, April 6, 2009
All game objects have
properties (key-value pairs)
! Property values edited in
Charter
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Conguration Parameters
45
Monday, April 6, 2009
Designers can create their
own free-form properties,
called tags
! Simply type key = value
in Tags eld
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Conguration Parameters
45
meaning-of-life = 42
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Conguration Parameters
State scripts have read-only access to game object properties...
! ... and free-form tags
46
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Conguration Parameters
State scripts have read-only access to game object properties...
! ... and free-form tags
46
(dene-state-script ("kickable-gate")
(state ("kicked")
(on (begin)
[wait-animate "self"
[tag-string "kick-anim"]
]
)
...
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Conguration Parameters
State scripts have read-only access to game object properties...
! ... and free-form tags
46
(dene-state-script ("kickable-gate")
(state ("kicked")
(on (begin)
[wait-animate "self"
[tag-string "kick-anim"]
]
)
...
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Conguration Parameters
State scripts have read-only access to game object properties...
! ... and free-form tags
46
(dene-state-script ("kickable-gate")
(state ("kicked")
(on (begin)
[wait-animate "self"
[tag-string "kick-anim"]
]
)
...
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Data Denition and Runtime
Ofine data-denition language
(Scheme) is intermingled with
runtime code
49
(dene-state-script ("kickable-gate")
(state ("locked")
(on (begin)
[print-string "Starting idle!"]
[animate "self" "locked-idle"]
)
(on (event "kicked")
[when [lock-broken?]
[print-string "BAM!"]
]
[if [task-complete? "wave2"]
[print-string "Complete!"]
[print-string "NOT!!!"]
]
)
)
...
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Data Denition and Runtime
Ofine data-denition language
(Scheme) is intermingled with
runtime code
49
(dene-state-script ("kickable-gate")
(state ("locked")
(on (begin)
[print-string "Starting idle!"]
[animate "self" "locked-idle"]
)
(on (event "kicked")
[when [lock-broken?]
[print-string "BAM!"]
]
[if [task-complete? "wave2"]
[print-string "Complete!"]
[print-string "NOT!!!"]
]
)
)
...
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Data Denition and Runtime
49
Really no different than the
distinction between declarations
and denitions in C++
class Vector3
{
private:
oat x, y, z;
public:
oat Dot(const Vector3& b)
{
return (x * b.x
+ y * b.y
+ z * b.z);
}
...
};
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Data Denition and Runtime
49
Really no different than the
distinction between declarations
and denitions in C++
class Vector3
{
private:
oat x, y, z;
public:
oat Dot(const Vector3& b)
{
return (x * b.x
+ y * b.y
+ z * b.z);
}
...
};
Monday, April 6, 2009
Case Studies
4:
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Custom Object Type: Breakable Sign
4;
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Custom Object Type: Breakable Sign
4;
Monday, April 6, 2009
(dene-state-script ("falling-sign")
(state ("untouched")
(on (update)
[when [task-complete? "wz-post-combat"]
[go "fallen"]
]
)
(on (event "hanging-from")
[go "breaking"]
)
)
...
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Custom Object Type: Breakable Sign
43
Monday, April 6, 2009
(dene-state-script ("falling-sign")
(state ("untouched")
(on (update)
[when [task-complete? "wz-post-combat"]
[go "fallen"]
]
)
(on (event "hanging-from")
[go "breaking"]
)
)
...
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Custom Object Type: Breakable Sign
43
Monday, April 6, 2009
(dene-state-script ("falling-sign")
(state ("untouched")
(on (update)
[when [task-complete? "wz-post-combat"]
[go "fallen"]
]
)
(on (event "hanging-from")
[go "breaking"]
)
)
...
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Custom Object Type: Breakable Sign
43
Monday, April 6, 2009
(state ("breaking")
(on (begin)
[spawn-particles-at-joint "self"
"hinge"
"sign-break-dust"]
[wait-animate "self" "sign-break"]
[go "fallen"]
)
)
(state ("fallen")
(on (begin)
[animate "self" "sign-broken"] ;; looping
)
)
)
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Custom Object Type: Breakable Sign
43
Monday, April 6, 2009
(state ("breaking")
(on (begin)
[spawn-particles-at-joint "self"
"hinge"
"sign-break-dust"]
[wait-animate "self" "sign-break"]
[go "fallen"]
)
)
(state ("fallen")
(on (begin)
[animate "self" "sign-broken"] ;; looping
)
)
)
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Custom Object Type: Breakable Sign
43
Monday, April 6, 2009
(state ("breaking")
(on (begin)
[spawn-particles-at-joint "self"
"hinge"
"sign-break-dust"]
[wait-animate "self" "sign-break"]
[go "fallen"]
)
)
(state ("fallen")
(on (begin)
[animate "self" "sign-broken"] ;; looping
)
)
)
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Custom Object Type: Breakable Sign
43
Monday, April 6, 2009
(state ("breaking")
(on (begin)
[spawn-particles-at-joint "self"
"hinge"
"sign-break-dust"]
[wait-animate "self" "sign-break"]
[go "fallen"]
)
)
(state ("fallen")
(on (begin)
[animate "self" "sign-broken"] ;; looping
)
)
)
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Custom Object Type: Breakable Sign
43
Monday, April 6, 2009
(state ("breaking")
(on (begin)
[spawn-particles-at-joint "self"
"hinge"
"sign-break-dust"]
[wait-animate "self" "sign-break"]
[go "fallen"]
)
)
(state ("fallen")
(on (begin)
[animate "self" "sign-broken"] ;; looping
)
)
)
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Custom Object Type: Breakable Sign
43
Monday, April 6, 2009
(state ("breaking")
(on (begin)
[spawn-particles-at-joint "self"
"hinge"
"sign-break-dust"]
[wait-animate "self" "sign-break"]
[go "fallen"]
)
)
(state ("fallen")
(on (begin)
[animate "self" "sign-broken"] ;; looping
)
)
)
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Custom Object Type: Breakable Sign
43
Monday, April 6, 2009
(state ("breaking")
(on (begin)
[spawn-particles-at-joint "self"
"hinge"
"sign-break-dust"]
[wait-animate "self" "sign-break"]
[go "fallen"]
)
)
(state ("fallen")
(on (begin)
[animate "self" "sign-broken"] ;; looping
)
)
)
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Custom Object Type: Breakable Sign
43
Monday, April 6, 2009
(state ("breaking")
(on (begin)
[spawn-particles-at-joint "self"
"hinge"
"sign-break-dust"]
[wait-animate "self" "sign-break"]
[go "fallen"]
)
)
(state ("fallen")
(on (begin)
[animate "self" "sign-broken"] ;; looping
)
)
)
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Custom Object Type: Breakable Sign
43
Monday, April 6, 2009
(state ("breaking")
(on (begin)
[spawn-particles-at-joint "self"
"hinge"
"sign-break-dust"]
[wait-animate "self" "sign-break"]
[go "fallen"]
)
)
(state ("fallen")
(on (begin)
[animate "self" "sign-broken"] ;; looping
)
)
)
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Custom Object Type: Breakable Sign
43
Monday, April 6, 2009
(dene-state-script ("falling-sign")
(state ("untouched")
(on (update)
[when [task-complete? "wz-post-combat"]
[go "fallen"]
]
)
(on (event "hanging-from")
[go "breaking"]
)
)
...
(state ("breaking")
(on (begin)
[spawn-particles-at-joint "self"
"hinge"
"sign-break-dust"]
[wait-animate "self" "sign-break"]
[go "fallen"]
)
)
(state ("fallen")
(on (begin)
[animate "self" "sign-broken"] ;; looping
)
)
)
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Custom Object Type: Breakable Sign
43
Monday, April 6, 2009
(dene-state-script ("falling-sign")
(state ("untouched")
(on (update)
[when [task-complete? "wz-post-combat"]
[go "fallen"]
]
)
(on (event "hanging-from")
[go "breaking"]
)
)
...
(state ("breaking")
(on (begin)
[spawn-particles-at-joint "self"
"hinge"
"sign-break-dust"]
[wait-animate "self" "sign-break"]
[go "fallen"]
)
)
(state ("fallen")
(on (begin)
[animate "self" "sign-broken"] ;; looping
)
)
)
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Custom Object Type: Breakable Sign
43
Monday, April 6, 2009
(dene-state-script ("falling-sign")
(state ("untouched")
(on (update)
[when [task-complete? "wz-post-combat"]
[go "fallen"]
]
)
(on (event "hanging-from")
[go "breaking"]
)
)
...
(state ("breaking")
(on (begin)
[spawn-particles-at-joint "self"
"hinge"
"sign-break-dust"]
[wait-animate "self" "sign-break"]
[go "fallen"]
)
)
(state ("fallen")
(on (begin)
[animate "self" "sign-broken"] ;; looping
)
)
)
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Custom Object Type: Breakable Sign
43
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Making the Sign Script Generic
52
(dene-state-script ("simple-animating-obj")
(state ("initial")
(on (update)
[when [task-complete?
[tag-string "done-task"]]
[go "done"]
]
)
(on (event "hanging-from")
[go "animating"]
)
)
...
(state ("animating")
(on (begin)
[spawn-particles-at-joint "self"
[tag-string "particle-joint"]
[tag-string "particle-name"]]
[wait-animate "self"
[tag-string "anim-name"]]
[go "done"]
)
)
(state ("done")
(on (begin)
[animate "self"
[tag-string "done-anim-name"]]
)
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Making the Sign Script Generic
52
(dene-state-script ("simple-animating-obj")
(state ("initial")
(on (update)
[when [task-complete?
[tag-string "done-task"]]
[go "done"]
]
)
(on (event "hanging-from")
[go "animating"]
)
)
...
(state ("animating")
(on (begin)
[spawn-particles-at-joint "self"
[tag-string "particle-joint"]
[tag-string "particle-name"]]
[wait-animate "self"
[tag-string "anim-name"]]
[go "done"]
)
)
(state ("done")
(on (begin)
[animate "self"
[tag-string "done-anim-name"]]
)
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Making the Sign Script Generic
52
(dene-state-script ("simple-animating-obj")
(state ("initial")
(on (update)
[when [task-complete?
[tag-string "done-task"]]
[go "done"]
]
)
(on (event "hanging-from")
[go "animating"]
)
)
...
(state ("animating")
(on (begin)
[spawn-particles-at-joint "self"
[tag-string "particle-joint"]
[tag-string "particle-name"]]
[wait-animate "self"
[tag-string "anim-name"]]
[go "done"]
)
)
(state ("done")
(on (begin)
[animate "self"
[tag-string "done-anim-name"]]
)
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Making the Sign Script Generic
52
(dene-state-script ("simple-animating-obj")
(state ("initial")
(on (update)
[when [task-complete?
[tag-string "done-task"]]
[go "done"]
]
)
(on (event "hanging-from")
[go "animating"]
)
)
...
(state ("animating")
(on (begin)
[spawn-particles-at-joint "self"
[tag-string "particle-joint"]
[tag-string "particle-name"]]
[wait-animate "self"
[tag-string "anim-name"]]
[go "done"]
)
)
(state ("done")
(on (begin)
[animate "self"
[tag-string "done-anim-name"]]
)
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Making the Sign Script Generic
52
(dene-state-script ("simple-animating-obj")
(state ("initial")
(on (update)
[when [task-complete?
[tag-string "done-task"]]
[go "done"]
]
)
(on (event "hanging-from")
[go "animating"]
)
)
...
(state ("animating")
(on (begin)
[spawn-particles-at-joint "self"
[tag-string "particle-joint"]
[tag-string "particle-name"]]
[wait-animate "self"
[tag-string "anim-name"]]
[go "done"]
)
)
(state ("done")
(on (begin)
[animate "self"
[tag-string "done-anim-name"]]
)
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Making the Sign Script Generic
52
(dene-state-script ("simple-animating-obj")
(state ("initial")
(on (update)
[when [task-complete?
[tag-string "done-task"]]
[go "done"]
]
)
(on (event "hanging-from")
[go "animating"]
)
)
...
(state ("animating")
(on (begin)
[spawn-particles-at-joint "self"
[tag-string "particle-joint"]
[tag-string "particle-name"]]
[wait-animate "self"
[tag-string "anim-name"]]
[go "done"]
)
)
(state ("done")
(on (begin)
[animate "self"
[tag-string "done-anim-name"]]
)
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Making the Sign Script Generic
52
(dene-state-script ("simple-animating-obj")
(state ("initial")
(on (update)
[when [task-complete?
[tag-string "done-task"]]
[go "done"]
]
)
(on (event "hanging-from")
[go "animating"]
)
)
...
(state ("animating")
(on (begin)
[spawn-particles-at-joint "self"
[tag-string "particle-joint"]
[tag-string "particle-name"]]
[wait-animate "self"
[tag-string "anim-name"]]
[go "done"]
)
)
(state ("done")
(on (begin)
[animate "self"
[tag-string "done-anim-name"]]
)
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Making the Sign Script Generic
52
(dene-state-script ("simple-animating-obj")
(state ("initial")
(on (update)
[when [task-complete?
[tag-string "done-task"]]
[go "done"]
]
)
(on (event "hanging-from")
[go "animating"]
)
)
...
(state ("animating")
(on (begin)
[spawn-particles-at-joint "self"
[tag-string "particle-joint"]
[tag-string "particle-name"]]
[wait-animate "self"
[tag-string "anim-name"]]
[go "done"]
)
)
(state ("done")
(on (begin)
[animate "self"
[tag-string "done-anim-name"]]
)
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Making the Sign Script Generic
52
(dene-state-script ("simple-animating-obj")
(state ("initial")
(on (update)
[when [task-complete?
[tag-string "done-task"]]
[go "done"]
]
)
(on (event "hanging-from")
[go "animating"]
)
)
...
(state ("animating")
(on (begin)
[spawn-particles-at-joint "self"
[tag-string "particle-joint"]
[tag-string "particle-name"]]
[wait-animate "self"
[tag-string "anim-name"]]
[go "done"]
)
)
(state ("done")
(on (begin)
[animate "self"
[tag-string "done-anim-name"]]
)
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Making the Sign Script Generic
52
(dene-state-script ("simple-animating-obj")
(state ("initial")
(on (update)
[when [task-complete?
[tag-string "done-task"]]
[go "done"]
]
)
(on (event "hanging-from")
[go "animating"]
)
)
...
(state ("animating")
(on (begin)
[spawn-particles-at-joint "self"
[tag-string "particle-joint"]
[tag-string "particle-name"]]
[wait-animate "self"
[tag-string "anim-name"]]
[go "done"]
)
)
(state ("done")
(on (begin)
[animate "self"
[tag-string "done-anim-name"]]
)
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
In-Game Debugging
5<
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
In-Game Debugging
5<
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
In-Game Debugging
5<
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
In-Game Debugging
5<
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
In-Game Debugging
5<
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
In-Game Debugging
5<
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
In-Game Cinematic: Bus Crash
51
Monday, April 6, 2009
(state ("crash")
(on (begin)
(track ("bus")
[wait-animate "bus-1" "bus-crash"
[get-locator "ref-bus-crash-1"]]
[signal "bus-done"]
)
(track ("player")
[animate "player" "player-watch-crash"
[get-locator "ref-bus-crash-1"]]
[wait-until-frame 250]
[say "player" "vox-wz-drk-01-what-the"]
[signal "drake-done"]
)
...
!"#$ &$'$()*$+, -)./$+$.0$ 1223
In-Game Cinematic: Bus Crash
54
(dene-state-script ("wz-bus-crash")
(state ("spawn-soldiers")
(on (begin)
[player-disable-controls
(controls all-but-right-stick)]
[spawn-npc-in-combat "npc-wz-52"]
[spawn-npc-in-combat "npc-wz-53"]
...
[go "crash"]
)
)
...
Monday, April 6, 2009
(state ("crash")
(on (begin)
(track ("bus")
[wait-animate "bus-1" "bus-crash"
[get-locator "ref-bus-crash-1"]]
[signal "bus-done"]
)
(track ("player")
[animate "player" "player-watch-crash"
[get-locator "ref-bus-crash-1"]]
[wait-until-frame 250]
[say "player" "vox-wz-drk-01-what-the"]
[signal "drake-done"]
)
...
!"#$ &$'$()*$+, -)./$+$.0$ 1223
In-Game Cinematic: Bus Crash
54
(dene-state-script ("wz-bus-crash")
(state ("spawn-soldiers")
(on (begin)
[player-disable-controls
(controls all-but-right-stick)]
[spawn-npc-in-combat "npc-wz-52"]
[spawn-npc-in-combat "npc-wz-53"]
...
[go "crash"]
)
)
...
Monday, April 6, 2009
(state ("crash")
(on (begin)
(track ("bus")
[wait-animate "bus-1" "bus-crash"
[get-locator "ref-bus-crash-1"]]
[signal "bus-done"]
)
(track ("player")
[animate "player" "player-watch-crash"
[get-locator "ref-bus-crash-1"]]
[wait-until-frame 250]
[say "player" "vox-wz-drk-01-what-the"]
[signal "drake-done"]
)
...
!"#$ &$'$()*$+, -)./$+$.0$ 1223
In-Game Cinematic: Bus Crash
54
(dene-state-script ("wz-bus-crash")
(state ("spawn-soldiers")
(on (begin)
[player-disable-controls
(controls all-but-right-stick)]
[spawn-npc-in-combat "npc-wz-52"]
[spawn-npc-in-combat "npc-wz-53"]
...
[go "crash"]
)
)
...
Monday, April 6, 2009
(state ("crash")
(on (begin)
(track ("bus")
[wait-animate "bus-1" "bus-crash"
[get-locator "ref-bus-crash-1"]]
[signal "bus-done"]
)
(track ("player")
[animate "player" "player-watch-crash"
[get-locator "ref-bus-crash-1"]]
[wait-until-frame 250]
[say "player" "vox-wz-drk-01-what-the"]
[signal "drake-done"]
)
...
!"#$ &$'$()*$+, -)./$+$.0$ 1223
In-Game Cinematic: Bus Crash
54
(dene-state-script ("wz-bus-crash")
(state ("spawn-soldiers")
(on (begin)
[player-disable-controls
(controls all-but-right-stick)]
[spawn-npc-in-combat "npc-wz-52"]
[spawn-npc-in-combat "npc-wz-53"]
...
[go "crash"]
)
)
...
Monday, April 6, 2009
(state ("crash")
(on (begin)
(track ("bus")
[wait-animate "bus-1" "bus-crash"
[get-locator "ref-bus-crash-1"]]
[signal "bus-done"]
)
(track ("player")
[animate "player" "player-watch-crash"
[get-locator "ref-bus-crash-1"]]
[wait-until-frame 250]
[say "player" "vox-wz-drk-01-what-the"]
[signal "drake-done"]
)
...
!"#$ &$'$()*$+, -)./$+$.0$ 1223
In-Game Cinematic: Bus Crash
54
(dene-state-script ("wz-bus-crash")
(state ("spawn-soldiers")
(on (begin)
[player-disable-controls
(controls all-but-right-stick)]
[spawn-npc-in-combat "npc-wz-52"]
[spawn-npc-in-combat "npc-wz-53"]
...
[go "crash"]
)
)
...
Monday, April 6, 2009
(state ("crash")
(on (begin)
(track ("bus")
[wait-animate "bus-1" "bus-crash"
[get-locator "ref-bus-crash-1"]]
[signal "bus-done"]
)
(track ("player")
[animate "player" "player-watch-crash"
[get-locator "ref-bus-crash-1"]]
[wait-until-frame 250]
[say "player" "vox-wz-drk-01-what-the"]
[signal "drake-done"]
)
...
!"#$ &$'$()*$+, -)./$+$.0$ 1223
In-Game Cinematic: Bus Crash
54
(dene-state-script ("wz-bus-crash")
(state ("spawn-soldiers")
(on (begin)
[player-disable-controls
(controls all-but-right-stick)]
[spawn-npc-in-combat "npc-wz-52"]
[spawn-npc-in-combat "npc-wz-53"]
...
[go "crash"]
)
)
...
Monday, April 6, 2009
(state ("crash")
(on (begin)
(track ("bus")
[wait-animate "bus-1" "bus-crash"
[get-locator "ref-bus-crash-1"]]
[signal "bus-done"]
)
(track ("player")
[animate "player" "player-watch-crash"
[get-locator "ref-bus-crash-1"]]
[wait-until-frame 250]
[say "player" "vox-wz-drk-01-what-the"]
[signal "drake-done"]
)
...
!"#$ &$'$()*$+, -)./$+$.0$ 1223
In-Game Cinematic: Bus Crash
54
(dene-state-script ("wz-bus-crash")
(state ("spawn-soldiers")
(on (begin)
[player-disable-controls
(controls all-but-right-stick)]
[spawn-npc-in-combat "npc-wz-52"]
[spawn-npc-in-combat "npc-wz-53"]
...
[go "crash"]
)
)
...
Monday, April 6, 2009
(state ("crash")
...
(track ("guy-hit-by-bus")
[wait-animate "npc-wz-52" "npc-hit-by-bus"
[get-locator "ref-bus-crash-1"]]
[npc-die "npc-wz-52"]
[signal "npc-dead"]
)
(track ("wait-for-all-done")
[wait-for-signal "bus-done"]
[wait-for-signal "drake-done"]
[wait-for-signal "npc-dead"]
[go "done"]
)
)
)
(state ("done")
...
!"#$ &$'$()*$+, -)./$+$.0$ 1223
In-Game Cinematic: Bus Crash
54
(dene-state-script ("wz-bus-crash")
(state ("spawn-soldiers")
(on (begin)
[player-disable-controls
(controls all-but-right-stick)]
[spawn-npc-in-combat "npc-wz-52"]
[spawn-npc-in-combat "npc-wz-53"]
...
[go "crash"]
)
)
...
Monday, April 6, 2009
(state ("crash")
...
(track ("guy-hit-by-bus")
[wait-animate "npc-wz-52" "npc-hit-by-bus"
[get-locator "ref-bus-crash-1"]]
[npc-die "npc-wz-52"]
[signal "npc-dead"]
)
(track ("wait-for-all-done")
[wait-for-signal "bus-done"]
[wait-for-signal "drake-done"]
[wait-for-signal "npc-dead"]
[go "done"]
)
)
)
(state ("done")
...
!"#$ &$'$()*$+, -)./$+$.0$ 1223
In-Game Cinematic: Bus Crash
54
(dene-state-script ("wz-bus-crash")
(state ("spawn-soldiers")
(on (begin)
[player-disable-controls
(controls all-but-right-stick)]
[spawn-npc-in-combat "npc-wz-52"]
[spawn-npc-in-combat "npc-wz-53"]
...
[go "crash"]
)
)
...
Monday, April 6, 2009
(state ("crash")
...
(track ("guy-hit-by-bus")
[wait-animate "npc-wz-52" "npc-hit-by-bus"
[get-locator "ref-bus-crash-1"]]
[npc-die "npc-wz-52"]
[signal "npc-dead"]
)
(track ("wait-for-all-done")
[wait-for-signal "bus-done"]
[wait-for-signal "drake-done"]
[wait-for-signal "npc-dead"]
[go "done"]
)
)
)
(state ("done")
...
!"#$ &$'$()*$+, -)./$+$.0$ 1223
In-Game Cinematic: Bus Crash
54
(dene-state-script ("wz-bus-crash")
(state ("spawn-soldiers")
(on (begin)
[player-disable-controls
(controls all-but-right-stick)]
[spawn-npc-in-combat "npc-wz-52"]
[spawn-npc-in-combat "npc-wz-53"]
...
[go "crash"]
)
)
...
Monday, April 6, 2009
(state ("crash")
...
(track ("guy-hit-by-bus")
[wait-animate "npc-wz-52" "npc-hit-by-bus"
[get-locator "ref-bus-crash-1"]]
[npc-die "npc-wz-52"]
[signal "npc-dead"]
)
(track ("wait-for-all-done")
[wait-for-signal "bus-done"]
[wait-for-signal "drake-done"]
[wait-for-signal "npc-dead"]
[go "done"]
)
)
)
(state ("done")
...
!"#$ &$'$()*$+, -)./$+$.0$ 1223
In-Game Cinematic: Bus Crash
54
(dene-state-script ("wz-bus-crash")
(state ("spawn-soldiers")
(on (begin)
[player-disable-controls
(controls all-but-right-stick)]
[spawn-npc-in-combat "npc-wz-52"]
[spawn-npc-in-combat "npc-wz-53"]
...
[go "crash"]
)
)
...
Monday, April 6, 2009
(state ("crash")
...
(track ("guy-hit-by-bus")
[wait-animate "npc-wz-52" "npc-hit-by-bus"
[get-locator "ref-bus-crash-1"]]
[npc-die "npc-wz-52"]
[signal "npc-dead"]
)
(track ("wait-for-all-done")
[wait-for-signal "bus-done"]
[wait-for-signal "drake-done"]
[wait-for-signal "npc-dead"]
[go "done"]
)
)
)
(state ("done")
...
!"#$ &$'$()*$+, -)./$+$.0$ 1223
In-Game Cinematic: Bus Crash
54
(dene-state-script ("wz-bus-crash")
(state ("spawn-soldiers")
(on (begin)
[player-disable-controls
(controls all-but-right-stick)]
[spawn-npc-in-combat "npc-wz-52"]
[spawn-npc-in-combat "npc-wz-53"]
...
[go "crash"]
)
)
...
Monday, April 6, 2009
Implementation
55
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Virtual Machine
Scheme-like runtime language implemented by a simple VM
! Each track compiled into block of byte code called a lambda
56
(dene-state-script ("kickable-gate")
(state ("locked")
(on (begin)
(track ("gate")
...
)
(track ("lock")
...
)
)
)
)
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Virtual Machine
Scheme-like runtime language implemented by a simple VM
! Each track compiled into block of byte code called a lambda
56
(dene-state-script ("kickable-gate")
(state ("locked")
(on (begin)
(track ("gate")
...
)
(track ("lock")
...
)
)
)
)
opcode1 )*$+".C< )*$+".C1
opcode2
opcode3 )*$+".C4
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Virtual Machine
Scheme-like runtime language implemented by a simple VM
! Each track compiled into block of byte code called a lambda
56
(dene-state-script ("kickable-gate")
(state ("locked")
(on (begin)
(track ("gate")
...
)
(track ("lock")
...
)
)
)
)
opcode1 )*$+".C< )*$+".C1
opcode2
opcode3 )*$+".C4
opcode4 )*$+".C5
opcodeS )*$+".C6
opcode6
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Virtual Machine
Internal state of VM consists of:
! Pointer to current lambda
(byte code program)
! Index to current instruction
! Bank of registers for temporary
and immediate data
Registers are of type variant
59
0B+ F.,@+
|ambda
___
___
___
+$I2
+$I<
+$I1
+$I5
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Virtual Machine
Internal state of VM consists of:
! Pointer to current lambda
(byte code program)
! Index to current instruction
! Bank of registers for temporary
and immediate data
Registers are of type variant
59
0B+ F.,@+
|ambda
___
___
___
+$I2
+$I<
+$I1
+$I5
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Virtual Machine
Internal state of VM consists of:
! Pointer to current lambda
(byte code program)
! Index to current instruction
! Bank of registers for temporary
and immediate data
Registers are of type variant
59
0B+ F.,@+
|ambda
___
___
___
+$I2
+$I<
+$I1
+$I5
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Virtual Machine
Language supports nested
function calls
Hence requires call stack
! Stack frame = bank of
registers + program counter
5:
|ambda
___
___
___
___
0B+ F.,@+
+$I2
+$I<
+$I1
+$I5
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Virtual Machine
Language supports nested
function calls
Hence requires call stack
! Stack frame = bank of
registers + program counter
5:
|ambda
___
___
___
___
0B+ F.,@+
+$I2
+$I<
+$I1
+$I5
0B+ F.,@+
+$I2
+$I<
+$I1
+$I5
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Virtual Machine
Language supports nested
function calls
Hence requires call stack
! Stack frame = bank of
registers + program counter
5:
0B+ F.,@+
|ambda
___
___
___
___
+$I2
+$I<
+$I1
+$I5
0B+ F.,@+
+$I2
+$I<
+$I1
+$I5
0B+ F.,@+
+$I2
+$I<
+$I1
+$I5
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Virtual Machine
Language supports nested
function calls
Hence requires call stack
! Stack frame = bank of
registers + program counter
5:
|ambda
___
___
___
___
0B+ F.,@+
+$I2
+$I<
+$I1
+$I5
0B+ F.,@+
+$I2
+$I<
+$I1
+$I5
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Continuations
State script code can wait (sleep)
Implemented via something
known as a continuation
5;
|ambda
___
___
___
___
0B+ F.,@+
+$I2
+$I<
+$I1
+$I5
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Continuations
State script code can wait (sleep)
Implemented via something
known as a continuation
5;
|ambda
___
___
___
___
0B+ F.,@+
+$I2
+$I<
+$I1
+$I5
0B+ F.,@+
+$I2
+$I<
+$I1
+$I5
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Continuations
State script code can wait (sleep)
Implemented via something
known as a continuation
5;
|ambda
___
___
___
___
connnuanon
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Continuations
State script code can wait (sleep)
Implemented via something
known as a continuation
5;
|ambda
___
___
___
___
0B+ F.,@+
+$I2
+$I<
+$I1
+$I5
0B+ F.,@+
+$I2
+$I<
+$I1
+$I5
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Continuations
State script code can wait (sleep)
Implemented via something
known as a continuation
5;
0B+ F.,@+
|ambda
___
___
___
___
+$I2
+$I<
+$I1
+$I5
0B+ F.,@+
+$I2
+$I<
+$I1
+$I5
0B+ F.,@+
+$I2
+$I<
+$I1
+$I5
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Native C++ Functions
The meat of an (on ...) block is its command sequence
! Some commands are user-dened: (defun func1 (...))
! Most commands are C++ hooks into the engine
Simple hash table maps function names to C++ code
53
(dene-c-function wait-animate
(object-name string)
(anim-name string)
)
Variant ScriptWaitAnimate(int argc, Variant* argv)
{
...
}
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
62
Variant ScriptWaitAnimate(int argc, Variant* argv)
{
StringId objName = SC_ARG(0, StringId, NULL);
StringId animName = SC_ARG(1, StringId, NULL);
if (!objName)
return ScriptError("wait-animate: expected object name (arg1)\n");
if (!animName)
return ScriptError("wait-animate: expected animation name (arg2)\n");
// nd the object
ProcessGameObject* pObj = g_processMgr.Lookup(objName);
if (!pObj)
return ScriptError("wait-animate: could not nd %s\n",
StringIdToString(objName));
// instruct object to play animation, and wake up this script when done
pObj->WaitAnimate(animName, g_scriptContext);
g_scriptContext.Suspend(); // go to sleep until anim is done
return Variant(true);
}
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
6<
Monday, April 6, 2009
Conclusion
61
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Key Features
Key features of a successful scripting system:
! Virtual machine integrated into game engine
! Ability to run code every frame (update)
! Ability to respond to events, and send events
! Ability to reference game objects (by handle, unique id, etc.)
! Ability to manipulate game objects
! Designers can dene new object types in script
64
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Architectural Styles
Many different engine-script architectures:
! script drives engine (engine just a library called by script)
! engine drives script...
simple scripted event handlers
scripted properties or components
scripted game object classes
65
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Some Advice...
Good debugging tools are crucial
! Understandable error messages from compiler
! In-game display of running scripts, or some kind of debugger
! Simple logging to TTY/console (e.g. [print-string "message"])
Watch for race conditions
! Event arrives too early or too latemissed
! Object youre trying to control hasnt spawned yet, or has died
! Tracks not synchronized properly
66
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
With Great Power...
... comes great responsibility
Your designers can now:
! break the build
! introduce progression stoppers
! crash the game
Take the leap of faith, but...
! PLAN FOR IT!
69
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
With Great Power...
... comes great responsibility
Your designers can now:
! break the build
! introduce progression stoppers
! crash the game
Take the leap of faith, but...
! PLAN FOR IT!
69
Monday, April 6, 2009
!"#$ &$'$()*$+, -)./$+$.0$ 1223
Thanks For Listening!
Free free to send questions to me at:
[email protected]
Naughty Dog is hiring! Send resumes to Candace Walker at:
[email protected]
6:
Monday, April 6, 2009

You might also like