Your First HSL Script

From HEWIKI
Jump to: navigation, search

Contents

This is an intermediate-level tutorial on how to write an HSL script that uses class methods, which will cause a visible reaction to an object on the screen when the mouse is moved

Before working through this tutorial, you should have worked through or be familiar with:

Overview

In this tutorial you will:


Assume you want to create an object that will move away from the mouse when a user moves the mouse pointer over the object. This is an easy task with HeroEngine, but as they say, "the devil is in the details..."

This tutorial will walk you through creating a class in the client DOM that will receive mouse events and cause an object which has the class GLOMmed onto it to move when the OnMouseEnter event occurs. When our event occurs, our object will move away from its current position by a random offset along the x/z axis.

What problems does this tutorial address?

What problems does this tutorial not address?

Concepts

Mouse Events are generated by the input system

Mouse events are generated by the C++ engine and passed into the input system, passing through whatever input layers are defined by your game. By default, the Clean Engine's mouse events enter the _Input_Mouse script which makes calls to the $INPUT system node.

Important: The HSL Input System only receives notification when you are in Character mode, either in HeroBlade by selecting the character mode button or by virtue of connecting using the (non-development) player client.

Implementation

The class methods script _scriptingTutorial1 serves as a code example for this tutorial. Included in it are two different ways of transforming the object's position: One does it as an immediate update, and the other way transforms the object's position/rotation/scale to the desired target values over time, using the _transform3d class.

The steps for implementation are:

Create a Client Class

Using the DOM Editor, create a new client class with a name that is <yourName> + ScriptingTutorial1 (ex. ChristopherScriptingTutorial1). For this particular tutorial you will not need any member fields for your new class.

Create a Class Method script

Using the HeroScript Editor, create a new empty client script and name it <yourName> + ScriptingTutorial1ClassMethods (ex. ChristopherScriptingTutorial1ClassMethods).

Add an Instance from the Library

AssetLibraryCleanEngineUtilityBox.png
HeroEngine comes with a few default objects, one of which is a plain white box. Using the Library, add a box (or sphere if you prefer) near your camera by double-clicking on it.

You can use any normal asset you like, but the white box comes with Clean Engine.

Important: Make sure to select the Instance of the asset and use the Properties panel to set the MouseTargetable property to true. This tells the input system that this object can receive mouse events. If you do not set MouseTargetable to true, you will only get the mouse events when you have the node selected with one of HeroBlade's selection tools.

You also need to verify that the Moveable property is also set to true for this instanced asset.


Add your Class to the Instance

PropertyPanelGUID.png

Select the instance of the white box that you created and open the HeroBlade's Properties Panel, you will need to copy the GUID of the instance for use with a CLI command to add your class to the instance.

Once you have copied the GUID's ID, use the following command in the Console window.

/mnac <GUID>, <YourClassName>

ex. /mnac 94870044549, ChristopherScriptingTutorial1

MNAC stands for Modify Node, Add Class. This command will add the new class you just created to the existing node. Remember that in HeroEngine, a node is an instantiation of a class and a node can have any other class added to it at any time. In this way a node can dynamically change what it is (through aggregation of new classes) at run-time. On the client, all asset instances (such as the white box you just created) are backed up by an HSL node. And by adding your new class to this node, we can now implement some methods to respond to mouse events for it.

We are now ready to implement the behaviors for our object.


Writing code for your Class Method Script

Your class method script will need to do these four tasks:

It is intended that you copy and paste the sample code into your class methods script. Remember to submit the new script after it is compiled. Take the time to try understand what the code is doing, once you have this sample running use the exercises to expand what the code does to manipulate different or additional Properties.


Catching a Mouse Event

Assuming you have not overridden the Clean Engine implementation of the Input System, the _InputHandlerClassMethods script makes a callback to a shared function InputMouseEvent. Using the args passed in, we can identify the node to which the event applies and modify its parameters (position, diffuse and ambient colors)

Having received an event and identified the node for which the event was generated, we can make use of the node's Properties to manipulate the node in a variety of ways (including the position).

shared function InputMouseEvent(args references Class _MouseEvent)
// Mouse event generated from the _InputHandlerClassMethods Script assuming it 
//   has not been overridden by a game specific implementation.
//
 
  // Get the Node For which the Event was Generated
  target as NodeRef = args.MouseTarget
 
  // Type Cast the node so we can access its fields/properties
  where target is kindof HBNode
    when args.MouseEventType
      is Enter        
        target._scriptingTutorial1SimpleReposition()      
 
        // Change the Ambient and Diffuse for fun
        target["AmbientColor"] = target._scriptingTutorial1GetRandomColorAsString()
        target["DiffuseColor"] = target._scriptingTutorial1GetRandomColorAsString()
      .
      default
        // Allow other events to fall through, doing a println
        println(args.MouseEventType)
      .
    .
  .
.

You may notice that the only two events you get in Hero's Journey right now are Enter and Leave, that is because the other events are overridden to support a legacy implementation until such a time as we refactor that particular aspect of Hero's Journey.

Get a Random Positional Offset

This method produces a random offset to apply to the current position of our object by producing a value of 1 to -1 units of offset.

method _scriptingTutorial1GetRandomPositionalOffset() as Vector3
// Select a random positional offset along the x and z axis
//
  offset as Vector3
  offset.x = RandomFloat() * 2.0 - 1.0
  offset.y = 0.0
  offset.z = RandomFloat() * 2.0 - 1.0
 
  return offset
.

Reposition the Object

Using the Random Positional Offset method we created for our class, this method repositions the object by setting its position to its current position plus the offset.

If you look closely at the Properties Panel, you should notice 'Position is one of the properties listed there. HSL may manipulate any of the properties you see using a special syntax of aNode["PropertyName"] = value.

method _scriptingTutorial1SimpleReposition()
// Simple routine to set the position of this node to a new position based on an random offset
//
 
  // Get current Position, the external function GetNodePosition is faster than
  //   accessing the value as a Property target["Position"]
  Pos as Vector3
  GetNodePosition( me, Pos )
 
  // Adjust the desired position to the current position plus a random offset
  Pos = Pos + me._scriptingTutorial1GetRandomPositionalOffset()
  SetNodePosition( me, Pos  )
.

Random colors for the object's ambient and diffuse colors =

Change the Properties for Ambient and Diffuse lighting for an object to two random colors. The required format for various properties can be found here.

method _scriptingTutorial1GetRandomColorAsString( ) as String
// Choose a random color and set the ambient or diffuse color for this node
//
  var r = randomFloat()
  var g = randomFloat()
  var b = randomFloat()
  var a = randomFloat()
 
  // Clamp the alpha to no less than 50% 
  if a < 0.5
    a = 1.0 - a
  .
 
  // Properties have special string formating that is parsed
  //   For plain old RGBA color it is #r,g,b,a where rgba are floats
  color as String = "#" + r + "," + g + "," + b + "," + a
 
  return color
.

Exercises

Look at the sample code

Color change over time

Using a TimeLine

The easiest way to get color properties, is to set a node's properties with the Properties Panel, and then copy/paste the resulting string property into your script:

Using a Timer

Instead of changing the color each time the mouse enters or with a timeline, add a timer field to your class and change the color at some time interval. You will need to start the timer the first time the mouse enters...

Where should I go from here?

A more advanced tutorial that makes a good followup is the Replication Tutorial which addresses a number of more advanced concepts with a lot of detail.


See also

Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox