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!
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.
The core gameplay would be quite simple: reach the end of the level while avoiding any traps, obstacles and enemies, collecting stuff and using ladders.
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. |
We’ll start by slicing the player’s spritesheet and then importing the animations into Visionaire. Then we need to assign some physics properties using box2d.
Using Sprite Sheet Slicer:
In Visionaire, create a new object (let’s call it player) under a scene (let’s call it level1) and import the animations. Set the idle animation as the default animation for now, so that we’ll be able to see it on the scene when running the game.
In order for the player to respond to collisions and to various forces, we need to create a box2d body for it and attach a fixture for it. This can be easily done with the relevant components that we attach to the player object:
Now if you run the game you will see the player falling of the screen.
Next step is to create our level in Tiled and then import in in Visionaire.
Using Tiled, will create a level along with the necessary collission info in order for Visionaire to use this with box2d.
First we create the map of the level. Basis the fact that our game resolution is 320 x 240 and the tile size is 8×8 let’s make a 960×480 px map (yeap, there will be scrolling, stay tuned. So create the map and save it as a tmx file.
Now let’s create our tileset from the tiles.png image of the Paper Pixel theme.
Now let’s set the collision info. This is a critical step that needs to be done before we start laying out the map; it will define which tiles have collision data, like walls, ground, etc. In the tileset editor, use the collision editor and adjust the bounding boxes for any tiles that need collision info as per below:
Now you can build your level in Tiled; you can also see the Collision info at anytime with View-> Show Tile Collision Shapes
Finally, let’s prepare the map to be imported in Visionaire. Critical to remember that any tilesets (normally .tsx files) neeed to be embedded in the map (.tmx) file, otherwise Visionaire won’t parse it. This needs to be set in Tiled Preferences as follows:
So, finally, you only need the Map file (.tmx) and the Tileset image(s) in the same folder:
And you are ready to import into Visionaire.
You can easily import the tmx map into Visionaire using the relevant component:
Now if you run the game, you will see the player falling off the screen, but landing on the ground, meaning that the map was imported correctly and physics work!
You can also verify that the collission info was imported properly by using the console:
The next thing is to create an input manager, i.e. a script that will listen for any key input. More specifically we need to listen for any arrow keys pressed and the space bar. Especially for the arrow keys, a convenient way to go is for the script to return a 2d vector representing the current (x,y) direction based on the key pressed at any time. So for example we’d have:
(-1,0) – left only pressed
(0,1) – down only pressed
(1,-1) – right and up pressed at the same time
and so on!
Create a new Ilios script under the Visual Scripting tab. Make sure you link it under Global Behaviours!