StateScriptingInUncharted2
Upcoming SlideShare
Loading in...5
×
 

StateScriptingInUncharted2

on

  • 776 views

GDC09-JQGregory-StateScriptingInUncharted2.key

GDC09-JQGregory-StateScriptingInUncharted2.key

Statistics

Views

Total Views
776
Views on SlideShare
775
Embed Views
1

Actions

Likes
0
Downloads
21
Comments
0

1 Embed 1

http://www.slideshare.net 1

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • Content creators gain an improved sense of ownership and empowerment. <br /> Engineering team is often a bottleneck; expensive resource. <br /> Treating code like data allows it to be modified and tested without requiring an engineer to recompile and relink the game. <br /> Some engines support on the fly script reloading—don’t even need to rerun the game. <br />
  • Data def languages allow data structures to be populated for consumption by engine. <br /> Some data def languages even allow data structures to be defined by the scripter. <br /> Runtime languages are typically: <br /> Interpreted. Compiled into byte code, executed by a virtual machine (VM). <br /> Simple and small. Easy to parse; virtual machine has minimal overhead. <br /> Accessible. Designers, artists and other “non-programmers” can use it. <br /> Powerful. Small amount of code = big impact on game. <br />
  • We use PLT Scheme (a Lisp variant) for data definition (http://www.plt-scheme.org). <br /> A simplified version of Scheme/Lisp (“Scheme lite”) is used for runtime scripting. <br /> Runtime code is a special kind of lambda. <br /> <br />
  • <br />
  • The game object model: <br /> Defines the various object types that populate the game world. <br /> (Player, NPC, weapon, power-up, light, trigger region, AI nav poly, camera, ...) <br /> Often, but not always, implemented using an object-oriented language. <br /> ore details, see: <br /> Jason Gregory. Game Engine Architecture: A Comprehensive Guide. AK Peters, 2009. <br />
  • <br />
  • <br />
  • “Lego block” approach to constructing new game object types <br /> Components can be authored in native C++ or in script <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • The world editor for Uncharted is called Charter. <br /> Place game objects, trigger regions, splines, etc. <br /> Edit object properties. <br /> Control level streaming. <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • Uncharted task system defines player objectives, flow of control from “level” to “level” <br /> Tasks are primary save-game mechanism <br /> Task scripts are automatically killed when the task is completed <br /> <br />
  • Uncharted task system defines player objectives, flow of control from “level” to “level” <br /> Tasks are primary save-game mechanism <br /> Task scripts are automatically killed when the task is completed <br /> <br />
  • Uncharted task system defines player objectives, flow of control from “level” to “level” <br /> Tasks are primary save-game mechanism <br /> Task scripts are automatically killed when the task is completed <br /> <br />
  • Uncharted task system defines player objectives, flow of control from “level” to “level” <br /> Tasks are primary save-game mechanism <br /> Task scripts are automatically killed when the task is completed <br /> <br />
  • Uncharted task system defines player objectives, flow of control from “level” to “level” <br /> Tasks are primary save-game mechanism <br /> Task scripts are automatically killed when the task is completed <br /> <br />
  • Uncharted task system defines player objectives, flow of control from “level” to “level” <br /> Tasks are primary save-game mechanism <br /> Task scripts are automatically killed when the task is completed <br /> <br />
  • Uncharted task system defines player objectives, flow of control from “level” to “level” <br /> Tasks are primary save-game mechanism <br /> Task scripts are automatically killed when the task is completed <br /> <br />
  • Uncharted task system defines player objectives, flow of control from “level” to “level” <br /> Tasks are primary save-game mechanism <br /> Task scripts are automatically killed when the task is completed <br /> <br />
  • Uncharted task system defines player objectives, flow of control from “level” to “level” <br /> Tasks are primary save-game mechanism <br /> Task scripts are automatically killed when the task is completed <br /> <br />
  • Uncharted task system defines player objectives, flow of control from “level” to “level” <br /> Tasks are primary save-game mechanism <br /> Task scripts are automatically killed when the task is completed <br /> <br />
  • Uncharted task system defines player objectives, flow of control from “level” to “level” <br /> Tasks are primary save-game mechanism <br /> Task scripts are automatically killed when the task is completed <br /> <br />
  • Uncharted task system defines player objectives, flow of control from “level” to “level” <br /> Tasks are primary save-game mechanism <br /> Task scripts are automatically killed when the task is completed <br /> <br />
  • Uncharted task system defines player objectives, flow of control from “level” to “level” <br /> Tasks are primary save-game mechanism <br /> Task scripts are automatically killed when the task is completed <br /> <br />
  • <br />
  • <br />
  • Square [brackets] can be used interchangeably with (parens) <br />
  • Square [brackets] can be used interchangeably with (parens) <br />
  • Square [brackets] can be used interchangeably with (parens) <br />
  • Square [brackets] can be used interchangeably with (parens) <br />
  • Square [brackets] can be used interchangeably with (parens) <br />
  • Events identified by free-form strings <br /> Three special block types: <br /> (on (begin) ...) Executed when state is first entered <br /> (on (update) ...) Executed once every frame <br /> (on (end) ...) Executed when state is exited <br />
  • Events identified by free-form strings <br /> Three special block types: <br /> (on (begin) ...) Executed when state is first entered <br /> (on (update) ...) Executed once every frame <br /> (on (end) ...) Executed when state is exited <br />
  • Events identified by free-form strings <br /> Three special block types: <br /> (on (begin) ...) Executed when state is first entered <br /> (on (update) ...) Executed once every frame <br /> (on (end) ...) Executed when state is exited <br />
  • Events identified by free-form strings <br /> Three special block types: <br /> (on (begin) ...) Executed when state is first entered <br /> (on (update) ...) Executed once every frame <br /> (on (end) ...) Executed when state is exited <br />
  • Events identified by free-form strings <br /> Three special block types: <br /> (on (begin) ...) Executed when state is first entered <br /> (on (update) ...) Executed once every frame <br /> (on (end) ...) Executed when state is exited <br />
  • Events identified by free-form strings <br /> Three special block types: <br /> (on (begin) ...) Executed when state is first entered <br /> (on (update) ...) Executed once every frame <br /> (on (end) ...) Executed when state is exited <br />
  • Events identified by free-form strings <br /> Three special block types: <br /> (on (begin) ...) Executed when state is first entered <br /> (on (update) ...) Executed once every frame <br /> (on (end) ...) Executed when state is exited <br />
  • Runtime script code exists inside (on ...) blocks. <br /> Runtime language is simplified Scheme: <br /> Imperative style. <br /> Most “commands” are native function calls into C++ code (hooks into the engine). <br /> Language also supports conditional expressions. For example: <br /> (when (condition) (do-if-true)) <br /> (if (condition) (do-if-true) (do-if-false)) <br />
  • Runtime script code exists inside (on ...) blocks. <br /> Runtime language is simplified Scheme: <br /> Imperative style. <br /> Most “commands” are native function calls into C++ code (hooks into the engine). <br /> Language also supports conditional expressions. For example: <br /> (when (condition) (do-if-true)) <br /> (if (condition) (do-if-true) (do-if-false)) <br />
  • Runtime script code exists inside (on ...) blocks. <br /> Runtime language is simplified Scheme: <br /> Imperative style. <br /> Most “commands” are native function calls into C++ code (hooks into the engine). <br /> Language also supports conditional expressions. For example: <br /> (when (condition) (do-if-true)) <br /> (if (condition) (do-if-true) (do-if-false)) <br />
  • Runtime script code exists inside (on ...) blocks. <br /> Runtime language is simplified Scheme: <br /> Imperative style. <br /> Most “commands” are native function calls into C++ code (hooks into the engine). <br /> Language also supports conditional expressions. For example: <br /> (when (condition) (do-if-true)) <br /> (if (condition) (do-if-true) (do-if-false)) <br />
  • Runtime script code exists inside (on ...) blocks. <br /> Runtime language is simplified Scheme: <br /> Imperative style. <br /> Most “commands” are native function calls into C++ code (hooks into the engine). <br /> Language also supports conditional expressions. For example: <br /> (when (condition) (do-if-true)) <br /> (if (condition) (do-if-true) (do-if-false)) <br />
  • Functions in Lisp are called “lambdas” <br />
  • Functions in Lisp are called “lambdas” <br />
  • Functions in Lisp are called “lambdas” <br />
  • Functions in Lisp are called “lambdas” <br />
  • Functions in Lisp are called “lambdas” <br />
  • Functions in Lisp are called “lambdas” <br />
  • Functions in Lisp are called “lambdas” <br />
  • Functions in Lisp are called “lambdas” <br />
  • Functions in Lisp are called “lambdas” <br />
  • Functions in Lisp are called “lambdas” <br />
  • Functions in Lisp are called “lambdas” <br />
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string <br /> “self” is much like the this pointer in C++ <br /> Very convenient, since many scripts are designed to control the object to which they are attached <br /> Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.) <br />
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string <br /> “self” is much like the this pointer in C++ <br /> Very convenient, since many scripts are designed to control the object to which they are attached <br /> Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.) <br />
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string <br /> “self” is much like the this pointer in C++ <br /> Very convenient, since many scripts are designed to control the object to which they are attached <br /> Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.) <br />
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string <br /> “self” is much like the this pointer in C++ <br /> Very convenient, since many scripts are designed to control the object to which they are attached <br /> Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.) <br />
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string <br /> “self” is much like the this pointer in C++ <br /> Very convenient, since many scripts are designed to control the object to which they are attached <br /> Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.) <br />
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string <br /> “self” is much like the this pointer in C++ <br /> Very convenient, since many scripts are designed to control the object to which they are attached <br /> Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.) <br />
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string <br /> “self” is much like the this pointer in C++ <br /> Very convenient, since many scripts are designed to control the object to which they are attached <br /> Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.) <br />
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string <br /> “self” is much like the this pointer in C++ <br /> Very convenient, since many scripts are designed to control the object to which they are attached <br /> Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.) <br />
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string <br /> “self” is much like the this pointer in C++ <br /> Very convenient, since many scripts are designed to control the object to which they are attached <br /> Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.) <br />
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string <br /> “self” is much like the this pointer in C++ <br /> Very convenient, since many scripts are designed to control the object to which they are attached <br /> Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.) <br />
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string <br /> “self” is much like the this pointer in C++ <br /> Very convenient, since many scripts are designed to control the object to which they are attached <br /> Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.) <br />
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string <br /> “self” is much like the this pointer in C++ <br /> Very convenient, since many scripts are designed to control the object to which they are attached <br /> Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.) <br />
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string <br /> “self” is much like the this pointer in C++ <br /> Very convenient, since many scripts are designed to control the object to which they are attached <br /> Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.) <br />
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string <br /> “self” is much like the this pointer in C++ <br /> Very convenient, since many scripts are designed to control the object to which they are attached <br /> Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.) <br />
  • (go ...) is really just a native C++ function call <br />
  • (go ...) is really just a native C++ function call <br />
  • (go ...) is really just a native C++ function call <br />
  • (go ...) is really just a native C++ function call <br />
  • (go ...) is really just a native C++ function call <br />
  • (go ...) is really just a native C++ function call <br />
  • Track syntax can be omitted when there’s only one track <br /> Tracks are the only place runtime script code can exist <br /> All tracks within an (on ...) block run in parallel <br /> Ability to sleep is called “latent” code in Unreal <br /> “Actions” include playing an animation, playing an audio cue, an NPC walking from point A to point B, etc. <br /> Signals are like very simple Boolean semaphores <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />

StateScriptingInUncharted2 StateScriptingInUncharted2 Presentation Transcript

  • State-Based Scripting in Jason Gregory Generalist Programmer Naughty Dog, Inc.
  • 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 Game Developers Conference 2
  • Introduction to State Scripts 3
  • Brief History of State Scripts • Script system on Uncharted: Drake’s Fortune originally developed for in-game cinematics (IGCs) • Evolved into general gameplay scripting system Game Developers Conference 4
  • Brief History of State Scripts • 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 TM Game Developers Conference 5
  • Why Script? • Scripting languages used in games since Quake C • Primary benefits of script:  Takes pressure off engineering team  Code becomes data—rapid iteration  Empowers content creators  Key enabler of mod community Game Developers Conference 6
  • Why Script? • Scripting languages used in games since Quake C • Primary benefits of script: I feel  Takes pressure off engineering team empowered!  Code becomes data—rapid iteration  Empowers content creators  Key enabler of mod community Game Developers Conference 6
  • Scripting Language Characteristics • Two kinds of game scripting languages:  data definition languages  runtime languages • Runtime scripting languages typically:  interpreted by virtual machine (VM)  simple and small—low overhead  accessible to designers and other “non-programmers”  powerful—one line of code = big impact Game Developers Conference 7
  • Choice of Language • At Naughty Dog, we make heavy use of both data definition and runtime script  Both based on PLT Scheme (a Lisp variant) • Key benefits of Lisp-like languages:  Easy to parse  Data def and runtime code can be freely intermixed  Powerful macro system—easy to define custom syntax  Naughty Dog has a rich Lisp heritage—comfortable Game Developers Conference 8
  • Choice of Language • Of course you don’t have to use Lisp! • Data definition 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), ... Game Developers Conference 9
  • Extending the Game Object Model • Every game engine has some kind of game object model  Defines 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... Game Developers Conference 10
  • 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) Game Developers Conference 11
  • Unreal’s Approach • UnrealScript tightly integrated with C++ object model  Single-root class hierarchy with some add-on components  Classes defined in UnrealScript (.uc)  C++ header file (.h) automatically generated  Implementation in C++ or entirely in UnrealScript Pawn.h Actor generate Pawn.uc ... Info Pawn Pickup Pawn.cp p implement ... Scout implement Game Developers Conference 12
  • 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 Armor: Light Health: 200 Object Weapon: BFG (UID) AI: PlayerAlly Weapon: Pistol Game Developers Conference 13
  • Uncharted Engine’s Object Model • Uncharted class hierarchy:  relatively shallow, single-root  host of add-on components Process ... SsProcess DynLight ... Character ... Game Developers Conference 14
  • Uncharted Engine’s Object Model • Uncharted class hierarchy:  relatively shallow, single-root Objects  host of add-on components that update over time Process ... SsProcess DynLight ... Character ... Game Developers Conference 14
  • Uncharted Engine’s Object Model • Uncharted class hierarchy:  relatively shallow, single-root  host of add-on components Objects with transform Process ... SsProcess DynLight ... Character ... Game Developers Conference 14
  • Uncharted Engine’s Object Model • Uncharted class hierarchy:  relatively shallow, single-root  host of add-on components Base class for all characters Process ... SsProcess DynLight ... Character ... Game Developers Conference 14
  • Uncharted Engine’s Object Model • Uncharted class hierarchy:  relatively shallow, single-root  host of add-on components Simple animating Process object ... SsProcess DynLight ... Character ... Game Developers Conference 14
  • Uncharted Engine’s Object Model • Uncharted class hierarchy:  relatively shallow, single-root  host of add-on components Process ... SsProcess DynLight ... Character Manages a ... State Script instance Game Developers Conference 14
  • Uncharted Engine’s Object Model • Uncharted class hierarchy:  relatively shallow, single-root  host of add-on components Process ... SsProcess DynLight ... Character Manages a ... chunk of running script code Game Developers Conference 14
  • Uncharted Engine’s Object Model • Uncharted class hierarchy:  relatively shallow, single-root  host of add-on components Process SsProcess Game Developers Conference 14
  • Uncharted Engine’s Object Model • Uncharted class hierarchy:  relatively shallow, single-root  host of add-on components Process SsProcess SsInstance Game Developers Conference 14
  • Uncharted Engine’s Object Model • Uncharted class hierarchy:  relatively shallow, single-root  host of add-on components Process ... AnimContr SsInstance DrawContr Game Developers Conference 14
  • Charter • World editor for Uncharted is called Charter  Place game objects  Edit object properties  Control level streaming Game Developers Conference 15
  • Uncharted State Scripts • State scripts similar in many respects to property-centric model...  adds finite state machine (FSM) support  not specifically 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 Game Developers Conference 16
  • Anatomy of a State Script • A state script is comprised of:  attributes  states • States define object’s behavior via runtime script code:  response to events  natural behavior over time (update event)  transitional actions between states (begin/end events) Game Developers Conference 17
  • Anatomy of a State Script State Script 1 Variables State Script 2 State A On Update Variables On Event1 State C On Begin State B On Event4 On Begin Game Developers Conference 18
  • Anatomy of a State Script State Script 1 Variables Event1 State Script 2 State A On Update Variables On Event1 State C On Begin State B On Event4 On Begin Game Developers Conference 18
  • Anatomy of a State Script State Script 1 Variables Event1 State Script 2 State A On Update Variables On Event1 State C go to On Begin State State B On Event4 On Begin Game Developers Conference 18
  • Anatomy of a State Script State Script 1 Variables Event1 State Script 2 State A On Update Variables On Event1 State C go to On Begin State State B Event4 On Event4 On Begin Game Developers Conference 18
  • Instantiating a State Script • Attached to a native (C++) game object: Game Object  designers extend or modify native C++ object type State Script 1  define entirely new object types Game Developers Conference 19
  • Instantiating a State Script • Attached to a native (C++) game object: Game Object  designers extend or modify native C++ object type State Script 1  define entirely new object types • Attached to a trigger region:  convex volume Trigger Region  detects enter, exit and occupancy State Script 2 Game Developers Conference 19
  • Instantiating State Scripts • Placed as stand-alone object: SsProces s  “director” orchestrates actions of State Script 3 other objects (e.g. IGC) (stand-alone) Game Developers Conference 20
  • Instantiating State Scripts • Placed as stand-alone object: SsProces s  “director” orchestrates actions of State Script 3 other objects (e.g. IGC) (stand-alone) • Associated with a task: Task A  task = check point  script manages associated task Task B1 Task B2  orchestrates AI encounters Task C  controls player objectives State Script 4 Task D Game Developers Conference 20
  • Instantiating State Scripts • Placed as stand-alone object: SsProces s  “director” orchestrates actions of State Script 3 other objects (e.g. IGC) (stand-alone) • Associated with a task: Task A  task = check point  script manages associated task Task B1 Task B2  orchestrates AI encounters Task C  controls player objectives State Script 4 • Spawned by another state script Task D Game Developers Conference 20
  • State Script Syntax 21
  • Game Developers Conference 22
  • State Script Syntax • State script defined as follows:  Don’t let Lisp syntax throw you!  Lisp syntax is all (parentheses) (define-state-script (quot;kickable-gatequot;)  Think C/C++ { } blocks (state (quot;lockedquot;) • Parenthesized blocks highly ... ) context-sensitive in Lisp/Scheme (state (quot;openingquot;) ... ) (state (quot;openquot;) ... ) ) Game Developers Conference 23
  • State Script Syntax • State script defined as follows:  Don’t let Lisp syntax throw you!  Lisp syntax is all (parentheses) (define-state-script (quot;kickable-gatequot;)  Think C/C++ { } blocks (state (quot;lockedquot;) • Parenthesized blocks highly ... ) context-sensitive in Lisp/Scheme (state (quot;openingquot;) ... ) (state (quot;openquot;) ... ) ) Game Developers Conference 23
  • State Script Syntax • State script defined as follows:  Don’t let Lisp syntax throw you!  Lisp syntax is all (parentheses) (define-state-script (quot;kickable-gatequot;)  Think C/C++ { } blocks (state (quot;lockedquot;) • Parenthesized blocks highly ... ) context-sensitive in Lisp/Scheme (state (quot;openingquot;) ... ) (state (quot;openquot;) ... ) ) Game Developers Conference 23
  • State Script Syntax • State script defined as follows:  Don’t let Lisp syntax throw you!  Lisp syntax is all (parentheses) (define-state-script (quot;kickable-gatequot;)  Think C/C++ { } blocks (state (quot;lockedquot;) • Parenthesized blocks highly ... ) context-sensitive in Lisp/Scheme (state (quot;openingquot;) ... ) (state (quot;openquot;) ... ) ) Game Developers Conference 23
  • Event Handler Blocks (define-state-script (quot;kickable-gatequot;) (state (quot;lockedquot;) (on (event quot;kickquot;) ... ;; handle quot;kickquot; event • Each state contains zero or more ) (on (begin) event handler blocks ... ;; do when state entered ) (on (update) ... ;; do every frame ) (on (end) ... ;; do when state exited ) ) Game Developers Conference 24
  • Event Handler Blocks (define-state-script (quot;kickable-gatequot;) (state (quot;lockedquot;) (on (event quot;kickquot;) ... ;; handle quot;kickquot; event • Each state contains zero or more ) (on (begin) event handler blocks ... ;; do when state entered ) (on (update) ... ;; do every frame ) (on (end) ... ;; do when state exited ) ) Game Developers Conference 24
  • Event Handler Blocks (define-state-script (quot;kickable-gatequot;) (state (quot;lockedquot;) (on (event quot;kickquot;) ... ;; handle quot;kickquot; event • Each state contains zero or more ) (on (begin) event handler blocks ... ;; do when state entered ) (on (update) ... ;; do every frame ) (on (end) ... ;; do when state exited ) ) Game Developers Conference 24
  • Event Handler Blocks (define-state-script (quot;kickable-gatequot;) (state (quot;lockedquot;) (on (event quot;kickquot;) ... ;; handle quot;kickquot; event • Each state contains zero or more ) (on (begin) event handler blocks ... ;; do when state entered ) (on (update) ... ;; do every frame ) (on (end) ... ;; do when state exited ) ) Game Developers Conference 24
  • Event Handler Blocks (define-state-script (quot;kickable-gatequot;) (state (quot;lockedquot;) (on (event quot;kickquot;) ... ;; handle quot;kickquot; event • Each state contains zero or more ) (on (begin) event handler blocks ... ;; do when state entered ) (on (update) ... ;; do every frame ) (on (end) ... ;; do when state exited ) ) Game Developers Conference 24
  • Runtime Script Code • Runtime script code inside (on ...) (state (quot;lockedquot;) (on (begin) blocks [print-string quot;Starting idle!quot;] [animate quot;selfquot; quot;locked-idlequot;] • Simplified Scheme/Lisp ) (on (event quot;kickedquot;)  Most “commands” are native calls [when [lock-broken?] into C++ code [print-string quot;BAM!quot;] ]  Conditional expressions [if [task-complete? quot;wave2quot;] [print-string quot;Complete!quot;]  Simple looping via label/goto [print-string quot;NOT!!!quot;] ] ) ) Game Developers Conference 25
  • Runtime Script Code • Runtime script code inside (on ...) (state (quot;lockedquot;) (on (begin) blocks [print-string quot;Starting idle!quot;] [animate quot;selfquot; quot;locked-idlequot;] • Simplified Scheme/Lisp ) (on (event quot;kickedquot;)  Most “commands” are native calls [when [lock-broken?] into C++ code [print-string quot;BAM!quot;] ]  Conditional expressions [if [task-complete? quot;wave2quot;] [print-string quot;Complete!quot;]  Simple looping via label/goto [print-string quot;NOT!!!quot;] ] ) ) Game Developers Conference 25
  • Runtime Script Code • Runtime script code inside (on ...) (state (quot;lockedquot;) (on (begin) blocks [print-string quot;Starting idle!quot;] [animate quot;selfquot; quot;locked-idlequot;] • Simplified Scheme/Lisp ) (on (event quot;kickedquot;)  Most “commands” are native calls [when [lock-broken?] into C++ code [print-string quot;BAM!quot;] ]  Conditional expressions [if [task-complete? quot;wave2quot;] [print-string quot;Complete!quot;]  Simple looping via label/goto [print-string quot;NOT!!!quot;] ] ) ) Game Developers Conference 25
  • Runtime Script Code • Runtime script code inside (on ...) (state (quot;lockedquot;) (on (begin) blocks [print-string quot;Starting idle!quot;] [animate quot;selfquot; quot;locked-idlequot;] • Simplified Scheme/Lisp ) (on (event quot;kickedquot;)  Most “commands” are native calls [when [lock-broken?] into C++ code [print-string quot;BAM!quot;] ]  Conditional expressions [if [task-complete? quot;wave2quot;] [print-string quot;Complete!quot;]  Simple looping via label/goto [print-string quot;NOT!!!quot;] ] ) ) Game Developers Conference 25
  • User-Defined Functions (defun verbose-anim ((anim string)) [print-string quot;Starting quot; anim] [animate quot;selfquot; anim] ) • Script functions can be defined and called by script programmer (define-state-script (quot;kickable-gatequot;) (state (quot;lockedquot;) (on (begin) [verbose-anim quot;locked-idlequot;] ) ) ... ) Game Developers Conference 26
  • User-Defined Functions (defun verbose-anim ((anim string)) [print-string quot;Starting quot; anim] [animate quot;selfquot; anim] ) • Script functions can be defined and called by script programmer (define-state-script (quot;kickable-gatequot;) (state (quot;lockedquot;) (on (begin) [verbose-anim quot;locked-idlequot;] ) ) ... ) Game Developers Conference 26
  • User-Defined Functions (defun verbose-anim ((anim string)) [print-string quot;Starting quot; anim] [animate quot;selfquot; anim] ) • Script functions can be defined and called by script programmer (define-state-script (quot;kickable-gatequot;) (state (quot;lockedquot;) (on (begin) [verbose-anim quot;locked-idlequot;] ) ) ... ) Game Developers Conference 26
  • User-Defined Functions (defun verbose-anim ((anim string)) [print-string quot;Starting quot; anim] [animate quot;selfquot; anim] ) • Script functions can be defined and called by script programmer (define-state-script (quot;kickable-gatequot;) (state (quot;lockedquot;) (on (begin) [verbose-anim quot;locked-idlequot;] ) ) ... ) Game Developers Conference 26
  • User-Defined Functions (defun verbose-anim ((anim string)) [print-string quot;Starting quot; anim] [animate quot;selfquot; anim] ) • Script functions can be defined and called by script programmer (define-state-script (quot;kickable-gatequot;) (state (quot;lockedquot;) (on (begin) [verbose-anim quot;locked-idlequot;] ) ) ... ) Game Developers Conference 26
  • The “Self” Argument • Any command operating on a game object takes its unique id (UID) as its first argument • Magic UID quot;selfquot; refers to the object to which script is attached gate-17 Game Object State Script 1 Game Developers Conference 27
  • The “Self” Argument • Any command operating on a game object takes its unique id (UID) as its first argument • Magic UID quot;selfquot; refers to the object to which script is attached (on (begin) gate-17 [animate quot;selfquot; quot;locked-idlequot;] Game ) Object State Script 1 self Game Developers Conference 27
  • The “Self” Argument • Any command operating on a game object takes its unique id (UID) as its first argument • Magic UID quot;selfquot; refers to the object to which script is attached gate-17 (on (begin) [animate quot;gate-17quot; quot;locked-idlequot;] Game ) Object State Script 1 Game Developers Conference 27
  • The “Self” Argument • Any command operating on a game object takes its unique id (UID) as its first argument • Magic UID quot;selfquot; refers to the object to which script is attached gate-17 (on (begin) Game [animate quot;lock-6quot; quot;fall-offquot;] Object ) lock-6 State Script 1 Game Object Game Developers Conference 27
  • Changing States (define-state-script (quot;kickable-gatequot;) (state (quot;lockedquot;) • Transitions to other states via ... (go quot;state-namequot;) command (on (event quot;kickedquot;) [when [lock-broken?] • State transitions cause current [go quot;openingquot;] ] state’s (on ...) blocks to be ) ) aborted (state (quot;openingquot;) (on (begin) • Use (on (exit) ...) block for ... clean-up ) ... ) ) Game Developers Conference 28
  • Changing States (define-state-script (quot;kickable-gatequot;) (state (quot;lockedquot;) • Transitions to other states via ... (go quot;state-namequot;) command (on (event quot;kickedquot;) [when [lock-broken?] • State transitions cause current [go quot;openingquot;] ] state’s (on ...) blocks to be ) ) aborted (state (quot;openingquot;) (on (begin) • Use (on (exit) ...) block for ... clean-up ) ... ) ) Game Developers Conference 28
  • Changing States (define-state-script (quot;kickable-gatequot;) (state (quot;lockedquot;) • Transitions to other states via ... (go quot;state-namequot;) command (on (event quot;kickedquot;) [when [lock-broken?] • State transitions cause current [go quot;openingquot;] ] state’s (on ...) blocks to be ) ) aborted (state (quot;openingquot;) (on (begin) • Use (on (exit) ...) block for ... clean-up ) ... ) ) Game Developers Conference 28
  • Tracks • (on ...) blocks contain one or more tracks • A track is a bit like a thread or fiber • 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 Game Developers Conference 29
  • Tracks State quot;shake-handsquot; (state (quot;shake-handsquot;) (on (begin) On Begin (track (quot;playerquot;)) Track Track [wait-move-to quot;playerquot; quot;waypoint7quot;] P S [signal quot;player-at-waypointquot;] [wait-for-signal quot;sully-at-waypointquot;] [wait-animate quot;playerquot; quot;shake-sullys-handquot;] s-a-w ) (track (quot;sullivanquot;)) [wait-move-to quot;sullivanquot; quot;waypoint7quot;] [signal quot;sully-at-waypointquot;] p-a-w [wait-for-signal quot;player-at-waypointquot;] [wait-animate quot;sullivanquot; quot;shake-drakes-handquot;] ) ) ) Game Developers Conference 30
  • Tracks State quot;shake-handsquot; (state (quot;shake-handsquot;) (on (begin) On Begin (track (quot;playerquot;)) Track Track [wait-move-to quot;playerquot; quot;waypoint7quot;] P S [signal quot;player-at-waypointquot;] [wait-for-signal quot;sully-at-waypointquot;] [wait-animate quot;playerquot; quot;shake-sullys-handquot;] s-a-w ) (track (quot;sullivanquot;)) [wait-move-to quot;sullivanquot; quot;waypoint7quot;] [signal quot;sully-at-waypointquot;] p-a-w [wait-for-signal quot;player-at-waypointquot;] [wait-animate quot;sullivanquot; quot;shake-drakes-handquot;] ) ) ) Game Developers Conference 30
  • Tracks State quot;shake-handsquot; (state (quot;shake-handsquot;) (on (begin) On Begin (track (quot;playerquot;)) Track Track [wait-move-to quot;playerquot; quot;waypoint7quot;] P S [signal quot;player-at-waypointquot;] [wait-for-signal quot;sully-at-waypointquot;] [wait-animate quot;playerquot; quot;shake-sullys-handquot;] s-a-w ) (track (quot;sullivanquot;)) [wait-move-to quot;sullivanquot; quot;waypoint7quot;] [signal quot;sully-at-waypointquot;] p-a-w [wait-for-signal quot;player-at-waypointquot;] [wait-animate quot;sullivanquot; quot;shake-drakes-handquot;] ) ) ) Game Developers Conference 30
  • Tracks State quot;shake-handsquot; (state (quot;shake-handsquot;) (on (begin) On Begin (track (quot;playerquot;)) Track Track [wait-move-to quot;playerquot; quot;waypoint7quot;] P S [signal quot;player-at-waypointquot;] [wait-for-signal quot;sully-at-waypointquot;] [wait-animate quot;playerquot; quot;shake-sullys-handquot;] s-a-w ) (track (quot;sullivanquot;)) [wait-move-to quot;sullivanquot; quot;waypoint7quot;] [signal quot;sully-at-waypointquot;] p-a-w [wait-for-signal quot;player-at-waypointquot;] [wait-animate quot;sullivanquot; quot;shake-drakes-handquot;] ) ) ) Game Developers Conference 30
  • Tracks State quot;shake-handsquot; (state (quot;shake-handsquot;) (on (begin) On Begin (track (quot;playerquot;)) Track Track [wait-move-to quot;playerquot; quot;waypoint7quot;] P S [signal quot;player-at-waypointquot;] [wait-for-signal quot;sully-at-waypointquot;] [wait-animate quot;playerquot; quot;shake-sullys-handquot;] p-a-w ) (track (quot;sullivanquot;)) [wait-move-to quot;sullivanquot; quot;waypoint7quot;] [signal quot;sully-at-waypointquot;] s-a-w [wait-for-signal quot;player-at-waypointquot;] [wait-animate quot;sullivanquot; quot;shake-drakes-handquot;] ) ) ) Game Developers Conference 30
  • Track Execution Over Time • 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 doesn’t have to wait; for example:  [wait-seconds 0]  [wait-npc-move-to quot;pos-4quot;] when she’s already there Game Developers Conference 31
  • Options and Variable Declarations • Options declared at top of script: (define-state-script (quot;kickable-gatequot;) :initial-state quot;closedquot;  initial state :declarations (decl-list  variable declarations (var quot;num-attemptsquot; :type int32) (var quot;is-lockedquot; :type boolean :default #t)  debugging options ) (state (quot;kickedquot;) ... ) ... ) Game Developers Conference 32
  • Options and Variable Declarations • Options declared at top of script: (define-state-script (quot;kickable-gatequot;) :initial-state quot;closedquot;  initial state :declarations (decl-list  variable declarations (var quot;num-attemptsquot; :type int32) (var quot;is-lockedquot; :type boolean :default #t)  debugging options ) (state (quot;kickedquot;) ... ) ... ) Game Developers Conference 32
  • Options and Variable Declarations • Options declared at top of script: (define-state-script (quot;kickable-gatequot;) :initial-state quot;closedquot;  initial state :declarations (decl-list  variable declarations (var quot;num-attemptsquot; :type int32) (var quot;is-lockedquot; :type boolean :default #t)  debugging options ) (state (quot;kickedquot;) ... ) ... ) Game Developers Conference 32
  • (define-state-script (quot;kickable-gatequot;) :initial-state quot;closedquot; Manipulating Variables :declarations (decl-list (var quot;num-attemptsquot; :type int32) • Simple commands for reading (var quot;is-lockedquot; :type boolean :default #t) ) and writing variables (state (quot;kickedquot;) (on (begin) • Lisp/Scheme uses prefix notation [when [get-boolean quot;is-lockedquot;] [set-int32 quot;num-attemptsquot; (a.k.a. Polish notation) [+ 1 [get-int32 quot;num-attemptsquot;]] ]  [+ a b] calculates (a + b) [wait-animate quot;selfquot; quot;kick-failurequot;] [go quot;closedquot;]  [set quot;xquot; [+ 1 [get quot;xquot;]]] ] increments variable “x” ;; else... [wait-animate quot;selfquot; quot;kick-successquot;] [go quot;openquot;] ) ) ... Game Developers Conference 33
  • (define-state-script (quot;kickable-gatequot;) :initial-state quot;closedquot; Manipulating Variables :declarations (decl-list (var quot;num-attemptsquot; :type int32) • Simple commands for reading (var quot;is-lockedquot; :type boolean :default #t) ) and writing variables (state (quot;kickedquot;) (on (begin) • Lisp/Scheme uses prefix notation [when [get-boolean quot;is-lockedquot;] [set-int32 quot;num-attemptsquot; (a.k.a. Polish notation) [+ 1 [get-int32 quot;num-attemptsquot;]] ]  [+ a b] calculates (a + b) [wait-animate quot;selfquot; quot;kick-failurequot;] [go quot;closedquot;]  [set quot;xquot; [+ 1 [get quot;xquot;]]] ] increments variable “x” ;; else... [wait-animate quot;selfquot; quot;kick-successquot;] [go quot;openquot;] ) ) ... Game Developers Conference 33
  • (define-state-script (quot;kickable-gatequot;) :initial-state quot;closedquot; Manipulating Variables :declarations (decl-list (var quot;num-attemptsquot; :type int32) • Simple commands for reading (var quot;is-lockedquot; :type boolean :default #t) ) and writing variables (state (quot;kickedquot;) (on (begin) • Lisp/Scheme uses prefix notation [when [get-boolean quot;is-lockedquot;] [set-int32 quot;num-attemptsquot; (a.k.a. Polish notation) [+ 1 [get-int32 quot;num-attemptsquot;]] ]  [+ a b] calculates (a + b) [wait-animate quot;selfquot; quot;kick-failurequot;] [go quot;closedquot;]  [set quot;xquot; [+ 1 [get quot;xquot;]]] ] increments variable “x” ;; else... [wait-animate quot;selfquot; quot;kick-successquot;] [go quot;openquot;] ) ) ... Game Developers Conference 33
  • (define-state-script (quot;kickable-gatequot;) :initial-state quot;closedquot; Manipulating Variables :declarations (decl-list (var quot;num-attemptsquot; :type int32) • Simple commands for reading (var quot;is-lockedquot; :type boolean :default #t) ) and writing variables (state (quot;kickedquot;) (on (begin) • Lisp/Scheme uses prefix notation [when [get-boolean quot;is-lockedquot;] [set-int32 quot;num-attemptsquot; (a.k.a. Polish notation) [+ 1 [get-int32 quot;num-attemptsquot;]] ˘ ]  [+ a b] calculates (a + b) [wait-animate quot;selfquot; quot;kick-failurequot;] [go quot;closedquot;]  [set quot;xquot; [+ 1 [get quot;xquot;]]] ] increments variable “x” ;; else... [wait-animate quot;selfquot; quot;kick-successquot;] [go quot;openquot;] ) ) ... Game Developers Conference 33
  • (define-state-script (quot;kickable-gatequot;) :initial-state quot;closedquot; Manipulating Variables :declarations (decl-list (var quot;num-attemptsquot; :type int32) • Simple commands for reading (var quot;is-lockedquot; :type boolean :default #t) ) and writing variables (state (quot;kickedquot;) (on (begin) • Lisp/Scheme uses prefix notation [when [get-boolean quot;is-lockedquot;] [set-int32 quot;num-attemptsquot; (a.k.a. Polish notation) [+ 1 [get-int32 quot;num-attemptsquot;]] ]  [+ a b] calculates (a + b) [wait-animate quot;selfquot; quot;kick-failurequot;] [go quot;closedquot;]  [set quot;xquot; [+ 1 [get quot;xquot;]]] ] increments variable “x” ;; else... [wait-animate quot;selfquot; quot;kick-successquot;] [go quot;openquot;] ) ) ... Game Developers Conference 33
  • Configuration Parameters • All game objects have properties (key-value pairs)  Property values edited in Charter Game Developers Conference 34
  • Configuration Parameters • All game objects have properties (key-value pairs)  Property values edited in Charter Game Developers Conference 34
  • Configuration Parameters • Designers can create their own free-form properties, called tags meaning-of-life = 42  Simply type “key = value” in Tags field Game Developers Conference 34
  • Configuration Parameters • State scripts have read-only access to game object properties...  ... and free-form tags Game Developers Conference 35
  • Configuration Parameters • State scripts have read-only access to game object properties...  ... and free-form tags (define-state-script (quot;kickable-gatequot;) (state (quot;kickedquot;) (on (begin) [wait-animate quot;selfquot; [tag-string quot;kick-animquot;] ] ) ... ) Game Developers Conference 35
  • Configuration Parameters • State scripts have read-only access to game object properties...  ... and free-form tags (define-state-script (quot;kickable-gatequot;) (state (quot;kickedquot;) (on (begin) [wait-animate quot;selfquot; [tag-string quot;kick-animquot;] ] ) ... ) Game Developers Conference 35
  • Configuration Parameters • State scripts have read-only access to game object properties...  ... and free-form tags (define-state-script (quot;kickable-gatequot;) (state (quot;kickedquot;) (on (begin) [wait-animate quot;selfquot; [tag-string quot;kick-animquot;] ] ) ... ) Game Developers Conference 35
  • Data Definition and Runtime (define-state-script (quot;kickable-gatequot;) • Offline data-definition language (state (quot;lockedquot;) (on (begin) (Scheme) is intermingled with [print-string quot;Starting idle!quot;] [animate quot;selfquot; quot;locked-idlequot;] runtime code ) (on (event quot;kickedquot;) [when [lock-broken?] [print-string quot;BAM!quot;] ] [if [task-complete? quot;wave2quot;] [print-string quot;Complete!quot;] [print-string quot;NOT!!!quot;] ] ) ) ... ) Game Developers Conference 36
  • Data Definition and Runtime (define-state-script (quot;kickable-gatequot;) • Offline data-definition language (state (quot;lockedquot;) (on (begin) (Scheme) is intermingled with [print-string quot;Starting idle!quot;] [animate quot;selfquot; quot;locked-idlequot;] runtime code ) (on (event quot;kickedquot;) [when [lock-broken?] [print-string quot;BAM!quot;] ] [if [task-complete? quot;wave2quot;] [print-string quot;Complete!quot;] [print-string quot;NOT!!!quot;] ] ) ) ... ) Game Developers Conference 36
  • Data Definition and Runtime class Vector3 { private: float x, y, z; • Really no different than the public: float Dot(const Vector3& b) distinction between declarations { return (x * b.x and definitions in C++ + y * b.y + z * b.z); } ... }; Game Developers Conference 36
  • Data Definition and Runtime class Vector3 { private: float x, y, z; • Really no different than the public: float Dot(const Vector3& b) distinction between declarations { return (x * b.x and definitions in C++ + y * b.y + z * b.z); } ... }; Game Developers Conference 36
  • Case Studies 37
  • Custom Object Type: Breakable Sign Game Developers Conference 38
  • Custom Object Type: Breakable Sign Game Developers Conference 38
  • Custom Object Type: Breakable Sign (define-state-script (quot;falling-signquot;) (state (quot;untouchedquot;) (on (update) [when [task-complete? quot;wz-post-combatquot;] [go quot;fallenquot;] ] ) (on (event quot;hanging-fromquot;) [go quot;breakingquot;] ) ) ... Game Developers Conference 39
  • Custom Object Type: Breakable Sign (define-state-script (quot;falling-signquot;) (state (quot;untouchedquot;) (on (update) [when [task-complete? quot;wz-post-combatquot;] [go quot;fallenquot;] ] ) (on (event quot;hanging-fromquot;) [go quot;breakingquot;] ) ) ... Game Developers Conference 39
  • Custom Object Type: Breakable Sign (define-state-script (quot;falling-signquot;) (state (quot;untouchedquot;) (on (update) [when [task-complete? quot;wz-post-combatquot;] [go quot;fallenquot;] ] ) (on (event quot;hanging-fromquot;) [go quot;breakingquot;] ) ) ... Game Developers Conference 39
  • Custom Object Type: Breakable Sign (state (quot;breakingquot;) (on (begin) [spawn-particles-at-joint quot;selfquot; quot;hingequot; quot;sign-break-dustquot;] [wait-animate quot;selfquot; quot;sign-breakquot;] [go quot;fallenquot;] ) ) (state (quot;fallenquot;) (on (begin) [animate quot;selfquot; quot;sign-brokenquot;] ;; looping ) ) ) Game Developers Conference 39
  • Custom Object Type: Breakable Sign (state (quot;breakingquot;) (on (begin) [spawn-particles-at-joint quot;selfquot; quot;hingequot; quot;sign-break-dustquot;] [wait-animate quot;selfquot; quot;sign-breakquot;] [go quot;fallenquot;] ) ) (state (quot;fallenquot;) (on (begin) [animate quot;selfquot; quot;sign-brokenquot;] ;; looping ) ) ) Game Developers Conference 39
  • Custom Object Type: Breakable Sign (state (quot;breakingquot;) (on (begin) [spawn-particles-at-joint quot;selfquot; quot;hingequot; quot;sign-break-dustquot;] [wait-animate quot;selfquot; quot;sign-breakquot;] [go quot;fallenquot;] ) ) (state (quot;fallenquot;) (on (begin) [animate quot;selfquot; quot;sign-brokenquot;] ;; looping ) ) ) Game Developers Conference 39
  • Custom Object Type: Breakable Sign (state (quot;breakingquot;) (on (begin) [spawn-particles-at-joint quot;selfquot; quot;hingequot; quot;sign-break-dustquot;] [wait-animate quot;selfquot; quot;sign-breakquot;] [go quot;fallenquot;] ) ) (state (quot;fallenquot;) (on (begin) [animate quot;selfquot; quot;sign-brokenquot;] ;; looping ) ) ) Game Developers Conference 39
  • Custom Object Type: Breakable Sign (state (quot;breakingquot;) (on (begin) [spawn-particles-at-joint quot;selfquot; quot;hingequot; quot;sign-break-dustquot;] [wait-animate quot;selfquot; quot;sign-breakquot;] [go quot;fallenquot;] ) ) (state (quot;fallenquot;) (on (begin) [animate quot;selfquot; quot;sign-brokenquot;] ;; looping ) ) ) Game Developers Conference 39
  • Custom Object Type: Breakable Sign (state (quot;breakingquot;) (on (begin) [spawn-particles-at-joint quot;selfquot; quot;hingequot; quot;sign-break-dustquot;] [wait-animate quot;selfquot; quot;sign-breakquot;] [go quot;fallenquot;] ) ) (state (quot;fallenquot;) (on (begin) [animate quot;selfquot; quot;sign-brokenquot;] ;; looping ) ) ) Game Developers Conference 39
  • Custom Object Type: Breakable Sign (state (quot;breakingquot;) (on (begin) [spawn-particles-at-joint quot;selfquot; quot;hingequot; quot;sign-break-dustquot;] [wait-animate quot;selfquot; quot;sign-breakquot;] [go quot;fallenquot;] ) ) (state (quot;fallenquot;) (on (begin) [animate quot;selfquot; quot;sign-brokenquot;] ;; looping ) ) ) Game Developers Conference 39
  • Custom Object Type: Breakable Sign (state (quot;breakingquot;) (on (begin) [spawn-particles-at-joint quot;selfquot; quot;hingequot; quot;sign-break-dustquot;] [wait-animate quot;selfquot; quot;sign-breakquot;] [go quot;fallenquot;] ) ) (state (quot;fallenquot;) (on (begin) [animate quot;selfquot; quot;sign-brokenquot;] ;; looping ) ) ) Game Developers Conference 39
  • Custom Object Type: Breakable Sign (state (quot;breakingquot;) (on (begin) [spawn-particles-at-joint quot;selfquot; quot;hingequot; quot;sign-break-dustquot;] [wait-animate quot;selfquot; quot;sign-breakquot;] [go quot;fallenquot;] ) ) (state (quot;fallenquot;) (on (begin) [animate quot;selfquot; quot;sign-brokenquot;] ;; looping ) ) ) Game Developers Conference 39
  • Custom Object Type: Breakable Sign (state (quot;breakingquot;) (on (begin) (define-state-script (quot;falling-signquot;) [spawn-particles-at-joint quot;selfquot; (state (quot;untouchedquot;) quot;hingequot; (on (update) quot;sign-break-dustquot;] [when [task-complete? quot;wz-post-combatquot;] [wait-animate quot;selfquot; quot;sign-breakquot;] [go quot;fallenquot;] [go quot;fallenquot;] ] ) ) ) (on (event quot;hanging-fromquot;) (state (quot;fallenquot;) [go quot;breakingquot;] (on (begin) ) [animate quot;selfquot; quot;sign-brokenquot;] ;; looping ) ) ... ) ) Game Developers Conference 39
  • Custom Object Type: Breakable Sign (state (quot;breakingquot;) (on (begin) (define-state-script (quot;falling-signquot;) [spawn-particles-at-joint quot;selfquot; (state (quot;untouchedquot;) quot;hingequot; (on (update) quot;sign-break-dustquot;] [when [task-complete? quot;wz-post-combatquot;] [wait-animate quot;selfquot; quot;sign-breakquot;] [go quot;fallenquot;] [go quot;fallenquot;] ] ) ) ) (on (event quot;hanging-fromquot;) (state (quot;fallenquot;) [go quot;breakingquot;] (on (begin) ) [animate quot;selfquot; quot;sign-brokenquot;] ;; looping ) ) ... ) ) Game Developers Conference 39
  • Custom Object Type: Breakable Sign (state (quot;breakingquot;) (on (begin) (define-state-script (quot;falling-signquot;) [spawn-particles-at-joint quot;selfquot; (state (quot;untouchedquot;) quot;hingequot; (on (update) quot;sign-break-dustquot;] [when [task-complete? quot;wz-post-combatquot;] [wait-animate quot;selfquot; quot;sign-breakquot;] [go quot;fallenquot;] [go quot;fallenquot;] ] ) ) ) (on (event quot;hanging-fromquot;) (state (quot;fallenquot;) [go quot;breakingquot;] (on (begin) ) [animate quot;selfquot; quot;sign-brokenquot;] ;; looping ) ) ... ) ) Game Developers Conference 39
  • Making the Sign Script Generic (state (quot;animatingquot;) (on (begin) [spawn-particles-at-joint quot;selfquot; (define-state-script (quot;simple-animating-objquot;) [tag-string quot;particle-jointquot;] (state (quot;initialquot;) [tag-string quot;particle-namequot;]] (on (update) [wait-animate quot;selfquot; [when [task-complete? [tag-string quot;anim-namequot;]] [tag-string quot;done-taskquot;]] [go quot;donequot;] [go quot;donequot;] ) ] ) ) (state (quot;donequot;) (on (event quot;hanging-fromquot;) (on (begin) [go quot;animatingquot;] [animate quot;selfquot; ) [tag-string quot;done-anim-namequot;]] ) ) ... ) ) Game Developers Conference 40
  • Making the Sign Script Generic (state (quot;animatingquot;) (on (begin) [spawn-particles-at-joint quot;selfquot; (define-state-script (quot;simple-animating-objquot;) [tag-string quot;particle-jointquot;] (state (quot;initialquot;) [tag-string quot;particle-namequot;]] (on (update) [wait-animate quot;selfquot; [when [task-complete? [tag-string quot;anim-namequot;]] [tag-string quot;done-taskquot;]] [go quot;donequot;] [go quot;donequot;] ) ] ) ) (state (quot;donequot;) (on (event quot;hanging-fromquot;) (on (begin) [go quot;animatingquot;] [animate quot;selfquot; ) [tag-string quot;done-anim-namequot;]] ) ) ... ) ) Game Developers Conference 40
  • Making the Sign Script Generic (state (quot;animatingquot;) (on (begin) [spawn-particles-at-joint quot;selfquot; (define-state-script (quot;simple-animating-objquot;) [tag-string quot;particle-jointquot;] (state (quot;initialquot;) [tag-string quot;particle-namequot;]] (on (update) [wait-animate quot;selfquot; [when [task-complete? [tag-string quot;anim-namequot;]] [tag-string quot;done-taskquot;]] [go quot;donequot;] [go quot;donequot;] ) ] ) ) (state (quot;donequot;) (on (event quot;hanging-fromquot;) (on (begin) [go quot;animatingquot;] [animate quot;selfquot; ) [tag-string quot;done-anim-namequot;]] ) ) ... ) ) Game Developers Conference 40
  • Making the Sign Script Generic (state (quot;animatingquot;) (on (begin) [spawn-particles-at-joint quot;selfquot; (define-state-script (quot;simple-animating-objquot;) [tag-string quot;particle-jointquot;] (state (quot;initialquot;) [tag-string quot;particle-namequot;]] (on (update) [wait-animate quot;selfquot; [when [task-complete? [tag-string quot;anim-namequot;]] [tag-string quot;done-taskquot;]] [go quot;donequot;] [go quot;donequot;] ) ] ) ) (state (quot;donequot;) (on (event quot;hanging-fromquot;) (on (begin) [go quot;animatingquot;] [animate quot;selfquot; ) [tag-string quot;done-anim-namequot;]] ) ) ... ) ) Game Developers Conference 40
  • Making the Sign Script Generic (state (quot;animatingquot;) (on (begin) [spawn-particles-at-joint quot;selfquot; (define-state-script (quot;simple-animating-objquot;) [tag-string quot;particle-jointquot;] (state (quot;initialquot;) [tag-string quot;particle-namequot;]] (on (update) [wait-animate quot;selfquot; [when [task-complete? [tag-string quot;anim-namequot;]] [tag-string quot;done-taskquot;]] [go quot;donequot;] [go quot;donequot;] ) ] ) ) (state (quot;donequot;) (on (event quot;hanging-fromquot;) (on (begin) [go quot;animatingquot;] [animate quot;selfquot; ) [tag-string quot;done-anim-namequot;]] ) ) ... ) ) Game Developers Conference 40
  • Making the Sign Script Generic (state (quot;animatingquot;) (on (begin) [spawn-particles-at-joint quot;selfquot; (define-state-script (quot;simple-animating-objquot;) [tag-string quot;particle-jointquot;] (state (quot;initialquot;) [tag-string quot;particle-namequot;]] (on (update) [wait-animate quot;selfquot; [when [task-complete? [tag-string quot;anim-namequot;]] [tag-string quot;done-taskquot;]] [go quot;donequot;] [go quot;donequot;] ) ] ) ) (state (quot;donequot;) (on (event quot;hanging-fromquot;) (on (begin) [go quot;animatingquot;] [animate quot;selfquot; ) [tag-string quot;done-anim-namequot;]] ) ) ... ) ) Game Developers Conference 40
  • Making the Sign Script Generic (state (quot;animatingquot;) (on (begin) [spawn-particles-at-joint quot;selfquot; (define-state-script (quot;simple-animating-objquot;) [tag-string quot;particle-jointquot;] (state (quot;initialquot;) [tag-string quot;particle-namequot;]] (on (update) [wait-animate quot;selfquot; [when [task-complete? [tag-string quot;anim-namequot;]] [tag-string quot;done-taskquot;]] [go quot;donequot;] [go quot;donequot;] ) ] ) ) (state (quot;donequot;) (on (event quot;hanging-fromquot;) (on (begin) [go quot;animatingquot;] [animate quot;selfquot; ) [tag-string quot;done-anim-namequot;]] ) ) ... ) ) Game Developers Conference 40
  • Making the Sign Script Generic (state (quot;animatingquot;) (on (begin) [spawn-particles-at-joint quot;selfquot; (define-state-script (quot;simple-animating-objquot;) [tag-string quot;particle-jointquot;] (state (quot;initialquot;) [tag-string quot;particle-namequot;]] (on (update) [wait-animate quot;selfquot; [when [task-complete? [tag-string quot;anim-namequot;]] [tag-string quot;done-taskquot;]] [go quot;donequot;] [go quot;donequot;] ) ] ) ) (state (quot;donequot;) (on (event quot;hanging-fromquot;) (on (begin) [go quot;animatingquot;] [animate quot;selfquot; ) [tag-string quot;done-anim-namequot;]] ) ) ... ) ) Game Developers Conference 40
  • Making the Sign Script Generic (state (quot;animatingquot;) (on (begin) [spawn-particles-at-joint quot;selfquot; (define-state-script (quot;simple-animating-objquot;) [tag-string quot;particle-jointquot;] (state (quot;initialquot;) [tag-string quot;particle-namequot;]] (on (update) [wait-animate quot;selfquot; [when [task-complete? [tag-string quot;anim-namequot;]] [tag-string quot;done-taskquot;]] [go quot;donequot;] [go quot;donequot;] ) ] ) ) (state (quot;donequot;) (on (event quot;hanging-fromquot;) (on (begin) [go quot;animatingquot;] [animate quot;selfquot; ) [tag-string quot;done-anim-namequot;]] ) ) ... ) ) Game Developers Conference 40
  • Making the Sign Script Generic (state (quot;animatingquot;) (on (begin) [spawn-particles-at-joint quot;selfquot; (define-state-script (quot;simple-animating-objquot;) [tag-string quot;particle-jointquot;] (state (quot;initialquot;) [tag-string quot;particle-namequot;]] (on (update) [wait-animate quot;selfquot; [when [task-complete? [tag-string quot;anim-namequot;]] [tag-string quot;done-taskquot;]] [go quot;donequot;] [go quot;donequot;] ) ] ) ) (state (quot;donequot;) (on (event quot;hanging-fromquot;) (on (begin) [go quot;animatingquot;] [animate quot;selfquot; ) [tag-string quot;done-anim-namequot;]] ) ) ... ) ) Game Developers Conference 40
  • In-Game Debugging Game Developers Conference 41
  • In-Game Debugging Game Developers Conference 41
  • In-Game Debugging Game Developers Conference 41
  • In-Game Debugging Game Developers Conference 41
  • In-Game Debugging Game Developers Conference 41
  • In-Game Debugging Game Developers Conference 41
  • In-Game Cinematic: Bus Crash Game Developers Conference 42
  • In-Game Cinematic: Bus Crash (state (quot;crashquot;) (on (begin) (define-state-script (quot;wz-bus-crashquot;) (track (quot;busquot;) (state (quot;spawn-soldiersquot;) [wait-animate quot;bus-1quot; quot;bus-crashquot; (on (begin) [get-locator quot;ref-bus-crash-1quot;]] [player-disable-controls [signal quot;bus-donequot;] (controls all-but-right-stick)] ) [spawn-npc-in-combat quot;npc-wz-52quot;] (track (quot;playerquot;) [spawn-npc-in-combat quot;npc-wz-53quot;] [animate quot;playerquot; quot;player-watch-crashquot; ... [get-locator quot;ref-bus-crash-1quot;]] [go quot;crashquot;] [wait-until-frame 250] ) [say quot;playerquot; quot;vox-wz-drk-01-what-thequot;] ) [signal quot;drake-donequot;] ... ) ... Game Developers Conference 43
  • In-Game Cinematic: Bus Crash (state (quot;crashquot;) (on (begin) (define-state-script (quot;wz-bus-crashquot;) (track (quot;busquot;) (state (quot;spawn-soldiersquot;) [wait-animate quot;bus-1quot; quot;bus-crashquot; (on (begin) [get-locator quot;ref-bus-crash-1quot;]] [player-disable-controls [signal quot;bus-donequot;] (controls all-but-right-stick)] ) [spawn-npc-in-combat quot;npc-wz-52quot;] (track (quot;playerquot;) [spawn-npc-in-combat quot;npc-wz-53quot;] [animate quot;playerquot; quot;player-watch-crashquot; ... [get-locator quot;ref-bus-crash-1quot;]] [go quot;crashquot;] [wait-until-frame 250] ) [say quot;playerquot; quot;vox-wz-drk-01-what-thequot;] ) [signal quot;drake-donequot;] ... ) ... Game Developers Conference 43
  • In-Game Cinematic: Bus Crash (state (quot;crashquot;) (on (begin) (define-state-script (quot;wz-bus-crashquot;) (track (quot;busquot;) (state (quot;spawn-soldiersquot;) [wait-animate quot;bus-1quot; quot;bus-crashquot; (on (begin) [get-locator quot;ref-bus-crash-1quot;]] [player-disable-controls [signal quot;bus-donequot;] (controls all-but-right-stick)] ) [spawn-npc-in-combat quot;npc-wz-52quot;] (track (quot;playerquot;) [spawn-npc-in-combat quot;npc-wz-53quot;] [animate quot;playerquot; quot;player-watch-crashquot; ... [get-locator quot;ref-bus-crash-1quot;]] [go quot;crashquot;] [wait-until-frame 250] ) [say quot;playerquot; quot;vox-wz-drk-01-what-thequot;] ) [signal quot;drake-donequot;] ... ) ... Game Developers Conference 43
  • In-Game Cinematic: Bus Crash (state (quot;crashquot;) (on (begin) (define-state-script (quot;wz-bus-crashquot;) (track (quot;busquot;) (state (quot;spawn-soldiersquot;) [wait-animate quot;bus-1quot; quot;bus-crashquot; (on (begin) [get-locator quot;ref-bus-crash-1quot;]] [player-disable-controls [signal quot;bus-donequot;] (controls all-but-right-stick)] ) [spawn-npc-in-combat quot;npc-wz-52quot;] (track (quot;playerquot;) [spawn-npc-in-combat quot;npc-wz-53quot;] [animate quot;playerquot; quot;player-watch-crashquot; ... [get-locator quot;ref-bus-crash-1quot;]] [go quot;crashquot;] [wait-until-frame 250] ) [say quot;playerquot; quot;vox-wz-drk-01-what-thequot;] ) [signal quot;drake-donequot;] ... ) ... Game Developers Conference 43
  • In-Game Cinematic: Bus Crash (state (quot;crashquot;) (on (begin) (define-state-script (quot;wz-bus-crashquot;) (track (quot;busquot;) (state (quot;spawn-soldiersquot;) [wait-animate quot;bus-1quot; quot;bus-crashquot; (on (begin) [get-locator quot;ref-bus-crash-1quot;]] [player-disable-controls [signal quot;bus-donequot;] (controls all-but-right-stick)] ) [spawn-npc-in-combat quot;npc-wz-52quot;] (track (quot;playerquot;) [spawn-npc-in-combat quot;npc-wz-53quot;] [animate quot;playerquot; quot;player-watch-crashquot; ... [get-locator quot;ref-bus-crash-1quot;]] [go quot;crashquot;] [wait-until-frame 250] ) [say quot;playerquot; quot;vox-wz-drk-01-what-thequot;] ) [signal quot;drake-donequot;] ... ) ... Game Developers Conference 43
  • In-Game Cinematic: Bus Crash (state (quot;crashquot;) (on (begin) (define-state-script (quot;wz-bus-crashquot;) (track (quot;busquot;) (state (quot;spawn-soldiersquot;) [wait-animate quot;bus-1quot; quot;bus-crashquot; (on (begin) [get-locator quot;ref-bus-crash-1quot;]] [player-disable-controls [signal quot;bus-donequot;] (controls all-but-right-stick)] ) [spawn-npc-in-combat quot;npc-wz-52quot;] (track (quot;playerquot;) [spawn-npc-in-combat quot;npc-wz-53quot;] [animate quot;playerquot; quot;player-watch-crashquot; ... [get-locator quot;ref-bus-crash-1quot;]] [go quot;crashquot;] [wait-until-frame 250] ) [say quot;playerquot; quot;vox-wz-drk-01-what-thequot;] ) [signal quot;drake-donequot;] ... ) ... Game Developers Conference 43
  • In-Game Cinematic: Bus Crash (state (quot;crashquot;) (on (begin) (define-state-script (quot;wz-bus-crashquot;) (track (quot;busquot;) (state (quot;spawn-soldiersquot;) [wait-animate quot;bus-1quot; quot;bus-crashquot; (on (begin) [get-locator quot;ref-bus-crash-1quot;]] [player-disable-controls [signal quot;bus-donequot;] (controls all-but-right-stick)] ) [spawn-npc-in-combat quot;npc-wz-52quot;] (track (quot;playerquot;) [spawn-npc-in-combat quot;npc-wz-53quot;] [animate quot;playerquot; quot;player-watch-crashquot; ... [get-locator quot;ref-bus-crash-1quot;]] [go quot;crashquot;] [wait-until-frame 250] ) [say quot;playerquot; quot;vox-wz-drk-01-what-thequot;] ) [signal quot;drake-donequot;] ... ) ... Game Developers Conference 43
  • In-Game Cinematic: Bus Crash (state (quot;crashquot;) ... (track (quot;guy-hit-by-busquot;) (define-state-script (quot;wz-bus-crashquot;) [wait-animate quot;npc-wz-52quot; quot;npc-hit-by-busquot; (state (quot;spawn-soldiersquot;) [get-locator quot;ref-bus-crash-1quot;]] (on (begin) [npc-die quot;npc-wz-52quot;] [player-disable-controls [signal quot;npc-deadquot;] (controls all-but-right-stick)] ) [spawn-npc-in-combat quot;npc-wz-52quot;] (track (quot;wait-for-all-donequot;) [spawn-npc-in-combat quot;npc-wz-53quot;] [wait-for-signal quot;bus-donequot;] ... [wait-for-signal quot;drake-donequot;] [go quot;crashquot;] [wait-for-signal quot;npc-deadquot;] ) [go quot;donequot;] ) ) ... ) ) (state (quot;donequot;) ... Game Developers Conference 43
  • In-Game Cinematic: Bus Crash (state (quot;crashquot;) ... (track (quot;guy-hit-by-busquot;) (define-state-script (quot;wz-bus-crashquot;) [wait-animate quot;npc-wz-52quot; quot;npc-hit-by-busquot; (state (quot;spawn-soldiersquot;) [get-locator quot;ref-bus-crash-1quot;]] (on (begin) [npc-die quot;npc-wz-52quot;] [player-disable-controls [signal quot;npc-deadquot;] (controls all-but-right-stick)] ) [spawn-npc-in-combat quot;npc-wz-52quot;] (track (quot;wait-for-all-donequot;) [spawn-npc-in-combat quot;npc-wz-53quot;] [wait-for-signal quot;bus-donequot;] ... [wait-for-signal quot;drake-donequot;] [go quot;crashquot;] [wait-for-signal quot;npc-deadquot;] ) [go quot;donequot;] ) ) ... ) ) (state (quot;donequot;) ... Game Developers Conference 43
  • In-Game Cinematic: Bus Crash (state (quot;crashquot;) ... (track (quot;guy-hit-by-busquot;) (define-state-script (quot;wz-bus-crashquot;) [wait-animate quot;npc-wz-52quot; quot;npc-hit-by-busquot; (state (quot;spawn-soldiersquot;) [get-locator quot;ref-bus-crash-1quot;]] (on (begin) [npc-die quot;npc-wz-52quot;] [player-disable-controls [signal quot;npc-deadquot;] (controls all-but-right-stick)] ) [spawn-npc-in-combat quot;npc-wz-52quot;] (track (quot;wait-for-all-donequot;) [spawn-npc-in-combat quot;npc-wz-53quot;] [wait-for-signal quot;bus-donequot;] ... [wait-for-signal quot;drake-donequot;] [go quot;crashquot;] [wait-for-signal quot;npc-deadquot;] ) [go quot;donequot;] ) ) ... ) ) (state (quot;donequot;) ... Game Developers Conference 43
  • In-Game Cinematic: Bus Crash (state (quot;crashquot;) ... (track (quot;guy-hit-by-busquot;) (define-state-script (quot;wz-bus-crashquot;) [wait-animate quot;npc-wz-52quot; quot;npc-hit-by-busquot; (state (quot;spawn-soldiersquot;) [get-locator quot;ref-bus-crash-1quot;]] (on (begin) [npc-die quot;npc-wz-52quot;] [player-disable-controls [signal quot;npc-deadquot;] (controls all-but-right-stick)] ) [spawn-npc-in-combat quot;npc-wz-52quot;] (track (quot;wait-for-all-donequot;) [spawn-npc-in-combat quot;npc-wz-53quot;] [wait-for-signal quot;bus-donequot;] ... [wait-for-signal quot;drake-donequot;] [go quot;crashquot;] [wait-for-signal quot;npc-deadquot;] ) [go quot;donequot;] ) ) ... ) ) (state (quot;donequot;) ... Game Developers Conference 43
  • In-Game Cinematic: Bus Crash (state (quot;crashquot;) ... (track (quot;guy-hit-by-busquot;) (define-state-script (quot;wz-bus-crashquot;) [wait-animate quot;npc-wz-52quot; quot;npc-hit-by-busquot; (state (quot;spawn-soldiersquot;) [get-locator quot;ref-bus-crash-1quot;]] (on (begin) [npc-die quot;npc-wz-52quot;] [player-disable-controls [signal quot;npc-deadquot;] (controls all-but-right-stick)] ) [spawn-npc-in-combat quot;npc-wz-52quot;] (track (quot;wait-for-all-donequot;) [spawn-npc-in-combat quot;npc-wz-53quot;] [wait-for-signal quot;bus-donequot;] ... [wait-for-signal quot;drake-donequot;] [go quot;crashquot;] [wait-for-signal quot;npc-deadquot;] ) [go quot;donequot;] ) ) ... ) ) (state (quot;donequot;) ... Game Developers Conference 43
  • Implementation 44
  • Virtual Machine • Scheme-like runtime language implemented by a simple VM  Each track compiled into block of byte code called a lambda (define-state-script (quot;kickable-gatequot;) (state (quot;lockedquot;) (on (begin) (track (quot;gatequot;) ... ) (track (quot;lockquot;) ... ) ) ) ) Game Developers Conference 45
  • Virtual Machine • Scheme-like runtime language implemented by a simple VM  Each track compiled into block of byte code called a lambda (define-state-script (quot;kickable-gatequot;) opcode1 operand1 (state (quot;lockedquot;) operand2 (on (begin) opcode2 (track (quot;gatequot;) ... ) (track (quot;lockquot;) ... ) ) ) ) Game Developers Conference 45
  • Virtual Machine • Scheme-like runtime language implemented by a simple VM  Each track compiled into block of byte code called a lambda (define-state-script (quot;kickable-gatequot;) opcode1 operand1 (state (quot;lockedquot;) operand2 (on (begin) opcode2 (track (quot;gatequot;) ... ) opcode4 operand4 (track (quot;lockquot;) opcode5 operand5 ... opcode6 ) ) ) ) Game Developers Conference 45
  • Virtual Machine • Internal state of VM consists of:  Pointer to current lambda (byte code program) cur instr lambd  Index to current instruction reg0 reg2 a  Bank of registers for temporary ___ reg1 reg4 ___ and immediate data • Registers are of type variant Game Developers Conference 46
  • Virtual Machine • Internal state of VM consists of:  Pointer to current lambda (byte code program) cur instr lambd  Index to current instruction reg0 reg2 a  Bank of registers for temporary ___ reg1 reg4 ___ and immediate data • Registers are of type variant Game Developers Conference 46
  • Virtual Machine • Internal state of VM consists of:  Pointer to current lambda (byte code program) cur instr lambd  Index to current instruction reg0 reg2 a  Bank of registers for temporary ___ reg1 reg4 ___ and immediate data • Registers are of type variant Game Developers Conference 46
  • Virtual Machine • Language supports nested lambd function calls a ___ • Hence requires call stack ___ ___  Stack frame = bank of registers + program counter cur instr reg0 reg2 reg1 reg4 Game Developers Conference 47
  • Virtual Machine • Language supports nested lambd function calls a ___ • Hence requires call stack ___ ___  Stack frame = bank of cur instr registers + program counter reg0 reg2 reg1 reg4 cur instr reg0 reg2 reg1 reg4 Game Developers Conference 47
  • Virtual Machine • Language supports nested cur instr lambd reg0 reg2 function calls a ___ reg1 reg4 • Hence requires call stack ___ ___  Stack frame = bank of cur instr registers + program counter reg0 reg2 reg1 reg4 cur instr reg0 reg2 reg1 reg4 Game Developers Conference 47
  • Virtual Machine • Language supports nested lambd function calls a ___ • Hence requires call stack ___ ___  Stack frame = bank of cur instr registers + program counter reg0 reg2 reg1 reg4 cur instr reg0 reg2 reg1 reg4 Game Developers Conference 47
  • Continuations • State script code can wait (sleep) lambd a • Implemented via something ___ known as a continuation ___ ___ cur instr reg0 reg2 reg1 reg4 Game Developers Conference 48
  • Continuations • State script code can wait (sleep) lambd a • Implemented via something ___ known as a continuation ___ ___ cur instr reg0 reg2 reg1 reg4 cur instr reg0 reg2 reg1 reg4 Game Developers Conference 48
  • Continuations • State script code can wait (sleep) lambd a • Implemented via something ___ known as a continuation ___ ___ continuati on Game Developers Conference 48
  • Continuations • State script code can wait (sleep) lambd a • Implemented via something ___ known as a continuation ___ ___ cur instr reg0 reg2 reg1 reg4 cur instr reg0 reg2 reg1 reg4 Game Developers Conference 48
  • Continuations • State script code can wait (sleep) cur instr lambd reg0 reg2 a • Implemented via something ___ reg1 reg4 known as a continuation ___ ___ cur instr reg0 reg2 reg1 reg4 cur instr reg0 reg2 reg1 reg4 Game Developers Conference 48
  • Native C++ Functions • The “meat” of an (on ...) block is its command sequence  Some commands are user-defined: (defun func1 (...))  Most commands are C++ hooks into the engine • Simple hash table maps function names to C++ code (define-c-function wait-animate Variant ScriptWaitAnimate(int argc, Variant* argv) (object-name string) { (anim-name string) ... ) } Game Developers Conference 49
  • Variant ScriptWaitAnimate(int argc, Variant* argv) { StringId objName = SC_ARG(0, StringId, NULL); StringId animName = SC_ARG(1, StringId, NULL); if (!objName) return ScriptError(quot;wait-animate: expected object name (arg1)nquot;); if (!animName) return ScriptError(quot;wait-animate: expected animation name (arg2)nquot;); // find the object ProcessGameObject* pObj = g_processMgr.Lookup(objName); if (!pObj) return ScriptError(quot;wait-animate: could not find %snquot;, 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); } Game Developers Conference 50
  • Game Developers Conference 51
  • Conclusion 52
  • 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 define new object types in script Game Developers Conference 53
  • 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 Game Developers Conference 54
  • 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 quot;messagequot;]) • Watch for race conditions  Event arrives too early or too late—missed  Object you’re trying to control hasn’t spawned yet, or has died  Tracks not synchronized properly Game Developers Conference 55
  • 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! Game Developers Conference 56
  • 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! Game Developers Conference 56
  • Thanks For Listening! • Free free to send questions to me at: jason_gregory@naughtydog.com • Naughty Dog is hiring! Send resumes to Candace Walker at: candace_walker@naughtydog.com Game Developers Conference 57