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!
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)
For this tutorial, we will use:
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.
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:
Â
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. |
Â
Setting the Assets
The basic steps to setup our player are:
Â
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:
Â
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:
Â
Â
So let’s add a body to our player:
Note that there are 3 types of Box2D bodies:Â
Â
Â
Â
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:
Â
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. |
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:
The equivalent script in visual scripting looks like this:
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. |
There are 3 ways to use Ilios scripts in Visionaire.
Â
as a component, that gives objects a type of behaviour
as a global class that other scripts can access
or as a data template, which is a definition of a type of data or type of class that other scripts will use