Dungeon Game 2: Classier Edition

Step 1

In this lesson, we're going to learn how to make a class, and use that to make the rest of the dungeon work using our existing code.

If you have made a class with a constructor before it probably looked different from the method we are going to use.

Don't worry! Our class will be able to do all the same things! Even though the setup is different, invoking class methods and making new class objects will be the same.

Step 2
What is a class?

A class is a way to make multiple objects with the same properties. Besides that, we can give these objects methods, that is, functions that only members of this class can do. Let's imagine a class of students:

var Student = function(studentData){
this.name = studentData.name;
this.age = studentData.age;
this.favColor = studentData.favColor;

var someStudent = new Student({name: "Billy Bob", age: 12, favColor: "purple"})

This is what's called a constructor. It will make me a new object, with the three properties mentioned.

this is a keyword that means "the object I'm talking about".

Step 3
Making the room object into a class

We have already made an object for room1. It has different properties that are necessary to making the game work. We're going to make these into a class called DungeonRoom, so we can make as many rooms as we like!

Step 4

To make a DungeonRoom class, we need to think about what properties all rooms should have. Some of these properties will be different for each room -- like the location -- and some properties will always start out the same for every room. A class will let us assign these properties to new objects.

Step 5
Make a DungeonRoom class!

To make a class in ScriptCraft, we have to declare it using a function.

The way you can tell a class from a regular function is that it starts with a CAPITAL LETTER

Step 6
Assign the location properties to construct new DungeonRoom objects

this will be the new DungeonRoom that we are making. We tell the program to make a new object, and give it the properties entrance, exit, etc.

Step 7
Add the room properties that are always the same

For these properties, like sealed and monsterIDs, we don't need to look at the roomData, since it will be the same for every room.

Step 8
But what to do about the total number of monsters?

Now we have a puzzle. If we treat monstersTotal like one of properties above, we would just say that it's always 1, and you could not create a room with a different number of total monsters. If we make it look at our roomData to decide how many monsters there should be, we'll have to say how many every time we make a room. . .

Step 9
There's another way!

Once again, we will be saved by the || ("or") operator! This way, we can say that the total number of monsters should EITHER be whatever we tell you in roomData, or, if we don't say anything, just make it 1.

Step 10
Add another property to the constructor

Create another property in the DungeonRoom constructor called monsterType. It should be whatever monster type we specify in roomData OR make it entityType.zombie by default.

Don't forget to use the keyword this!

Step 11
Make an array of all your DungeonRooms

We will need a place to put all the rooms we are going to make. At the top with your other global variables, make an empty array called dungeonRooms.

Step 12
Push all your rooms into an array

.push() is an array method that means "put this thing in this array". We can add code in our class that automatically puts every room we make in the dungeonRooms array.

Step 13
Making functions that work for all the rooms

Next we need to figure out how to make functions that work for all the rooms, not just room1.

Take a look at your sealDoors() function, and notice all the places that it references room1.

Step 14
What is a class method?

A method is a function that only a class object can do. Think of it as an ability that that object has.

If we look back at our example student class, we can think about some things a student should be able to do:

var Student = function(studentData){
  this.name = studentData.name;
  this.age = studentData.age;
  this.favColor = studentData.favColor;

  this.sayHello = function(){
  this.doHomework = function(assignment){
    return assignment;

var someStudent = new Student({name: "Billy Bob", age: 12, favColor: "purple"})

Here, any student can say "Hello!" or do homework, because they have two methods to do so. Billy Bob, our example student, will be able to do both these things, now.

Notice how we use this.nameOfMyMethod = function(){ } to create a new class method.

Step 15
Make your first DungeonRoom method

Sealing doors sounds like the kind of thing a dungeon room should know how to do, so we will use this function as our first method.

Copy and paste the sealDoors function into the bottom of the DungeonRoom class, and change the word exports to this.

Step 16
Make it work for any room

We don't want all of the rooms just to seal room1, so we need to make sure they seal themselves, instead.

Find all the places that reference room1 and change them to this so that it always references whichever room we called the method on.

Step 17
Make unsealDoors() a DungeonRoom class method.

Using the same process you did for sealDoors(), make unsealDoors() a DungeonRoom class method, replacing room1 with the keyword this.

Step 18
Find all the coordinates for the second room

Go through the exit of your first room to find the second one. Just like with room1, place blocks in the center, both doors, and diagonally opposite corners so that we can find all the locations.

Jul 8 2018 6 14 pm
Step 19
Save all these locations in a new object

Make a new object called room2 and save all the coordinates for the different points in the room there. We will use this later as the roomData to make the new DungeonRoom class objects.

Step 20
Make your first DungeonRooms!

We use the keyword new to say we want a new instance of the DungeonRoom class. Instance is just a fancy way to say an individual member of the class that we have made.

Step 21
What happens when we make a room?

When we call newDungeon() with room1 and room2 in parentheses, we turn room1 and room2 into the roomData that the class uses to make the new rooms.

First, it looks in the roomData for a property called entrance, and assigns this to the entrance property of the new room.

Webp.net gifmaker %283%29

This might all seem redundant now, but it will save us lots of work in the end!

Step 22
Make a function to test out your new DungeonRoom class objects and methods!

We're going to use a for loop to go through each DungeonRoom in the dungeonRooms array, and try out their sealDoors() method.

Step 23
Test out your DungeonRoom class
Jul 8 2018 7 39 pm

Save, deploy, reload and call the testYourRooms() function on your server. It should seal the doors for both of the rooms.

Step 24
Make a method to reset the DungeonRooms

Make a new class method called reset().
It should:

  • set the started and finished properties back to false
  • set monstersIn back to 0
  • set monsterIDs back to an empty array
  • unseal the doors
Step 25
Reset all the rooms in stopDungeon()
Check Your Work
Step 26
Reset the dungeon

Save, deploy, reload and call /js stopDungeon()

It should take the bars off the doors and let you back out!

Step 27
Make a new DungeonRoom method called "contains"

We're going to change the inRoom() function to be a class method as well. First we'll make a method called contains() right after our reset() function.


Why change the name? Because room.inRoom() doesn't make sense. But it will do the same thing.

Step 28
Copy and paste your inRoom() function here

Copy and paste what's inside your inRoom() function into this new class method. Make sure you add entity as an input.

Step 29
Make it work for every room

Next, change everywhere you see room1 to this.

Step 30
Test your new "contains()" method

Change your testYourRooms() function to test the contains() method. We can take out the door sealing code for now.

Step 31
Dividing up the code to make the rest of the rooms work
Step 32
Add start and end methods

At the end of your DungeonRoom class, add two more methods, start() and end()

Step 33
Add the code that starts the room

Copy and paste the code from the checkPlayerPosition() function that starts the room.

Step 34
Add "this"

Change everywhere you see room1 this this.

We will also need to add this before sealDoors(), since it is now a class method

Step 35
Make it possible to spawn different monster types

We already make a property called monsterType for our dungeon rooms, so lets use it here. Change the variable zombie to monster, and make it spawn whatever entityType our room has for monsterType.

Step 36
Make the end method

Just like with start(), copy and paste the code from the checkPlayerPosition() function that ends the room into your new end() method, and change room1 to this.

Step 37
Get all the rooms working!

Delete everything currently inside your checkPlayerPosition() function. We're going to assign the player normally, and use another for loop to go through each of the rooms, and start and end them when the monsters are defeated.

Step 38
Make another method to count monster deaths

Make a new DungeonRoom method called countMonsters() and copy and paste all of the code from your onMonsterDeath() function into it.

Step 39
Make it work for all the rooms

Change room1 to this and entityType.zombie to this.monsterType.

We also need to supply the monster we will be talking about as an input in the function, since we won't know what entity we are dealing with until we use this function in the EntityDeath event.

Step 40
Use this method when an entity dies

Delete everything inside of your onMonsterDeath() function, which is called during the Entity Death event. We'll assign each entity that dies to a variable called monster, and use a for loop to go through each room and count the monsters.

Check Your Work
Step 41
Test out your rooms

You should now be able to start your dungeon and defeat enemies in both rooms to escape!

Step 42
Change the second room's monsters

In your room2 object that we use as data to build the second DungeonRoom, add a monsterType property, and set it to entityType.skeleton.

Then add a monstersTotal property and set it to 3.

Save, deploy, reload your server, start the game, and see the skeletons spawn in the next room.

Step 43

Next, we are going to add something to give the player when they complete the room. Add a new "loot" property to your DungeonRoom constructor.

We will set this to "null" by default, so that the room only gets loot if we specify an item.

Step 44
Drop an item if loot is not null

Although null is not the same thing as false, an if statement like this will only drop the loot item if it is not set to null.

Try opening up the console and testing what it gives you when you enter these statements:

null == false
null == true
null == null
!null == !false
!null == true
Step 45
Add a custom healing potion

Add this code to create a custom healing potion. If you want to try adding a different potion effect, check out the complete list of potion effects here

Step 46
Give your second room loot

Add a loot property to the data for the second room, and make your new healingPotion the loot.

Check Your Work
Step 47
Test if your second room drops a healing potion

Save, deploy, reload, start the dungeon, and fight your way through rooms 1 and 2. When you defeat the final monster, you should get a healing potion.

Step 48
Add doors to room 3

Because room 3 is at the back of the dungeon, you will need to turn to the right to make the second door. In this photo, we made the door 3 blocks wide and 3 blocks tall.

It should open into a giant drop!

Step 49
Add the coordinates for the third room

Create a new object for the data for room 3. You will need to save its coordinates the same way you did for rooms 1 and 2.

Once you have saved all the locations, make a new DungeonRoom.

We are also going to assign all of the rooms to variables, now, in case we need to change them individually. We'll use dr for "dungeon room"

Step 50
Overriding Class Methods

Right now, we have this awesome class that lets us make tons and tons of rooms, and all of them know how to start, end, and reset themselves, basically the same way.

Another cool thing we can do with classes is override these methods, which just means giving them different behavior from the rest of the class objects.

Let's look at an example with an imaginary student class:


Try this yourself in the console!

Step 51
Override the "start" method for Room 3

We don't want this new room to seal itself when we walk in, so we are going to override the start() method for this room. We will still check if it hasn't been started yet, and mark started as true once it does.

First, let's just and a broadcastMessage to test it.

Check Your Work
Step 52
Test your DungeonRoom start override

Save, deploy, reload, start the dungeon, fight through the first two rooms, and see if you get a the message when you enter Room 3

Step 53
Now, override the "end" method

Next, we are also going to override the end() method for room 3, since there are no monsters to defeat, and we want to give the player another item, this time in a chest.

Check Your Work
Step 54
Test to see if the chest appears in the center of room 3.
Step 55
Adding the grappling hook to the dungeon

To be able to add a custom item you have already made to the dungeon, this program will have to know what it is.

Go back to your grappling hook repo, and copy these lines. We don't need the ingredients or the recipe, since we are not going to craft it.


Paste that code near the top of this repo, just under the healing potion item meta info.

Step 56
Put the grappling hook in the chest

Now that we have defined grapplingHook in this repo, we can add it into the chest when the chest appears.

Check Your Work
Step 57
Check the chest to see if it has a grappling hook now

Save, deploy, reload, startDungeon() and defeat all the enemies in rooms 1 and 2 to get to your chest.

Step 58
Override the "reset" method

We need to change this room's reset() method as well.
Just like the other rooms, we need to

  • set the room's started property back to false
  • set the room's finished property back to false

But we don't need to unseal any doors or change the monster count. Instead we need to get rid of the chest so that it isn't there until the player gets there.

Use the drone to spawn an air block in the center of the room.

Step 59
Create the door on the other side of the chasm

Finally, we need to add a door on the other side of the giant drop. Made at least two of the bottom blocks chiseled stone, so that the player can use the grappling hook to get to them.

Step 60
Make the second half yourself!

You have seen how to find the coordinates for new rooms, choose what kind of monsters they will have, how many, and what item they will drop when the room is finished.

You have also learned how to override the methods you made for your room to make certain rooms work differently.

Your challenge now is to finish the other three rooms of the dungeon! Decide what kind of monsters and items they will have, and find the coordinates for all three of them.

Your imagination and Bukkit/ScriptCraft are your only limits!

Dungeon Game 2: Classier Edition Info


MVCode Clubs

Created By

Mandala2 slinkous


Temple Dungeon

Access Level


For Teachers and Schools

Teach coding to your students with MVCode Teach

MVCode offers an integrated product designed to teach coding to students.

Learn more about MVCode Teach