First Project - Lesson 6: Inheritances and Static Objects
We have learned quite a bit about Object types and how to define variables and functions under them, as well as how to create child types (Mob/Player for example). In this tutorial we will focus a bit more on how inheritance works for Object types and how we can manipulate it to fit our needs. We will also introduce a few new static objects that the engine has built-in and go further into detail about some we have already used. Some built-in function variables (behind the scenes variables that every function has that can be used to access information about the function call) will also be introduced.

We will continue from the project we created in the previous tutorials. If you are just now jumping in, go to the previous tutorial and create a project to match the project at the bottom of the page.

Open up our previous FirstProject project in the IDE and open the main code file. If it has been awhile since completing the last tutorial, be sure to look over the code to get yourself familiarized with it.

As we learned in a previous tutorial, Object types have an inheritance system which allows child types to get variables and functions defined under their parent types. If you have any experience in programming, a type is much like a class in other languages.

The lowest level of inheritances (the type that all other types inherit from) is the Object type. The Object type has very few properties and is designed to hold data and track information (much like just a basic object, but with a few extra properties and the ability to use the type system). It does not have the necessary properties needed to be displayed, so the Diob type exists for this reason. Anything that is seen on the screen will have to inherit from Diob. We were shown a list of built-in types that inherit from Diob in a previous tutorial, but we will list them again as a refresher.

All of the above types will inherit from Diob, but we can also create our own. We learned about Mob and Tile already. Movable is Mob's parent type, which gives it the ability to move around on the map. The rest of the types will be explained more in future tutorials.

Custom inheritances allow us to give our custom type a parent without adding that parent to the our type string. This can simplify our type tree and use smaller type strings, among other things. The best way to understand this more is to just get it into our project! Inside of the main code file, we are going to be making some alterations to our Mob/Player and Mob/Monster type definition codes. Change that code to look like the following.

Note: You can back tab large sections of code by selecting it and then holding shift while pressing tab.

Mob atlasName = 'icons' Player : inherit [Mob] iconName = 'player' xCoord = 5 yCoord = 5 onMouseEnter() this.scale = 2 this.alpha = 0.5 this.angle = 0.5 onMouseExit() this.scale = 1 this.alpha = 1 this.angle = 0 onMouseMove(pClient, pX, pY) this.setAnchor(pX / this.width, pY / this.height) onMouseClick() this.setLoc(1, 1) Monster : inherit [Mob] iconName = 'monster' width = 64 height = 64 onNew() this.dir = 'east' Event.addTicker(this, {'resetAt': 500, 'resetEnd': true}) onTick(pT) if (this.xCoord <= 3) this.dir = 'east' else if (this.xCoord >= 23) this.dir = 'west' this.stepDir(this.dir, 2) if (!(pT % 150)) this.setTransition({'scale': 2}, -1, 500) this.setTransition({'scale': 1}, -1, 500, true) onTickerAdd() this.color = 'rgb(200, 0, 0)' onTickerRemove() this.color = '' Basically we back tabbed all our player and monster codes and added : inherit [Mob] to both types. It does not seem like we did much, but we turned our Mob/Player type into just Player and our Mob/Monster type into just Monster, which are shorter. One could also argue that the code looks cleaner and more compact. Once a project gets larger and type trees get longer and more complex, things like this come in handy. These are only some of the benefits of this inheritance system.

Before we build and run, we need to make sure we update our World/mainMob to point to our new player type. Find that code and update it to look like below.

World mainMob = 'Player' This next step is going to be a new learning experience about the IDE and map editor. Our map contains our old types, so after we build and open the map, it is going to yell at us that Mob/Monster does not exist. We need to fix this issue. When you open the map map file after building, you should get an alert. Simply replace Mob/Monster with Monster and hit OK. Build, open map, replace the types, then build again and run the game and everything should work as normal.

The inherit system allows more than one type to be inherited at the same time (the order of them matters). So let's learn a bit about that before moving on.

We will create a new Object type that will hold some information for us that we can give to whatever other type we want with the inherit system. Above our Mob type (on a blank line and not inside any other code) add the following code.

Prop var myVar1 = 1 var myVar2 = 2 Prop is the name of our new custom Object type (it is not built in) and it has two variables.

We can now give these two variables to our Player type (or any other type we want). Go to our Player type definition which currently looks like Player : inherit [Mob] and make it look like below. Also add the onNew event function shown to the type.

Player : inherit [Mob, Prop] onNew() alert(this.myVar2) Now our Player will inherit from Mob and then Prop. You can add as many more types as you want. They will be inherited in order from left to right.

Build and run and we should now get a 2 alert at the start of the game, since our player's myVar2 variable is being outputted and it is equal to 2.

Moving on. So we have our normal Mob type definition without atlasName defined under it and our Player and Monster types which both inherit from Mob (giving them the atlasName). The next thing we will learn about is the override operation, but before we do, we need to set things up and see why we might want to use it.

Under the Mob type, add a new onNew event function like we had for our old Mob/Player type in previous tutorials. Change the Mob type code to look like below.

Mob atlasName = 'icons' onNew() this.setLoc(10, 10) This code should be familiar and not need explanation again. Build and run the project. All of our monsters, as well as us, should now all be stacked together at the 10,10 coordinates (the monsters will move together from the location immediately).

We probably do not want our monsters to execute this code, so we need to override it. Note: The obvious solution here is to add the onNew event to Player so that Monster never gets it, but we are learning inheritance manipulation here!

So let's override the onNew event function for Monster. Simply add override to the top of our onNew event function found under our Monster type like shown below.

Monster : inherit [Mob] onNew() override this.dir = 'east' Event.addTicker(this, {'resetAt': 500, 'resetEnd': true}) Build and run the game and our monsters should now no longer be at the 10,10 coordinates. Our override operation has blocked any inherited onNew code from being executed.

A couple things to take note of when using override. You must put override at the very top of the function as the very first line, every time. Also, override will not prevent child code from being executed. For example, if a new type was added that inherited from Monster, the Monster onNew that starts with the override would execute first, then the child's onNew would call.

Before we move on with inheritances, we need to learn about a new global function that the engine that lets us create brand new diobs during runtime. But before we learn that, lets add a new type definition for us to create (you can create any type during runtime, but this will let us use something we have not used yet). Above the new Prop type (the same was it was added itself) add the type below, along with it's properties.

Movable atlasName = 'icons' iconName = 'monster' Mob inherits from Movable, so it will not inherit anything we have already created for our Mob, Player, and Monster types. But because Mob does inherit Movable, anything we add to Movable will be given to our Mob types. This means our atlasName = 'icons' defined under Mob is kind of useless now, but we wont worry about it. We gave the new type the monster icon just for simplicity.

Now that we have a new type with properties that we can create, lets learn how to do that. Find our Tile type definition code and put the following event function code found below under it (make sure the code is indented under Tile and not the Tile/Dirt or Tile/Grass types).

Tile onMouseDown() var d = new Diob('Movable') d.setLoc(this) A couple new things here. The new Diob('Movable') code allows us to create a new diob with the specified type during runtime. This is a very important feature and will be use a lot while making your game, so it is good to know (if you wanted to create a different type, you would simply replace 'Movable' with the type). Then of course var d holds a reference to that new diob so that we can work with it, which we do in the next line. The setLoc call should be familiar by now, but this time instead of passing in coordinates, we pass in this alone (which points to our tile). We are able to do this because tiles are locs. Each loc (location or coordinate) has a tile, so they are related.

If you build and run the game, you can click on tiles on the map and place new Movable diobs.

Note: These new diobs look like our monsters, but they are different types, so they will not move or use a ticker like our monsters do.

Before we proceed, let's clean up a bit. We will be using alerts to display some information, show inheritance orders, and other things. So we should remove our current alert located under our player's onNew event function. Find that code and remove the two lines associated with it. It should look like the code below.

onNew() alert(this.myVar2) With that gone, we can continue. We will look into some of the built-in function variables that we have access to. The first is the arguments variable. Any function can access this variable and it will provide useful information about the function call, including an array of the arguments being used. Lets add a child type to our Movable type, give it an onNew event function, and loop the arguments variable to output the value of each argument. Change your Movable type definition code to look like the code below.

Movable atlasName = 'icons' iconName = 'monster' Test onNew() foreach (var v in arguments) alert(v) If we ran this code right now, we would not get any alerts because we do not currently have any arguments. With that said, any function can be called with any amount of arguments, even if the function code does not give them names or define them. So that makes it easier for us to add something to alert.

Find our new Diob('Movable') code under the Tile onMouseDown event function and change it to be new Diob('Movable/Test', 1, 2) so that the whole block of code looks like below.

Tile onMouseDown() var d = new Diob('Movable/Test', 1, 2) d.setLoc(this) Every parameter passed into new Diob after the type string will become arguments inside of that new diob's onNew event function. So now when we build and run the project and click a tile, we should get two alerts which display 1 and then 2.

Note: You may notice that once the alert appears, everything behind it freezes. This is good lesson to learn. You should not use alert in your game unless you are using it for quick testing.

The arguments variable holds other information other than just a list of the arguments, but we wont go into those details in this tutorial.

Up next is the retVal function variable. This variable holds the return value from a parent's function call.

In order to see this in action, we will add an onNew event function to Movable that returns a value and then output that value under our Movable/Test's onNew event function. Change the Movable type code to look like the code below.

Movable atlasName = 'icons' iconName = 'monster' onNew() return 12 Test onNew() alert(retVal) Build and run the code and when you click on a tile, an alert with 12 in it should appear. This code allows us to pass a value from a parent function call to the child function calls, all the way down if desired.

One last thing to cover related to inheriting, which also overlaps with static objects that we will be covering more shortly, is the ability to go back and call parent functions (or any function really) when using the override system. This gives us the ability to change the order of our function calls if we want to.

In order to do this, we will need to be introduced to a static object function called Type.callFunction. This function allows us to call any function that belongs to any type, and do so with different arguments and even a completely different owner (the this inside the function). Having control over the this of the function is important, because if we call a function that belongs to Mob/A by a diob that has the type Tile/A we want the this of that function call to be the diob that called the function and not a diob that has that function defined.

To see this in action, we will have the Movable/Test type onNew use override and then call the parent onNew at the end, essentially reversing the order that they are called in. Change the Movable type code to look like below.

Movable atlasName = 'icons' iconName = 'monster' onNew() foreach (var v in arguments) alert(v) Test onNew() override alert(3) Type.callFunction(this.parentType, 'onNew', this, arguments) Normally when running this code (without an override and Type.callFunction call) we would get three alerts in order from 1 to 3, but with our override we prevent Movable's onNew from being called first and get a 3 then 1 and 2. The Type.callFunction function has four parameters, which we use above. The first is a string with the Object type that owns the function we want to call, the second is a string with the name of the function, the third is a reference to what object should be the owner of the call (the this inside of it), and the fourth is an array of arguments to pass into the function. For the first parameter we use this.parentType which is a new variable for us, but it holds a string that is the parent's type which is Movable in this case. For the second parameter we use the string 'onNew' because that is the name of our function, then we pass in our this and arguments so that they are the same as our current function.

Go ahead and build and run to see the code in action.

That basically does it for the inheritance system. We will now go over some of the built-in static objects and some of their variables and functions. We just used the Type static object above, so we will continue to explore it some more.

The Type static object holds important information relating to our project's Object type system, along with useful functions for being able to manipulate types or gather information on them during runtime. Two of the most important functions the static object has is probably Type.callFunction and Type.getVariable. We already saw the first, so we'll try out the second before moving on to the next static object. If you want to see more properties that the Type static objects has, you can visit the documentation page.

To make use of Type.getVariable we will make some changes to our code. What Type.getVariable does is it allows us to get the default value of a variable belonging to the specified type, instead of the current value of a variable belonging to an active Object.

In our code, under the Tile type code that we created awhile back in a previous tutorial, we will give the Tile/Grass and Tile/Dirt types two more event functions which will return their icons back to normal after we exit them. Find that code and make it something like the code below.

Tile Grass iconName = 'grass' onEntered() this.setIcon('icons', 'dirt') onExited() this.iconName = Type.getVariable(this.type, 'iconName') Dirt iconName = 'dirt' onEntered() this.setIcon('icons', 'grass') onExited() this.iconName = Type.getVariable(this.type, 'iconName') Our code returns each Tile's iconName back to the default of 'grass' or 'dirt' after the thing entering it leaves. We also use a new variable at this.type which is just a string holding the type of our Object. This Type.getVariable function is useful for returning values back to normal or default like this.

Build and run and see how each tile you enter has its icon change as you enter and then return back to normal as you leave.

Another useful and very commonly used static object is the Map static object. It is a static object you will be using quite a bit to work with things on the map, which is a large part of a game. There are way too many properties to cover here, but we will go over a few commonly used ones.

The first function we will learn about is the Map.getRange function. This function will give us an array of all non-tile diobs on the map around the diob we pass into it, with a few variations we can enable. The first parameter of the function is where to start to look for diobs, the second is the number of positional units to the sides of that diob to look, the third is the number of positional units above and below the diob to look, and the fourth is if the diob itself should be included in the returned array.

We will use this function inside of a new event function called onRelocated (which is called every time a diob changes position) that we will put under the Movable/Test type. In order to test this properly, we need to clean up some of our code under the Movable type and get rid of the alerts, so make that code look like the code below.

Movable atlasName = 'icons' iconName = 'monster' Test onRelocated() foreach (var d in Map.getRange(this, 50, 50, true)) d.scale = 0.5 At this point, the code should be somewhat familiar. Basically when a Movable/Test Diob moves in any way (including when it is first placed down on the map or changes maps), it will grab all diobs that are up to 50 positional units away from our Movable/Test Diob (minus the diob itself) that we placed down and loop them, setting each one to have have a scale of 0.5.

Build and run and click some tiles to put Movable/Test diobs on the map and notice when you put one down close to another, it shrinks the ones around it.

You may have noticed that this code can also shrink our player or the monsters, which might not be what we want. We could use an if statement to weed out those things, but there is also a built-in Map function to handle it for us called Map.getRangeByType. The function is the same as Map.getRange but it has two new parameters after the first which can be set to only grab diobs with a certain type or parent type. We saw a version of this when we used World.getDiobs in a previous tutorial.

So lets change our code to use that function. Make the Movable/Test onRelocated function look like the code below.

Movable Test onRelocated() foreach (var d in Map.getRangeByType(this, 'Movable', true, 50, 50, true)) d.scale = 0.5 Now our code should only give is diobs that have the Movable type or has a parent type that starts with Movable. Build and run to test it out.

There are quite a few more functions belonging to the Map static object which are related to these two functions, but we wont be going over them. If you are interested in some of them, you can check out the documentation page for the Map static object.

One last Map function that will probably be commonly used is the Map.getDist function, which returns the positional unit distance between two diobs on the map.

Find our Client type code and change the onMouseDown event function code to be like the code below.

Client onMouseDown(pD) if (pD) alert(Map.getDist(this.mob, pD)) Each time you press the mouse down, it should alert with the positional unit distance from the center of your player mob to center of the diob clicked on. The this.mob variable is a Client variable that references the client's player mob.

Build and run and see how the number increases the further away you click from your player mob (the center of the screen).

The final static object we will be covering in this tutorial is the Util static object, which is basically just a static object containing properties that could not find a home somewhere else. There are quite a few things and we will only be covering a couple, so if you want to learn more about the properties the Util static object has, go check out the documentation page for it.

First up is the Util.toRadians function. There is also a Util.toDegrees but because we need radians for angle, we will use degrees that are converted to radians for simplified angle setting. Find the this.angle = 0.5 code under our Player type in the onMouseEnter event function and change it to this.angle = Util.toRadians(35) so that the event function looks something like the code below.

Player : inherit [Mob, Prop] onMouseEnter() this.scale = 2 this.alpha = 0.5 this.angle = Util.toRadians(35) Now we can use degrees (35) as an angle. You can build and run to see the code still works properly with the new function call.

One last Util function that might be useful is the Util.pick function. We can either pass an array into it or a bunch of parameters and it will return only one value, basically picking the value for us.

To test, we will replace the Client's onMouseDown event function again. Make it look like the code below.

Client onMouseDown() alert(Util.pick(1, 2, 3, 4, 5)) Build and run and each time you click you should get an alert that displays 1 to 5 randomly.

We have learned a bit about the Event, World, Map, Type, and Util static objects. We could probably spend days going over all the possible static objects and all of their properties, but it is good to understand that they all exist and go over a few of the commonly used ones. There are quite a few more static objects that we did not go over. Here is a list some of the other available static objects.

So, we have now learned how to use the inheritance system, a bit about some static objects, and also about some built-in function variables.

If you followed everything in this tutorial, the source of your project should look something like this.