Order now AGK Bitesize

Lesson Three - Let's get Physical

by Steven Holding

Introduction to input

One of the problems with trying to make a game adaptable for multiple platforms is the method of control. AGK helps out with a set of commands for creating "Virtual Joysticks" and "Virtual Buttons" that can be used to bridge the gap and make games work equally well on touch-screen devices and desktops.

This month we will create a virtual joystick and a button to control a character. We will create our character in a physics based world in order to expand our knowledge of using physics sprites and create a simple platform game engine.

Let's start with a brand new project and add a virtual joystick using the following command before our loop.

AddVirtualJoystick(1,10,88,12)

This will add a virtual joystick with an ID of 1 at 10% across the screen and 88% down (the bottom left corner of the screen) with a diameter of 12% of the width of the screen as shown below.

bitesize

To get an idea of the kind of output we get from the joystick add these lines within the loop and run the project.

Print("Joystick X:" + str(GetVirtualJoystickX(1)))
Print("Joystick Y:" + str(GetVirtualJoystickY(1)))

When you run the project try dragging the joystick with the mouse. As you will see we get a value between -1.0 and 1.0 for X and Y which directly relates to the position of the joystick from its centre.

We can change the images used and visibility of the joystick to suit our game and even set up a "dead zone" for the joystick to give us a minimum returned value. This means small movements are not picked up by the joystick allowing us to concentrate on only the more deliberate moves made by the player (if we wish).

For now let's add a character for us to move with the joystick. We will use a simple box shaped character for the time being and turn it into a dynamic physics object, this will simplify movement and dealing with collisions as you will see.

spr = createSprite(0)
setSpriteSize(spr,4,8)
setSpriteOffset(spr,2,4)
setSpritePositionByOffset(spr,50,96)
setSpritePhysicsOn(spr,2)
setSpritePhysicsCanRotate(spr,0)
boxman = spr

Most of the code above should be familiar from last month's tutorial but the last physics command is very useful "setSpritePhysicsCanRotate(spr,0)". This means our dynamic sprite will not rotate or fall over and will for the most part react something like a character controller. The sprite will still react to forces such as gravity but can stay standing at the same angle unless we change the angle of the sprite using "setSpriteAngle(spriteID, angle#)".

Our character sprite doesn't move around yet though so let's add some code into the loop to get it moving!

setSpritePhysicsVelocity(boxman,GetVirtualJoystickX(1)*30, _
getSpritePhysicsVelocityY(boxman))

Now compile the project again and you'll see "boxman" can run left and right. You may notice that we are setting the left / right velocity to 30 times the value from the joystick meaning it will be set between -30 and 30. The vertical velocity is being set to its existing value, why? Well we will be setting boxman's vertical velocity (jumping) separately. This just makes it easier to set the two velocities separately and shows how we can build up a combination of different velocities independently.

What we don't have at the moment is any way to jump. What's a platform game without jumping right? First we need a jump button so add the following line before the loop.

AddVirtualButton(1,90,88,12)

As you can see the settings are very similar to the joystick commands, we are creating button number 1 at 90% across the screen and 88% down. This time we are making it 8% of the screen width in diameter. It should look something like this when you compile and run the project.

bitesize

Below is some simple code to add vertical velocity to our character when the button is first pressed. Add it into the loop.

jump = GetVirtualButtonPressed(1)
if jump>0
    setSpritePhysicsVelocity(boxman,getSpritePhysicsVelocityX(boxman),-jump*60)
endif

This time we are setting the horizontal velocity to its existing value since we are editing it elsewhere (as before). The vertical velocity is being set only when the button is pressed.

This time when you compile and run you will be able to make boxman jump when the button is pressed. Of course when we are not running on a touch-screen device this control method would be rather difficult and un-intuitive so let's add keyboard control too and some code to decide which version to run. Take the virtual joystick and button creation commands and put them into a conditional statement like this.

keyboard = getKeyboardExists()
if keyboard=0
    rem create a virtual joystick
    AddVirtualJoystick(1,10,88,12)
    rem create a jump button
    AddVirtualButton(1,90,88,8)
endif

Now edit the loop so that we have a similar condition like this.

do
    if keyboard=0
        rem get jump
        jump = GetVirtualButtonPressed(1)
        if jump>0
            setSpritePhysicsVelocity(boxman,getSpritePhysicsVelocityX(boxman), _
-jump*60)
        endif
       
        rem move boxman
      setSpritePhysicsVelocity(boxman,GetVirtualJoystickX(1)*30, _
getSpritePhysicsVelocityY(boxman))
    else
        rem add keyboard control here!
       
    endif

 
    Sync()


loop

We will now add some code where I have added the remark "add keyboard contro

l here!" as the rest of the code will now only run on devices that have no keyboard. First it is useful to know the ID of the keys you would like to use. Here is how we can find that out. Add the following line of code after the remark "add keyboard control here!"

Print(str(getRawLastKey()))

This will tell us which key we have just pressed. Compile and run, then press the keys you would like to use for "left", "right" and "jump" and write down the ID's that are printed to the screen. I will just be using the left / right / up keys which are 37, 39 and 38 respectively. Here is a keyboard version of our "virtual" control system using those keys. Have a look and check the differences.

jump = GetRawKeyPressed(38)
if jump>0
    setSpr itePhysicsVelocity(boxman,getSpritePhysicsVelocityX(boxman),-jump*60)
endif
rem move boxman
setSpritePhysicsVelocity(boxman,(GetRawKeyState(39)-GetRawKeyState(37))*30, _
getSpritePhysicsVelocityY(boxman))

We are using two new commands here "GetRawKeyPressed(keyID)" and "GetRawKeyState(keyID)". The first returns a value of 1 when the key is first pressed and 0 otherwise. The second returns 1 for as long as the key remains pressed and 0 otherwise. So using a similar version of the previous code we can create a similar kind of control system using completely different input methods.

Now we will add some simple platforms to jump around on. Add the following code before the loop to give us some static platforms.

spr = createSprite(0)
setSpriteSize(spr,30,2)
setSpriteOffset(spr,15,1)
setSpritePositionByOffset(spr,15,75)
setSpritePhysicsOn(spr,1)
spr = createSprite(0)
setSpriteSize(spr,30,2)
setSpriteOffset(spr,15,1)
setSpritePositionByOffset(spr,85,50)
setSpritePhysicsOn(spr,1)
spr = createSprite(0)
setSpriteSize(spr,30,2)
setSpriteOffset(spr,15,1)
setSpritePositionByOffset(spr,15,25)
setSpritePhysicsOn(spr,1)

Also add this code before the loop to add a single "kinematic" platform which we will animate in the loop later.

spr = createSprite(0)
setSpriteSize(spr,30,2)
setSpriteOffset(spr,15,1)
setSpritePositionByOffset(spr,50,15)
setSpritePhysicsOn(spr,3)
kinematic = spr
direction = 10

Remember that kinematic physics sprites can have velocity (speed) applied to them, to make our platform move simply add the following during the loop.

setSpritePhysicsVelocity(kinematic,0,direction)
if getSpriteYbyOffset(kinematic)>85
    direction=-10
else
    if getSpriteYbyOffset(kinematic)<15
        direction=10
    endif
endif

This just moves the platform up / down to within 15% of the top / bottom of the screen then changes its direction. Have a jump around on the platforms and try playing with some of the values to make boxman move faster or jump higher. As a further challenge why not try adding some images and animation too! Maybe you could try editing the jump button to make boxman fly like he's wearing a jetpack?

bitesize

This example of setting up different control methods for different platforms uses less than sixty lines of code to create a simple platform game. A full version of the code for this tutorial can be downloaded <here>

AGK Bitesize

The full code and a compiled version of this month's example can be downloaded here. As an extra challenge, why not try to build a more complex structure to demolish, using the simple techniques learned in this tutorial.