ILIOS GUIDE

VISUAL SCRIPTING AND TYPED CODE

ILIOS is a scripting language that you can approach either by Visual Scripting or classic Typed Code. Along with Box2D will allow you to create physics-based games, such as Platformers or even RPGs!

Have fun and be creative!

Introduction #

While Visionaire is a really powerful engine designed originally for 2D point ‘n click adventure games, it is possible since version 5 with the addition of Box2D and the Ilios scripting language to create different genre games, like physics-based platformers. So, welcome to the first Box2d/Ilios scripting tutorial for Visionaire! Let’s try to make a prototype platformer and see how this works 🙂

 

Some useful reference links:

 

https://box2d.org/documentation (Box2D)

https://www.visionaire-studio.com/luadocs/ilios.html (Ilios)

 

Feel free to contact us for your comments, ideas and any assistance to your projects! As always, the community’s assistance is also there to help:

 

https://www.visionaire-studio.net/forum (Forum)
https://discord.com/invite/g5zFejW (Discord)

Yes No Suggest edit
0 of 0 users found this section helpful

Prerequisities #

For this tutorial, we will use:

 

  • The Animated Pixel Adventurer asset pack which can be found here: https://rvros.itch.io/animated-pixel-hero . While it can be downloaded for free, we strongly encourage you to support the creator with a donation to allow them to create such nice assets!
  • Background Image 
  • Visionaire Studio 5.1.9.2 + 

 

Please note that while deep programming knowledge is not critical, it’s highly recommended to know the basics of object-oriented programming in order to fully understand the concepts set out in this tutorial. This guide’s primary purpose is not teach programming but to show implementation of these concepts on the Visionaire engine.

 

Yes No Suggest edit
2 of 2 users found this section helpful

Quickstart #

Ilios is offering Visionaire a component-based approach to game development. The basic principle is to create behaviours (which are basically classes) that can then be attached to objects, characters, scenes, interfaces, buttons, and the game itself through components. The basic steps can be summarized below:

 

1. Create a script block to hold your Behaviour Class 

 

Go to the Visual Scripting tab and create a new block entry. You are now ready to create your class. You have 2 options: Visual Scripting (Blocks Tab) or classic Typed Code (Code Tab). Both offer basically the same functionality so it’s a matter of preference. Will show you first how to do it with the visual editor and at the end of this section you can see the code version.

 

2. Create a Behaviour Class

 

On the Visual Scripting Editor, Click on the canvas. This will bring up the Block List to create your block. Choose ‘New Class’ and double click to confirm.


You can now name your class and assign it to a behaviour superclass. A behaviour superclass is just a mother class which holds basic behaviours for Visionaire entities (objects, characters, scenes, interfaces, buttons, and the game itself). By assigning your class to a superclass, you inherit from it all these behaviours which you can now override and alter and you will be able to attach your new behaviour to the relevant Visionaire entity through components.

 

The behaviour superclasses available are:

 

  • GameBehaviour
  • ObjectBehaviour
  • CharacterBehaviour
  • SceneBehaviour
  • ButtonBehaviour,
  • Interface Behaviour

 

For now let’s make an object behaviour so let’s attach it to ObjectBehaviour superclass:

Click OK when finished and your class node is now on the canvas:

 

3. Create your function

 

By click on the + sign you can create connection points (yellow dot) for adding functions, variables, states etc to your class. Just click on a connection point and drag it anywhere on the canvas, then release it. A list of possible nodes to connect to will be shown.


More importantly, you will now be able to Override functions of the ObjectBehaviour superclass, like for example the Fixed Update function which runs at every frame (50 times per second). Let’s do this then:

 

The Fixed Update block is now visible. It’s colour is yellow, denoting that it is a function:

 

Now let’s call a method to print something on the screen. This method for this is Debug.Print(). Click anywhere on the canvas to open the block list and search for ‘debug’, double click to choose Print(string) from the Debug internal class:

 

The block looks like this:

 

You notice that it has an input node to the left (purple color dot means ‘string’ input). Similarly, output nodes are positioned to the right of the block, but here there is no any. To enter your string input here you have 2 ways: either connect a string, or enter the text directly. Let’s do the 2nd for now, click on the small box to the left of the purple dot and you can enter your text:

 

 

4. Create your execution flow

 

The Debug.Print block is ready but won’t run unless we connect it with our class and update function. We can connect blocks by dragging a white line between them, the ‘Execution Flow’ line.  Execution starts at a function, follows the line, and executes all blocks in order.

 

Just drag from the small white arrow on the FixedUpdate over the Debug.Print block (you will see a hint msg ‘add exec’) and release. The blocks are now connected and our first script is ready! 

 

5. Connect the behaviour to your object

 

Our new script – behaviour is now available under the components tab to be connected to our object (test-player):

 

When you Run Game, open the console (TAB) and note that under Lua Execute you will see Debug.Print being executed 50 times/s as it is inside the Update function. Well done!

 

7. Using Function Arguments

 

Now let’s say that we also want to print out the object’s name (“test-player” in our case). How can we retrieve the linked object’s data and manipulate it? The secret is in the Update function’s “this” argument:

 

 

‘this’ holds a reference to the object currently linked to the behaviour and it will help us access and manipulate its properties. To do this, you need to click and drag ‘this’ and drop it on the canvas:

 

You now have an instance of the linked object and full access to its properties. For example, we want to retrieve and print the object’s name; click and drag the output node on the right (blue dot) and drop it on the canvas. A list of possible Visionaire Object properties are now available to select, so go ahead and choose Name:

 

You will now see the Name node appear and getting linked to this. You also see that it has a purple output node which means that it’s of string type:

 

And you guessed right; you can connect the purple output node to a block that accepts strings as input, and yes that is our purple Debug.Print block, so go ahead, make a new Debug Print Block and link it:

 

Finally, connect the two Debug.Print blocks using the execution line so that they run one after the other and your script is ready:

 

And you can confirm it in the console:

 

The code version of the above looks like:

 

class TestClassCode : ObjectBehaviour

{
  override void FixedUpdate() 
  {
      Debug.Print("Hello World! -Code Version-");
      Debug.Print(this.Name);      
  }
}

 

(we changed a bit the Class name so that you can use it interchangeably with TestClass component in the dropdown):

 

Project Files

quickstart.veb Visionaire file containing this section’s example.

 

Yes No Suggest edit
0 of 0 users found this section helpful

Setup Player's Physics #

Setting the Assets

 

The basic steps to setup our player are:

 

  • Create the player object (e.g. test-player)
  • Create an idle animation, add its frames and Adjust its settings (set it to Infinite Loops!):

 

  • Position the animation on the canvas, for now place it at (40,90)

 

 

  • Finally, for now, set the idle animation to be the default animation for the player:

 

Now if you run the game you will see the player on the screen with his idle animation. A few notes though due to the small size of the pixel art player assets to improve the display:

 

  • Set the resolution to 320×240 px
  • At a script at Start Action to enlarge the window area:

 

  • Activate Pixel Effect for a crispy pixel display: 

 

 

Apply Physics Properties

 

Visionaire uses Box2D engine to apply physics behaviours to objects through components so let’s add some to our player. To have a fully working Box2D object, you need to define 1. a Body and 2. a Fixture component:

 

Think of a body as the properties of an object that you cannot see (draw) or touch (collide with). These invisible properties are:

 

  • mass – how heavy it is
  • velocity – how fast and in which direction it’s moving
  • rotational inertia – how much effort it takes to start or stop spinning
  • angular velocity – how fast and which way it’s rotating
  • location – where it is
  • angle – which way it is facing

 

So let’s add a body to our player:

 

Note that there are 3 types of Box2D bodies: 

 

  • dynamic body – a body that is affected by world forces and reacts to collisions. Our player is one example.
  • static body – a body that isn’t affected by world forces and does not react to collisions. It can’t be moved, e.g. wall or the ground.
  • kinematic body (not supported at the moment) – a hybrid body that is not affected by forces and collisions like a static body but can be moved with a linear velocity like a dynamic body. Example is a moving platform.

 

  • Static – leave it unticked, we want our player to be a dynamic body
  • Fixed Rotation – Prevents the body from rotating (e.g when colliding). We need that for our player!
  • Linear Damping – Used to reduce the linear velocity
  • Angular Damping – Used to reduce the angular velocity
  • Gravity Scale – Used to weaken or strengthen the effect of the world’s gravity. E.g. 1 = normal gravity, -1 = reverse gravity, 0 = zero gravity etc.

 

Even if you know all of these characteristics of an object, you still don’t know what it looks like or how it will react when it collides with another object. To define the size and shape of an object we need to use fixtures; fixtures are used to describe the size, shape, and material properties of an object. One body can have multiple fixtures attached to it, and the center of mass of the body will be affected by the arrangement of its fixtures. When two bodies collide, their fixtures are used to decide how they will react. The main properties of fixtures are:

 

  • sensor – whether the fixture is sensor or not. Sensors detect collisions but do not react to them (our player is not a sensor)
  • friction – how slippery it is
  • restitution – how bouncy the fixture is
  • density – how heavy it is in relation to its area
  • shape – a polygon or circle

 

So let’s add a fixture to our body. Note that you can make 3 fixture shapes: 1. Rectangle, 2. Circle, 3. Edge (free form). All work similarly but for our example let’s choose the box one:

 

The red rectangle we created is actually the bounding box that defines the collision borders of our player.

 

Try to run the game now. The player will fall off the screen due to gravity, nice! (well, sort of). So let’s make some ground. Add the background image provided above and setup a new ground object and its relevant (static!) body and fixture:

 

 

Try to run the game and now the player will stand on the ground, our first collision is a fact!

 

Project Files

player-setup.zip Zip file containing this section’s example.
Yes No Suggest edit
2 of 2 users found this section helpful

Constructors #

A Constructor is a special method which is invoked automatically at the time of object creation and is used to initialize the data members of the new object fast.

 

Creating a Constructor (Code and Visual Scripting)

 

Create a new block, and in the code tab let’s create a class for Weapon objects which will also hold the Weapon constructor:

 

class Weapon : object // we inherit from the object Superclass

{

  string wpnName;
  int dmg;
  float fRate;
  
  Weapon(string weaponName, int damage, float fireRate) // constructor, needs to have the same name with its class
    {
      	this.wpnName = weaponName;
      	this.dmg = damage;
      	this.fRate = fireRate;
      Debug.Print("Created ${this.wpnName} with Damage ${this.dmg} and Fire Rate ${this.fRate}");
    }
    
}

A few notes:

 

  • Such objects inherit from the internal ‘object’ superclass and cannot be attached on any Visionaire object, as they do not describe any behaviour.
  • the constructor must have the same name as its Class (‘Weapon’ in this case).
  • ‘this’ refers to the Weapon object (instance) currently being created.

 

The equivalent script in visual scripting looks like this:

 


(Click image to enlarge)

 

To create the constructor in the block editor, just create a normal function block, but instead select ‘Constructor’:

 

 

Using the Constructor (Code and Visual Scripting)

 

For this example we want the objects to be created 1 time upon script loading, so we place their creation inside the Awake(). We will also attach the script on our main player, so our Superclass here will be ObjectBehaviour.

 

class MainPlayer : ObjectBehaviour

{

  override void Awake()
  
  {

  Weapon axe = new Weapon("Axe", 7, 3);    
  Weapon sword = new Weapon("Sword", 5, 4);
  
  }

}

 

Visual Scripting version:

 

 

Now if you run the project and check the console, you will see the two objects (sword and axe) being created:

 

 

Constructor Overloading

 

You can also create multiple constructors for the same object but with different signatures. Signature is the part of the constructor declaration which holds the arguments, ie the part inside the parentheses:

Weapon(string weaponName, int damage, float fireRate)

So you can have in addition, a constructor with no parameters Weapon() and one with only a string for the weapon name Weapon(string weaponName). This gives you the flexibility to instantiate weapon object with various ways, e.g. Weapon(spear) or just Weapon()

 

Project Files

constructors.veb Visual scripting version for the above example.
constructors-code.veb Code version for the above example.

 

 

Yes No Suggest edit
0 of 0 users found this section helpful
Suggest Edit