Scripts

From Plasmaworks

Jump to: navigation, search

Overview

A Plasmacore Script is an object-oriented list of commands that are sequentially executed. A Script is used to enqueue a series of actions to be executed over time and is better suited to modeling pre-planned actions than a state machine.

To use scripts:

  • [include "script.slag"]
  • Add a Script property to any and all classes that could make use of it.
  • Extend "Cmd", override on_activate() to perform setup, and override execute().Cmd to perform an action whenever Script::update() is called; return "this" to execute the same command on the next update() or return "next" to continue executing the next command.
  • Add extended Cmd objects to a script with Script::add(Cmd).
  • Add "CmdFn<<arbitrary code>>()" objects that execute a small piece of arbitrary code without having to create an entire class.
  • Add predefined CmdWait(seconds) objects to pause script execution.
  • Call Script::update().Logical to update a script. It will return "false" if there are no remaining commands.
  • Use a CmdGroup object to execute multiple commands simultaneously. Each command can be its own Script if desired.
  • Instead of returning "this" or "next" from Command::execute(), you can return a new Cmd object or chain of objects to be the next command.

Examples

 # Test app that cycles the background color through red, green, and blue, changing every second.
 # A debug message is printed out when the script is finished.
 [include "script.slag"]
  
 class Test : Screen
   PROPERTIES
     script() : Script
  
   METHODS
     method init
       script.add( CmdWait(1) )
       script.add( CmdBGColor(Color.red) )
       script.add( CmdWait(1) )
       script.add( CmdBGColor(Color.green) )
       script.add( CmdWait(1) )
       script.add( CmdBGColor(Color.blue) )
       script.add( CmdFn<<println("Script finished")>>() )
  
     method update
       script.update
 endClass
  
 class CmdBGColor( Color color ) : Cmd
   METHODS
     method on_activate
       Display.background_color = color
 endClass
 # Test app that moves a box to four corners of the screen
 # over and over, changing the color of the box after every 
 # cycle.
 [include "script.slag"]
  
 singleton class Test : Screen
   PROPERTIES
     script() : Script
     square(0,0,64,64) : Box
     color=Color.red : Color
  
   METHODS
     method update
       if (not script.update)
         local var x2 = Display.size.x - 64
         local var y2 = Display.size.y - 64
         script.add( CmdMoveSquare( x2,  0, 1.0 ) )
         script.add( CmdMoveSquare( x2, y2, 1.0 ) )
         script.add( CmdMoveSquare(  0, y2, 1.0 ) )
         script.add( CmdMoveSquare(  0,  0, 1.0 ) )
         script.add( CmdFn<<Test.color=random_Color>>() )
       endIf
 
     method draw
       square.fill( color )
 endClass
  
 class CmdMoveSquare( Real64 dest_x, Real64 dest_y, Real64 interval ) : Cmd
   PROPERTIES
     ticks : Int32
     delta : Vector2

   METHODS
     method on_activate
       ticks = interval * 60
       delta = (Vector2(dest_x,dest_y) - Test.square.position) / ticks

     method execute.Cmd
       Test.square += delta
       --ticks
       if (ticks?) return this
       else        return next
   endClass
 # This script-based example types out a message, blinks
 # it three times, and repeats.
 [include "script.slag"]
  
 singleton class Test : Screen
   PROPERTIES
     message  : Message
     script() : Script
  
   METHODS
     method init
       message = Message( "Scripts are cool.", Display.center )
 
     method update
       if (not script.update)
         script.add( CmdWaitFor(message) )
         script.add( CmdFlash(message,3) )
         script.add( CmdReset(message) )
       endIf
 
     method draw
       message.draw
 
     method on( MouseEvent e )
       if (e.is_button_press) message.reset
 endClass
 
 class Message( String text, Vector2 position )
   PROPERTIES
     count         : Int32
     visible=true  : Logical
     script()      : Script

   METHODS
     method reset
       visible = true
       count = 0
       script.clear
 
     method revealed.Logical
       return (count == text.count)
 
     method update
       if (not script.update)
         if (count < text.count)
           ++count
         else
           visible = not visible
         endIf
         script.add( CmdWait(0.20) )
       endIf
 
     method draw
       if (visible)
         SystemFont.handle = Handle.center
         SystemFont.draw( text.leftmost(count), position )
       endIf
 endClass
 
 class MessageCmd( Message message ) : Cmd;
 
 class CmdWaitFor : MessageCmd
   method execute.Cmd
     message.update
     if (message.revealed) return next
     return this
 endClass
 
 class CmdFlash : Cmd
   PROPERTIES
     message : Message
     times   : Int32
 
   METHODS
     method init( message, times )
       times = times * 2  + 1
 
     method execute.Cmd
       message.visible = not message.visible
       --times
       if (times?)
         return CmdWait(0.2).chain(this)
       else
         return next
       endIf
 endClass
 
 class CmdReset : MessageCmd
   method on_activate
     message.reset
 endClass

Credits

The Plasmacore Script system is based on Paul Stevens's (Riverman Media) Action Queue system.