StateScriptingInUncharted2

644
-1

Published on

GDC09-JQGregory-StateScriptingInUncharted2.key

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
644
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
22
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide





  • Content creators gain an improved sense of ownership and empowerment.
    Engineering team is often a bottleneck; expensive resource.
    Treating code like data allows it to be modified and tested without requiring an engineer to recompile and relink the game.
    Some engines support on the fly script reloading—don’t even need to rerun the game.
  • Data def languages allow data structures to be populated for consumption by engine.
    Some data def languages even allow data structures to be defined by the scripter.
    Runtime languages are typically:
    Interpreted. Compiled into byte code, executed by a virtual machine (VM).
    Simple and small. Easy to parse; virtual machine has minimal overhead.
    Accessible. Designers, artists and other “non-programmers” can use it.
    Powerful. Small amount of code = big impact on game.
  • We use PLT Scheme (a Lisp variant) for data definition (http://www.plt-scheme.org).
    A simplified version of Scheme/Lisp (“Scheme lite”) is used for runtime scripting.
    Runtime code is a special kind of lambda.


  • The game object model:
    Defines the various object types that populate the game world.
    (Player, NPC, weapon, power-up, light, trigger region, AI nav poly, camera, ...)
    Often, but not always, implemented using an object-oriented language.
    ore details, see:
    Jason Gregory. Game Engine Architecture: A Comprehensive Guide. AK Peters, 2009.


  • “Lego block” approach to constructing new game object types
    Components can be authored in native C++ or in script








































  • The world editor for Uncharted is called Charter.
    Place game objects, trigger regions, splines, etc.
    Edit object properties.
    Control level streaming.













  • Uncharted task system defines player objectives, flow of control from “level” to “level”
    Tasks are primary save-game mechanism
    Task scripts are automatically killed when the task is completed

  • Uncharted task system defines player objectives, flow of control from “level” to “level”
    Tasks are primary save-game mechanism
    Task scripts are automatically killed when the task is completed

  • Uncharted task system defines player objectives, flow of control from “level” to “level”
    Tasks are primary save-game mechanism
    Task scripts are automatically killed when the task is completed

  • Uncharted task system defines player objectives, flow of control from “level” to “level”
    Tasks are primary save-game mechanism
    Task scripts are automatically killed when the task is completed

  • Uncharted task system defines player objectives, flow of control from “level” to “level”
    Tasks are primary save-game mechanism
    Task scripts are automatically killed when the task is completed

  • Uncharted task system defines player objectives, flow of control from “level” to “level”
    Tasks are primary save-game mechanism
    Task scripts are automatically killed when the task is completed

  • Uncharted task system defines player objectives, flow of control from “level” to “level”
    Tasks are primary save-game mechanism
    Task scripts are automatically killed when the task is completed

  • Uncharted task system defines player objectives, flow of control from “level” to “level”
    Tasks are primary save-game mechanism
    Task scripts are automatically killed when the task is completed

  • Uncharted task system defines player objectives, flow of control from “level” to “level”
    Tasks are primary save-game mechanism
    Task scripts are automatically killed when the task is completed

  • Uncharted task system defines player objectives, flow of control from “level” to “level”
    Tasks are primary save-game mechanism
    Task scripts are automatically killed when the task is completed

  • Uncharted task system defines player objectives, flow of control from “level” to “level”
    Tasks are primary save-game mechanism
    Task scripts are automatically killed when the task is completed

  • Uncharted task system defines player objectives, flow of control from “level” to “level”
    Tasks are primary save-game mechanism
    Task scripts are automatically killed when the task is completed

  • Uncharted task system defines player objectives, flow of control from “level” to “level”
    Tasks are primary save-game mechanism
    Task scripts are automatically killed when the task is completed



  • Square [brackets] can be used interchangeably with (parens)
  • Square [brackets] can be used interchangeably with (parens)
  • Square [brackets] can be used interchangeably with (parens)
  • Square [brackets] can be used interchangeably with (parens)
  • Square [brackets] can be used interchangeably with (parens)
  • Events identified by free-form strings
    Three special block types:
    (on (begin) ...) Executed when state is first entered
    (on (update) ...) Executed once every frame
    (on (end) ...) Executed when state is exited
  • Events identified by free-form strings
    Three special block types:
    (on (begin) ...) Executed when state is first entered
    (on (update) ...) Executed once every frame
    (on (end) ...) Executed when state is exited
  • Events identified by free-form strings
    Three special block types:
    (on (begin) ...) Executed when state is first entered
    (on (update) ...) Executed once every frame
    (on (end) ...) Executed when state is exited
  • Events identified by free-form strings
    Three special block types:
    (on (begin) ...) Executed when state is first entered
    (on (update) ...) Executed once every frame
    (on (end) ...) Executed when state is exited
  • Events identified by free-form strings
    Three special block types:
    (on (begin) ...) Executed when state is first entered
    (on (update) ...) Executed once every frame
    (on (end) ...) Executed when state is exited
  • Events identified by free-form strings
    Three special block types:
    (on (begin) ...) Executed when state is first entered
    (on (update) ...) Executed once every frame
    (on (end) ...) Executed when state is exited
  • Events identified by free-form strings
    Three special block types:
    (on (begin) ...) Executed when state is first entered
    (on (update) ...) Executed once every frame
    (on (end) ...) Executed when state is exited
  • Runtime script code exists inside (on ...) blocks.
    Runtime language is simplified Scheme:
    Imperative style.
    Most “commands” are native function calls into C++ code (hooks into the engine).
    Language also supports conditional expressions. For example:
    (when (condition) (do-if-true))
    (if (condition) (do-if-true) (do-if-false))
  • Runtime script code exists inside (on ...) blocks.
    Runtime language is simplified Scheme:
    Imperative style.
    Most “commands” are native function calls into C++ code (hooks into the engine).
    Language also supports conditional expressions. For example:
    (when (condition) (do-if-true))
    (if (condition) (do-if-true) (do-if-false))
  • Runtime script code exists inside (on ...) blocks.
    Runtime language is simplified Scheme:
    Imperative style.
    Most “commands” are native function calls into C++ code (hooks into the engine).
    Language also supports conditional expressions. For example:
    (when (condition) (do-if-true))
    (if (condition) (do-if-true) (do-if-false))
  • Runtime script code exists inside (on ...) blocks.
    Runtime language is simplified Scheme:
    Imperative style.
    Most “commands” are native function calls into C++ code (hooks into the engine).
    Language also supports conditional expressions. For example:
    (when (condition) (do-if-true))
    (if (condition) (do-if-true) (do-if-false))
  • Runtime script code exists inside (on ...) blocks.
    Runtime language is simplified Scheme:
    Imperative style.
    Most “commands” are native function calls into C++ code (hooks into the engine).
    Language also supports conditional expressions. For example:
    (when (condition) (do-if-true))
    (if (condition) (do-if-true) (do-if-false))
  • Functions in Lisp are called “lambdas”
  • Functions in Lisp are called “lambdas”
  • Functions in Lisp are called “lambdas”
  • Functions in Lisp are called “lambdas”
  • Functions in Lisp are called “lambdas”
  • Functions in Lisp are called “lambdas”
  • Functions in Lisp are called “lambdas”
  • Functions in Lisp are called “lambdas”
  • Functions in Lisp are called “lambdas”
  • Functions in Lisp are called “lambdas”
  • Functions in Lisp are called “lambdas”
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string
    “self” is much like the this pointer in C++
    Very convenient, since many scripts are designed to control the object to which they are attached
    Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.)
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string
    “self” is much like the this pointer in C++
    Very convenient, since many scripts are designed to control the object to which they are attached
    Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.)
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string
    “self” is much like the this pointer in C++
    Very convenient, since many scripts are designed to control the object to which they are attached
    Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.)
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string
    “self” is much like the this pointer in C++
    Very convenient, since many scripts are designed to control the object to which they are attached
    Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.)
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string
    “self” is much like the this pointer in C++
    Very convenient, since many scripts are designed to control the object to which they are attached
    Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.)
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string
    “self” is much like the this pointer in C++
    Very convenient, since many scripts are designed to control the object to which they are attached
    Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.)
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string
    “self” is much like the this pointer in C++
    Very convenient, since many scripts are designed to control the object to which they are attached
    Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.)
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string
    “self” is much like the this pointer in C++
    Very convenient, since many scripts are designed to control the object to which they are attached
    Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.)
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string
    “self” is much like the this pointer in C++
    Very convenient, since many scripts are designed to control the object to which they are attached
    Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.)
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string
    “self” is much like the this pointer in C++
    Very convenient, since many scripts are designed to control the object to which they are attached
    Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.)
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string
    “self” is much like the this pointer in C++
    Very convenient, since many scripts are designed to control the object to which they are attached
    Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.)
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string
    “self” is much like the this pointer in C++
    Very convenient, since many scripts are designed to control the object to which they are attached
    Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.)
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string
    “self” is much like the this pointer in C++
    Very convenient, since many scripts are designed to control the object to which they are attached
    Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.)
  • In Uncharted, object UIDs are 32-bit hashed strings called “string ids” Melds speed of an integer with human-readable string
    “self” is much like the this pointer in C++
    Very convenient, since many scripts are designed to control the object to which they are attached
    Other magic UIDs include the names of singleton characters in the game (e.g. player, sullivan, elena, chloe, etc.)
  • (go ...) is really just a native C++ function call
  • (go ...) is really just a native C++ function call
  • (go ...) is really just a native C++ function call
  • (go ...) is really just a native C++ function call
  • (go ...) is really just a native C++ function call
  • (go ...) is really just a native C++ function call
  • Track syntax can be omitted when there’s only one track
    Tracks are the only place runtime script code can exist
    All tracks within an (on ...) block run in parallel
    Ability to sleep is called “latent” code in Unreal
    “Actions” include playing an animation, playing an audio cue, an NPC walking from point A to point B, etc.
    Signals are like very simple Boolean semaphores































  • StateScriptingInUncharted2

    1. 1. State-Based Scripting in Jason Gregory Generalist Programmer Naughty Dog, Inc.
    2. 2. 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
    3. 3. Introduction to State Scripts 3
    4. 4. 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
    5. 5. 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
    6. 6. 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
    7. 7. 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
    8. 8. 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
    9. 9. 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
    10. 10. 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
    11. 11. 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
    12. 12. 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
    13. 13. 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
    14. 14. 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
    15. 15. 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
    16. 16. 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
    17. 17. 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
    18. 18. 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
    19. 19. 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
    20. 20. 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
    21. 21. 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
    22. 22. Uncharted Engine’s Object Model • Uncharted class hierarchy:  relatively shallow, single-root  host of add-on components Process SsProcess Game Developers Conference 14
    23. 23. Uncharted Engine’s Object Model • Uncharted class hierarchy:  relatively shallow, single-root  host of add-on components Process SsProcess SsInstance Game Developers Conference 14
    24. 24. 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
    25. 25. Charter • World editor for Uncharted is called Charter  Place game objects  Edit object properties  Control level streaming Game Developers Conference 15
    26. 26. 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
    27. 27. 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
    28. 28. 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
    29. 29. 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
    30. 30. 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
    31. 31. 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
    32. 32. 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
    33. 33. 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
    34. 34. 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
    35. 35. 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
    36. 36. 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
    37. 37. State Script Syntax 21
    38. 38. Game Developers Conference 22
    39. 39. 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
    40. 40. 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
    41. 41. 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
    42. 42. 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
    43. 43. 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
    44. 44. 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
    45. 45. 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
    46. 46. 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
    47. 47. 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
    48. 48. 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
    49. 49. 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
    50. 50. 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
    51. 51. 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
    52. 52. 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
    53. 53. 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
    54. 54. 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
    55. 55. 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
    56. 56. 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
    57. 57. 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
    58. 58. 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
    59. 59. 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
    60. 60. 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
    61. 61. 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
    62. 62. 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
    63. 63. 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
    64. 64. 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
    65. 65. 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
    66. 66. 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
    67. 67. 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
    68. 68. 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
    69. 69. 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
    70. 70. 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
    71. 71. 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
    72. 72. 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
    73. 73. 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
    74. 74. (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
    75. 75. (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
    76. 76. (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
    77. 77. (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
    78. 78. (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
    79. 79. Configuration Parameters • All game objects have properties (key-value pairs)  Property values edited in Charter Game Developers Conference 34
    80. 80. Configuration Parameters • All game objects have properties (key-value pairs)  Property values edited in Charter Game Developers Conference 34
    81. 81. 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
    82. 82. Configuration Parameters • State scripts have read-only access to game object properties...  ... and free-form tags Game Developers Conference 35
    83. 83. 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
    84. 84. 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
    85. 85. 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
    86. 86. 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
    87. 87. 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
    88. 88. 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
    89. 89. 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
    90. 90. Case Studies 37
    91. 91. Custom Object Type: Breakable Sign Game Developers Conference 38
    92. 92. Custom Object Type: Breakable Sign Game Developers Conference 38
    93. 93. 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
    94. 94. 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
    95. 95. 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
    96. 96. 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
    97. 97. 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
    98. 98. 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
    99. 99. 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
    100. 100. 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
    101. 101. 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
    102. 102. 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
    103. 103. 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
    104. 104. 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
    105. 105. 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
    106. 106. 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
    107. 107. 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
    108. 108. 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
    109. 109. 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
    110. 110. 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
    111. 111. 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
    112. 112. 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
    113. 113. 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
    114. 114. 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
    115. 115. 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

    ×