Beyond State

posted in A Keyboard and the Truth for project 96 Mill
Published July 22, 2009
Advertisement
State is wonderful, but without processes to change state it is useless; it would remain frozen in time, just as the developer created it.

When a game is created in the Selenite Editor, the configuration of the state is built as it should be for when the game starts:


  • NPCs waiting to be discovered.

  • Enemies waiting to kill you.

  • Items scattered and hidden about.



The initial state is a untouched place, until the first update.

Pushing state through time

The Selenite state is made to be pushed forward by increments of time; fractions of a second per update usually. At the core of the engine a great loop (the game loop of course) triggers an update which echoes through the state tree, from the game to the currently selected room to all its actors and with this update the amount of time (in fractions of a second) to push forward is passed.

As the update touches the game, room and actors, it 'animates' them as if it were the life-blood of the engine.


  • the camera moves towards the selected actor

  • the physics simulation solves collisions and applies velocities.

  • actors push their current frame forward in frames-per-second

  • logic events are fired

  • pause locks are released

  • sound channels are released

  • color and lighting values shift as needed

  • and a whole other wealth of mechanics move



With each update of the state, the forces that govern it, change the state.

The programmable nature of Selenite

While selenite supports a lot of Fixed-Function features; (such as actors that automatically animate) the real power of selenite comes from it's scriptable nature. It is with scripting that you really begin to author the game.

Scripting in Selenite, works on a system of events and API functions; it is implemented with the Lua scripting engine.

Events

Events are slots where script code can be written, only certain objects can fire certain events and the parameters passed vary from event to event.

In terms of the selenite data and state design, there can be any number of events for any object type of any name, however The Selenite Editor and Selenite Engine currently agree on a certain set of events for state objects.

the parameter 'this' is passed for all events and represents the calling object.

StateObject

  • load - a very important event, called on each object when a state is loaded, either as a new game or a previously saved game; whether or not its a new game or a saved game, is passed as a parameter to allow for one-time initialization

  • logic - an event called when the state object's logic value elapses, used for AI and timed recurring processes



Game

  • combine - called when one inventory item is dropped on another inventory item, both items are passed as item1 and item2; this function is called twice with item1 and item2 values being transposed (to avoid having to code for both drop-orderings)



DisplayObject
no special events for display object

Room

  • enter - called when a new room is selected, 'this' is the new room

  • leave - called when a new room is selected, 'this' is the old room



Actor

  • item - when the player drops an inventory item on an actor, item id is passed

  • topic - when the player chooses a topic for this actor in a dialogue sequence, topic id is passed

  • talkBegin - right before an actor is about to say something via the talk command

  • talkDone - after talking is finished for the actor

  • moveBegin - before an actor begins moving

  • moveDone - when an actor has gone from moving to rest

  • collision - called when an actor is collided with another actor, both actors are passed in actor1 and actor2, and this function is called twice, with actor1 and actor2 transposed

  • click - when the actor is clicked




These events, provide a robust way to write scripts to further impact the game state; but to actually impact the state, we need API functions to do so.


The Selenite Scripting API

The Selenite engine exposes to Lua scripts a set of functions used for changing the state in a traditional procedural fashion; an example of some of these functions are:

[] parameters are optional

  • place(actor,[x,y]):x,y - gets or sets the current actor position

  • marker(room,id):x,y - gets the named marker position of a room

  • room([roomObj]|[actorObj]):roomObj - gets or sets the current room, or gets an actors current room

  • actor([actorObj]):actorObj - gets or sets the current actor

  • actors([roomObj]|[actorObj,radius]):table - gets all actors in a room, or all actors around actorObj within a given radius

  • talk(actorObj,text) - makes the actor talk in accordance with current language settings

  • item(id,[amount]):amount - adjusts the amount of an inventory item and/or returns the current amount of an item

  • anim(actor,anim,[restart]):syncobj - sets the current animation for an actor, optional parm restart dictates whether or not to reset to frame 0 if 'anim' is the currently playing animation

  • sound(stateobj,id):syncobj - set a sound to playing on an object

  • stopSound(stateobj,id) - stop a sound from playing on an object

  • color(dispobj,a,r,g,b,v):syncobj - start a color shift on a display object from the current color to the new a,r,g,b at a rate of (v) in units per second, if v is <=0 the shift is immediate

  • light(dispobj,r,g,b,v):syncobj - start a light shift on a display object from the current light to the new r,g,b at a rate of (v) in units per second, if v is <=0 the shift is immediate

  • brightness(actor,b,v):syncobj - start a brightness shift on an actor from the current brightness to the new b at a rate of (v) in pixels per second, if v is <=0 the shift is immediate

  • beginDialogue(actor) - begin a topic-choice sequence with the topics of 'actor'; will terminate a currently active topic-choice sequence

  • endDialogue() - terminates the current topic-choice sequence

  • lock(stateobj):bool - tries to take an object's mutex for dedicated use of this object, returns true if mutex is taken, false if mutex is already taken

  • unlock(stateobj) - unlocks the current objects mutex

  • force(actor,x,y) - applies a force to the actor object

  • torque(actor,v) - applies a torque to the actor object

  • logic(stateobj,[logic]):logic - sets and or gets the objects logic property

  • visible(actorobj,[v]):v - sets and or gets the actors visible property

  • clickable(actorobj,[v]):v - sets and or gets the actors clickable property

  • shadow(actorobj,[v]):v - sets and or gets the actors shadow property

  • setKey(stateobj,key,value) - sets the custom data value 'value' into 'key' on stateobj

  • getKeyString(stateobj,key):v - gets the custom data value 'key' from stateobj as a string

  • getKeyNumber(stateobj,key):v - gets the custom data value 'key' from stateobj as a number

  • getKeyBool(stateobj,key):v - gets the custom data value 'key' from stateobj as a boolean

  • pause(stateobj,time) - pauses the script in the locking context of stateobj for 'time' seconds

  • video(id) - play a cutscene video

  • and more...



With all these functions, it makes it easy to write scripts and make engaging games.
0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement