Now that we know how to make object types and how to give them density and layer, as well as different icons, we will cover some of the other things that we can set the defaults of. We will also cover event functions and how to call a few of the built-in functions from within those event functions.
To start, we will change a few of the default variables for some of our object types. We will continue from our last project
FirstProject.
Vylocity has many built in variables and functions that let developers easily make games. In order to make use of some of these systems, we need to tell the engine that we want to use them by setting certain variables under the object type we wish to change.
First off is
width and
height. We can change the width and height of any diob. By default the width and height are set to 32. The default size of all diobs in the game can be changed with a
World variable called tileSize, but we will keep it at 32x32 for these tutorials. Width and height only determine the physical size of a Diob. If they are changed to something like 48 and the icon assigned to the diob is 32x32, there will be a blank area. When the diob interacts with other diobs on the map, it will interact as if it is 48x48 and not 32x32. The icon is just a visual representation. In fact, you don't even have to give a diob an icon at all, it can just be an 'invisible' thing there. But we will make sure the icon and physical size match up here so we can see the size properly represented. In the
main code file, modify the
Mob code to look like the following.
Mob
atlasName = 'icons'
Player
iconName = 'player'
xCoord = 5
yCoord = 5
Monster
iconName = 'monster'
width = 64
height = 64
This will make our monsters 64x64. After making that change, go to the
icons icon file and add a new icon called
monster, but this time change the icon size to 64px by 64px. Modify the new monster icon to look how you want and then right-click on the old
monster icon and select
Delete to get rid of it. Build and run and the monsters should now be 64x64 in size. Both physically and visually.
Now let's add some offsets to both the position and the icon of the monsters. For the sake of having less code be shown below and to show that it can be done, we will define
Mob/Monster again, but with our new changes. Both instances of the type will be implemented on build. Everything does not have to be grouped together in the code. So after the
Mob chunk of code, add the following.
Mob
Monster
layer = 5
xCoordOffset = 5
yCoordOffset = 5
xIconOffset = -10
yIconOffset = -10
What this code will do is it will offset the monster on the x-axis by 5 pixels and the y-axis by 5 pixels, but then it will offset the icon that is attached to the monster on the x-axis by -10 pixels and the y-axis by -10 pixels. Build and run and run into a monster on the map in different ways to see how it has changed the monster.
Now that we have seen how the offsets work, go ahead and delete the chunk of code we just added.
There are many other variables we can set, but for this tutorial, we will end, variable-wise, on the variable
iconState. Icon states let you change how something looks, usually for a short time, without changing the icon itself. An example of what you would use an icon state for is something like an 'attack' animation or walking or even changing direction for a
Movable. But you can use it for anything you wish.
We will start by creating icon states in the icon editor first. Go to the
icons icon file, right-click on the
player icon and select
New Icon State. Enter
some_state as the name. Icon states must have a name because a blank name is basically the icon itself. After hitting
Create the icon should now have a + off to the left in the icon list. Clicking the + will display all of the icon states for that icon under it. As you can see, the icon state is automatically given the same icon as the icon itself. This is because icon states are mainly just modifications to the main icon, so you'll most likely want to work off of it to make changes. Go ahead and edit the
some_state icon state so it is visually different than the
player icon.
Head back over to the
main code file and type
iconState = 'some_state' under the
Mob/Player type (with one tab before for indentation). Build and run and your player should now look like the new icon state you created.
While we are setting the default icon state of the player, icon states are designed to be changed during runtime, in some cases many times, so later in this tutorial we will learn how to manually change the icon state with code within an event function.
Now that you have seen how to change the default icon state if you want, go ahead and delete the line we just added that set it. The reason for this is because if we manually change the icon state, the built-in icon state handler will not work. When we manually change the icon state of something, we basically tell the engine to stop automatically changing the icon state, but if we return the icon state to a blank string, the automatic system will kick back in. When using the default movement, the Vylocity engine will automatically change the icon state of the moving diob, like mentioned above. In order to get this working, we will need to create some new icon states for our player icon.
Head over to the
icons icon and add the following icon states to the
player icon:
north,
south,
east,
west,
northeast,
northwest,
southeast,
southwest. Give them icons that help you tell what direction the player is facing. The Vylocity engine will use these icon states when the player is facing the respective direction in the game and not moving. We will handle the icon states for moving in a bit. Once you have the icons the way you want, build and run the game. When you stop moving, your icon state should be the icon state of the direction you are left facing.
Now for movement. Add the following icon states to the
player icon:
move_north,
move_south,
move_east,
move_west,
move_northeast,
move_northwest,
move_southeast,
move_southwest. Give them proper icons then build and run. You should now see the icon change when moving, with the icon representing the proper direction.
That will do it for default object type variables for this tutorial.
We're off to event functions and calling code inside of them, including built-in functions. Event functions are basically functions that are called by the engine when certain things happen in the game. Adding code to an event function lets you make changes to your game during runtime. Most of your code will execute from an event function. We will go over some of the basic and most common ones.
When every diob is created, an event function called
onNew is called. We can use this event to tell the game what to do when certain diobs are created. We are going to use the
onNew event function for our player mob to change its location on the map after it has been created. In the
main code file, change your
Mob chunk of code to appear like below.
Mob
atlasName = 'icons'
Player
iconName = 'player'
xCoord = 5
yCoord = 5
onNew()
this.setLoc(15, 15)
Monster
iconName = 'monster'
width = 64
height = 64
You can see under
Mob/Player that a new thing is added, this is the
onNew event function declaration. Tabbed under it is a single line of code which is called when
onNew is called by the engine, which is every time a diob of type
Mob/Player is created in the world in this case.
So what does the line
this.setLoc(15, 15) mean? Well it tells the engine to call the function
setLoc which belongs to the object
this, which sets the location of the diob. The
this in any function is a reference to the object that is calling the function. In an event function,
this will always be the diob that the event function belongs to, so our
Mob/Player mob in this case. The two 15s are passed into the function, telling the function to set the
xCoord and
yCoord of our player to 15 and 15 respectively.
Build and run and you will now see that your player mob spawns more towards the middle of the map. Technically, when the player is created it appears at 5,5 but then we use our
onNew event function to change it to 15,15.
The amount of things you can do inside of an event function are infinite. But below are a few code examples of functions you can call to set some of the variables we have learned about so far. You can also just set the variable directly, which is the best option when you are only changing one variable.
this.layer = 20 would set the layer of the diob to 20.
this.setSize(64, 96) or
this.width = 64 and
this.height = 96 would set the width of the diob to 64 and height of the diob to 96.
this.setIcon('icons', 'some_icon') or
this.atlasName = 'icons' and
this.iconName = 'some_icon' would change the diob's icon to the icon that exists in the 'icons' file and is named 'some_icon'.
this.setIconOffsets(10, 20) or
this.xIconOffset = 10 and
this.yIconOffset = 20 would set the diob's icon x-offset to 10 and y-offset to 20.
this.setCoordOffsets(10, 20) or
this.xCoordOffset = 10 and
this.yCoordOffset = 20 would set the actual diob's x-axis offset to 10 and y-axis offset to 20.
this.setIconState('some_state') or
this.iconState = 'some_state' would set the diob's icon state to 'some_state'.
These are nice functions to be able to use, but sometimes you want to get the values so you can alter them or display them, or whatever you want. Each of the above functions also have a 'get' version and most variables can be directly accessed to get the value. For example
this.getSize() would return the diob's width and height and
this.layer would return the diob's layer. The other functions and variables work the same way, just change the 'set' to 'get' and remove the parameters between the parenthesis, or just simply access the single variable you want.
Let's change the code in our player's
onNew event function to grab some variables. Change your
Mob code to look like the code below.
Mob
atlasName = 'icons'
Player
iconName = 'player'
xCoord = 5
yCoord = 5
onNew()
this.setLoc(this.getCoords().x + 5, this.getCoords().y + 5)
Monster
iconName = 'monster'
width = 64
height = 64
So what is going on here is we are calling
this.getCoords which returns an object holding two variables 'x' and 'y' which lets us know what the diob's x and y coords are. We then add 5 to both the x and y values and pass them into the
setLoc function. So when we build and run this, our player should now appear at 10,10 on the map since our default location is 5,5 and we add 5 to each position.
So what exactly is returned by
this.getCoords and why can we do
.x and
.y after accessing them? Well, the function returns a basic object like we learned about in the previous tutorial, which holds the variables for us so we can access them.
{'x': 5, 'y': 5}
The object returned has two variables called
x and
y where the first variable is equal to the number 5 and the second is equal to the number 5 (because our player's xCoord and yCoord are 5). To access the first variable, we would use the code
object.x where
object is a variable holding a reference to the above object. So how do we create that reference? Well, any variable can hold the object, but for the sake of this tutorial, we will use a local variable.
Local variables are variables that are defined inside a function and only the code inside of that function has access to them, known as a scope. So a line of code creating such a variable that holds our above object would look like this:
var object = {'x': 5, 'y': 5}
So here is some example code of how this might work inside the
onNew event function. Do not include this in your project, just observe how it works. Also notice that you can put
Mob/Player on a single line if you want to only change it.
Mob/Player
onNew()
var object = {'varName1': 34, 'varName2': 67}
this.setLoc(object.varName1, object.varName2)
What the above code would do is create a local variable that holds a new object. It then calls the function to set the mob's location and uses the values in the
object variable. So in this case, the mob would be moved to the coordinate 34,67.
So now let's make some changes to our actual function to make use of local variables and our understanding of basic objects. Change your
Mob chunk of code in the
main code file to look like the code below.
Mob
atlasName = 'icons'
Player
iconName = 'player'
xCoord = 5
yCoord = 5
onNew()
var coords = this.getCoords()
this.setLoc(coords.x + 5, coords.y + 5)
Monster
iconName = 'monster'
width = 64
height = 64
What we do here is create a new local variable called
coords which holds the object that the
getCoords function returns, which would look like {'x': 5, 'y': 5}, then we access the x and y variables of the object during our
setLoc call.
Calling getCoords isn't the most efficient method of getting the x and y coordinates, especially if we only want one of them. Creating an object (which is what getCoords does) is much more expensive when it comes to processing than just accessing variables that already exist, but the above methods were good examples of how function code works. A good programming tip would be to limit the amount of processing you do as much as possible. The less code running, the better. But obviously you need to get your task completed, so make sure you do that.
So before we move on, we will change our code to use the most efficient method, which also demonstrates accessing variables directly. Change the
Mob chunk of code which we just changed to look like the code below.
Mob
atlasName = 'icons'
Player
iconName = 'player'
xCoord = 5
yCoord = 5
onNew()
this.setLoc(this.xCoord + 5, this.yCoord + 5)
Monster
iconName = 'monster'
width = 64
height = 64
Directly accessing variables is almost always the best and most efficient way to read values.
So now that we have a feel of functions, local variables, objects, some built-in functions we can call, and how event functions work. What other event functions could we use? Here's a list of the basic event functions you could use.
Diob: onBumped, onNew, onDel
Tile: onEnter, onEntered, onExited
Movable: onBump, onMove, onMoved, onCrossed, onUncrossed
To reinforce how inherit works, all diobs have the above
Diob event functions, then all tiles have all the
Diob event functions and the
Tile functions, and all movables have all the
Diob event functions and the
Movable event functions, but none of the
Tile event functions.
So how do some of these work? In order to execute code when a diob has been bumped into by another diob (basically when a dense movable is prevented from moving because of a dense diob) you would use the
onBumped event function. The
onBump event function would also be called during this process, but only for the movable that bumped into the dense diob.
Let's put an
onBumped event into our project. Let's have it set the player's location to 1,1 on the map if they run into an
Diob/Solid diob. At the bottom of your
main code file, make your
Diob chunk of code resemble what is below.
Diob
atlasName = 'icons'
Solid
iconName = 'solid'
density = true
onBumped(pBumper)
pBumper.setLoc(1, 1)
NotSolid
iconName = 'not_solid'
plane = 1
layer = 20
The
onBumped event function has an extra part to it. When it is called, it passes the
Movable that bumped into the diob into it as the first argument of the function. You can name your arguments anything you want, but in this case we call it
pBumper. This variable holds the reference to the movable that bumped this obj. We then call
setLoc on it to make the movable, our player mob in our case, teleport to the 1,1 location on the map. Build and run and run into a diob on the map that is of the type
Diob/Solid to see our event in action.
Note: The standard in VyScript for naming arguments is to start it with a
p to show that it was passed into the function call as a parameter. This is entirely optional and arguments can be given any name you want
Let's briefly go over the other mentioned event functions. The event function
tile.onEnter is called when a movable tries to enter a tile on the map. If you wish, you can stop the movable from entering by returning false inside of it. We'll discuss
return more in the functions tutorial. Moving on,
tile.onEntered is called when a movable succeeds in entering the tile, and
tile.onExited is called when the movable succeeds in exiting the tile.
Like mentioned before, the event function
diob.onNew is called when a diob is created. Then
diob.onDel is called when a diob is deleted,
movable.onMove is called when a movable is attempting to move,
movable.onMoved is called when a movable has successfully moved,
movable.onCrossed is called when a movable's position on the map overlaps another diob's position, and
movable.onUncrossed is called when a movable's position on the map no longer overlays another diob's position.
We wont go over them all, but let's add one of the events to our grass tile to make it change to a dirt icon when our player enters it and the opposite for our dirt tile. In your
main code file, make the
Tile chunk of code look like the code below.
Tile
atlasName = 'icons'
iconName = 'tile'
Grass
iconName = 'grass'
onEntered()
this.setIcon('icons', 'dirt')
Dirt
iconName = 'dirt'
onEntered()
this.setIcon('icons', 'grass')
Build and run to see our new events in action.
So now we have seen how to work with variables and event functions. In the next tutorial we will go over how to create our own functions and go into a little more detail on some of what can be done inside both event functions and our custom functions.
If you followed everything in this tutorial, the source of your project should look something like this.
https://vylocity.com/ide/Vylocity/FirstProject2/
References