Difference between revisions of "Flappy Tim - Part One"

From Contraptionmaker Wiki
Jump to: navigation, search
Line 142: Line 142:
 
  }
 
  }
 
   
 
   
  FlappyTim.preCollision = onCollision; // TODO - this will change to ‘onCollision’
+
  FlappyTim.preCollision = flappyTimCollision; // TODO - this will change to ‘onCollision’
 
</code>
 
</code>

Revision as of 01:59, 5 September 2014

If you are just getting started, be sure to read Contraption Maker Modding Guide first.

The very first mod we at Spotkin decided to make is the new “Hello, World” of games - a clone of the game “Flappy Bird”. We were amazed at how little code it took. Let’s walk through the construction of “Flappy Tim” step by step.

The first thing you need to do is create a simple level with a Toolman Tim and a wall piece as a floor. Then you will need to give Toolman Tim a script name so that we can access him from the script. You do this by clicking the script button after selecting Toolman Tim.

Selecttoolman.png

Clicking that button brings up a dialog where you can enter the name. We’ll call him “FlappyTim”.

Nameflappy.png

Contraption Maker will automatically create the script object “FlappyTim” so that it can be accessed with the modding script. Say for example we wanted to make FlappyTim jump when the level first starts. We could add a force to him like this:

function onStart()
{
  FlappyTim.addForce(CM.DIR_UP,5);
}

There a few new things introduced in this one line of code that you should notice.

  • We are calling a method on a script object that we named in the Make editor. That object’s name is FlappyTim.
  • We are calling a method on that object called “addForce” and passing in two parameters: a direction in which to apply the force and the size of the force. Technically, in physics terms, we are actually adding an impulse.
  • The direction is a property on a global object “CM”. You will frequently use this object’s properties and methods when writing mods. This global object is always available from any function. For a complete list of properties and methods on the CM object, see the Javascript API Documentation: CM

Try entering this script and hitting play. You should see FlappyTim jump up in the air!

Just for fun, try adding another force to the right:

function onStart()
{
  FlappyTim.addForce(CM.DIR_UP,5);
  FlappyTim.addForce(CM.DIR_RIGHT,5);
}

This time when you hit play FlappyTim will jump up and to the right, and possibly fall off the screen if the floor isn’t long enough!

That was fun, but now lets figure out how we can make FlappyTim move like he should. In Flappy Bird, the bird is constantly flying to the right. We've seen how to apply a single force. How can we apply a constant force? The trick is to apply the force not in the onStart method, but in the onUpdate method. The onUpdate method is called once every frame. Remove the addForce calls from the onStart method and modify your onUpdate function to apply a force every call.

The FlappyTim script should now look like this:

function onStart()
{
}
function onUpdate()
{
   FlappyTim.addForce(CM.DIR_RIGHT,1);
}

When you run this you will notice a problem. FlappyTim flies too fast off the right side of the screen. We need a way to cap his velocity. We can do this by only applying a force if his velocity is less than the velocity we want him to move.

function onUpdate()
{
 if (FlappyTim.getVelX() < 50)
 {
   FlappyTim.addForce(CM.DIR_RIGHT,1);
 }
}

Now FlappyTim moves at a nice even speed.

But wait - how can we let the user make him actually jump? In addition to the onStart and onUpdate methods, there is a third built-in callback function that Contraption Maker will call if it is in your script: onKeyDown. In this method, we can check for a particular key and apply an upward force when that key is pressed.

function onKeydown(key)
{
  if (key == CM.KEY_SPACEBAR)
  {
     FlappyTim.addForce(CM.DIR_UP,5);
  }
}

Now when you press play, Tim starts moving right, and by pressing the spacebar you can keep him aloft indefinitely. Now what we need are to add some obstacles to make things more challenging. Drag some pipes out to make a wall with a gap that Tim must get through, so it looks like this:

Timpipes.png

If you run the game now, Tim will hit the pipes and get stuck. We want the game to actually end, so lets add some code that ends the game when Tim hits a pipe. In order to do this, we need to add a function that will be called when Tim hits the pipe. Contraption Maker looks for the function “onCollision” attached to any script object and will call that function when the object hits something. The part that the object hits is passed into the function.

function flappyTimCollision(otherPart)

{
   partType = otherPart.getType();
   if (partType == CM.PART_BIG_PIPE)
   {
       CM.showGameOver();
   }
}

FlappyTim.onCollision = flappyTimCollision;

There are a few new things being introduced here, lets break this down. We have created a new function “flappyTimCollision”. The function name can actually be anything you want it to be. This function takes a single parameter which can also have any name you want. Inside the method, we call the function “getType” on the part parameter passed into the function. We compare the part type we have collided with to the CM global constant for the big pipe part. If they are equal, we call a CM global function to end the game. Last, and definitely not least - we assign this function to the FlappyTim “onCollision” property. This way the game knows what function to call when the scripted part FlappyTim hits something.

That is it for this first part of making FlappyTim. In the second part, we’ll look at making the camera follow FlappyTim around and add a score. Right now the completed script should look like this:

// onStart called when play is hit 
function onStart()
{
}

// onUpdate called every frame
function onUpdate()
{
   if (FlappyTim.getVelX() < 50)
   {
      FlappyTim.addForce(CM.DIR_RIGHT,1);
   }
}

function onKeyDown(keyCode)
{
   if (keyCode == CM.KEY_SPACEBAR)
   {
      FlappyTim.addForce(CM.DIR_UP,5);
   }
}

function flappyTimCollision(otherPart)
{
    partType = otherPart.getType();

    if (partType==CM.PART_BIG_PIPE)
    {
        CM.showGameOver();
    }
}

FlappyTim.preCollision = flappyTimCollision; // TODO - this will change to ‘onCollision’