Sidescrolling Platformer ~Part 7~ Keys and Doors

First, I’d like to apologize for my brief hiatus over the past month — I upgraded to a new computer, and Flash was out of commission for a while. But assuming you haven’t abandoned this site yet, here’s the next part of the side scrolling series.

Last tutorial pretty much finished up the bare-bone mechanics and visuals of a basic platformer. So I figured with this tutorial we’d start adding various extra features to spice up the game. This time, we’re adding a collectible key to the level, as well as a locked door which it will open. This door might be the end of one of your levels, which in turn might load a new level afterwards (although we aren’t coding multiple levels in this tutorial — just the door and key which will allow for this in the future).

Make sure you’ve read up through Part 6 of the series.

Creating the Objects

We need to create:

  • A Locked Door
  • A Key

The Door

Double-click on the main background object to edit it, then create a new layer on top of the Visuals layer from last tutorial. You can just name it “Other“. This layer isn’t really necessary, but for the sake of organization, this is where we will put any game objects that don’t collide with player and block him (like a wall), but also aren’t only for a visual purpose. We will individually add code for each object in this layer, instead of using a container-object.

Now, I just chose the uppermost platform of my level to be the “end”, which is where I am placing my door. So I drew my door in the “Other Layer”, right on top of the visuals of that platform. I used a combination of the Rectangle Tool, the Circle Tool, and the Transform Tool to draw the following door:

Convert the door into a Movie Clip, which I named LockedDoor, and give it the instance name “lockedDoor. That’s all set now, except it would be nice to have a separate image of an open door, which we can switch to after the player unlocks it with the key. So double-click the door to edit it. In order to hold multiple images within the same object, we need to add another keyframe to its timeline.

You can do this by using the menu: Insert –> Timeline –> Keyframe.

You can click on Frame 2 in the timeline to make sure you switched to it, and then edit the door to show that it is open. I just filled it in with black on the inside of the door frame.

So, the door is finally done now, right? Wrong.

By default, Flash plays each frame in a Movie Clip object as an animation. If we don’t stop it using code, these two frames will switch back and forth 30 times per second, no matter if the key is collected.

Luckily, the solution is simple! We just use the built-in stop() function. There are two ways we can do this. First, we could go into our main code file on Frame 1 of the main timeline, and add in back.lockedDoor.stop(); at the beginning of the program. But if we end up adding a lot of different objects, that can get a bit complicated. So the easy way out is to add code directly onto the timeline of the door object itself.  Yes, that is within the rules (although it’s considered poor practice to add code that isn’t related to the animation).

Click on frame 1 of the LockedDoor, and go to the Actions Panel. It should be blank.

Add to line 1:

stop();

…that’s it. Done!

The Key

OK, time for the key… this one’s simple.

Go back to the “Other” layer in your background object, and find a good location for the key. Then draw any kind of key you like at that spot. Finally, convert it into a Movie Clip symbol (which I named DoorKey), and give it the instance name: “doorKey“.

We’re all set now to start coding! After adding in the door and the key, my background looks like this:

Programming the Door and Key

Here’s what we want to happen:

  • If the player hasn’t collected the key yet, keep checking if he is colliding with it
  • But don’t check for collisions between the door and the player if he hasn’t collected the key yet
  • When the player does collect the key, hide it from view
  • After the player collects the key, if the player collides with the door, unlock the door by changing its frame

By breaking it into steps, we have really simplified what we need to do.

First, let’s create two Boolean variables. Add these right underneath the rest of the variable declarations.

var keyCollected:Boolean = false;
var doorOpen:Boolean = false;

These will keep track of the logic that is going on behind the scenes in the game.

Now, anywhere in the main game loop, start by adding the code that handles the key:

if(keyCollected == false){ // if we still haven't collected the key
if(player.hitTestObject(back.doorKey)){ // and if the player collides with the key
back.doorKey.visible = false; // hide the key from view
keyCollected = true; // set our Boolean to true
}
}

I realize I just combined a few of the steps we outlined earlier, but hopefully it is easy enough to understand. As long as our keyCollected variable is false, we know that the player is still looking for the key, so we run a hitTestObject between the player and the key. If that hitTest is successful, the first thing we do if modify the “visible” property of a key. Every Movie Clip has a “visible” property, which can be used to show or hide an object. Setting it to false doesn’t completely remove the key from the stage — it makes the key invisible. If we wanted to show the key again, we would just set the property to true, and the key would reappear in the same spot.

Finally, we set the keyCollected Boolean to true.

Next, we need to handle the door. Here is the last chunk of code. Add this directly beneath the last code snippet.

if(doorOpen == false){ // if the door hasn't been opened yet
     if(keyCollected == true){ // and if the player has already collected the key
          if(player.hitTestObject(back.lockedDoor)){ // check if the door and the player are touching
               // if all of these conditions are met...
               back.lockedDoor.gotoAndStop(2); // ...switch the door's image to its 2nd frame
               doorOpen = true; // ...set the variable to true
          }
     }
}

This shouldn’t be too had to understand. If the door is still locked, but the player has already collected the key, we keep checking whether the player and the door are colliding. When they do finally collide, we change the door’s image using the built-in gotoAndStop(function on the lockedDoor. This function switches whatever frame number you pass into the function. back.lockedDoor.gotoAndStop(1) wouldn’t do anything, because the door started on frame 1, but back.lockedDoor.gotoAndStop(2) does just what we need to make the door open up.

The last thing we do is set the doorOpen variable to true. This prevents this conditional from running more than once, and we can also use this to make certain things happen after the door is open.

That’s as far as we’re going in this part — try out the demo below to see how the door works:

And here’s the source file.

Enjoy! Sorry again for the lack of recent tutorials — I’ll try to get another one up within the next week to catch up on lost time! :-)

EDIT: Part 8 has been released! Click here to learn how to connect multiple levels with the door from this tutorial.

18 comments on “Sidescrolling Platformer ~Part 7~ Keys and Doors

  1. RenZ says:

    Thanks for this tutorial Ben :). How if the player want’s to go to next stage or to enter the room?? Hope that would we be the next tutorial. Thanks.

  2. kvakk0 says:

    ABOUT TIME!! I WAS GETTING TIR…
    umm.. ah, wrong tone.. :D

    I got a request, could you make an tutorial on class-files, and how to use your own classes in games?

    -newbeginner game-maker Grambo

    • Ben Reynolds says:

      Thanks for the request — I definitely plan on making a bunch of tutorials on building games using multiple class files. I was thinking of writing them after I finish few other tutorials, but since you are the 2nd person in 2 days who has asked about these, I might bump the class-based tutorials up a bit in the schedule.

      • kvakk0 says:

        And thank you for responding to my request, I working on something this Easter, if it works, you will see it on my website.

        your tutorials have helped my a bit (ok, a bit more than a bit), to make games.
        I hope your future tutorials will be more helpful.

        http://www.grambogames.host22.com/

  3. ashwin says:

    Great tutorial Ben.

  4. Jarvy.2 says:

    Hey, I have a quick question, I’m using your setup *Mostly* and I wanted to have “keys” appear in a random place, as in, I want the key to spawn in one of three places, and I want it to keep track of how many keys are collected, would there be any easy way to do this?

    • Ben Reynolds says:

      Sure. To keep track of how many keys have been collected, create an integer variable (maybe called “keysCollected”) and increase it by one each time you collect a key. To see if a certain number of keys have been collected, you can just say: “if(keysCollected == 3)” or “if(keysCollected > 2)”, etc.

      If you want the key to spawn in one of three random places, first choose the coordinates of each place. For simplicity, I’m going to say the 3 places are at the coordinates: (100,100) and (200,200) and (300,300).

      Now when your game starts, add the following code:

      var randomNumberFromOneToThree:int = Math.ceil( Math.rand() * 3));

      if(randomNumberFromOneToThree == 1) {
      back.doorKey.x = 100;
      back.doorKey.y = 100;

      } else if(randomNumberFromOneToThree == 2) {
      back.doorKey.x = 200;
      back.doorKey.y = 200;

      } else if(randomNumberFromOneToThree == 3) {
      back.doorKey.x = 300;
      back.doorKey.y = 300;

      }

      That should do the trick!
      Let me know how it goes :-)

  5. Tim says:

    Hi, could you help me with the collision issues that i have right now? I went through all followed all your steps but my version still has the guy going through some of the floating pieces of land and other things

    • Ben Reynolds says:

      The collision detection system I’m using right now isn’t perfect, but at least it’s really simple. There are a number of different ways to make it better, but it depends on what your problem is. Do you have really thin platforms, which the player manages to slip through because he is falling too fast that the hitTestPoint misses the platform? Or is it something else?

      • Tim says:

        I tried thickning the platforms but i would still sink into them half way and sometimes i would go through completely, i was wondering if i could somehow add more hitTestPoints? I noticed it doen’t happen in yours so could you explain what you did.
        Thanx

  6. Justin says:

    hi ben, i followed everything in this tutorial correctly, but when i get the key, the key acts like a wall and so does all my other items including the door. can you please help me with this issue? thank you heaps!!

    • L.E. Grambo says:

      Hello, I’m Grambo. I been helping with helping those of you that need help.
      For the problem you describe, I think you put your door and key at the wrong place, or your collitiontest is wrong.

      Please double-check they are where they should be.
      According to the source-file here, the collision should be “back.collisions”.
      the key and door should just be in “back”(that is, the background).

      And you may want to register to the forums.
      http://as3gametuts.forumatic.com/index.php

      -Grambo

  7. Rio says:

    Hi Ben, is there any other solution of visible =false? I would like to have the key to be completely removed from the scene once it’s collected because i add scoring system for the key, so leaving your character standing there will spawn the score… Thanks.

  8. becky says:

    HI Ben, i’m using a walking dog image instead of the guy i cant seem to get the collision detection right? any ideas……

  9. Bijay Mishra says:

    Very nice tutorial Ben! Thanks!

  10. Ben could you help im getting this error when i launch the game with the key and door mechanics:

    TypeError: Error #2007: Parameter hitTestObject must be non-null.
    at flash.display::DisplayObject/_hitTest()
    at flash.display::DisplayObject/hitTestObject()
    at Loovt_fla::MainTimeline/loop()

Leave a reply to Ben Reynolds Cancel reply