Introduction:
Hello and welcome to the tutorial for creating your own "Flappy Birds" style game in hyperPad.
Our version is slightly different, so we're calling it Tappy Plane.
This tutorial is made for beginners who want to dive deeper into our behaviour system and learn about visual coding. Through out the tutorial you'll also learn your way around the hyperPad interface.
In this tutorial we'll create a simple game in the style of Flappy Bird. Gameplay will consist of the player tapping the screen to control the plane to move up and down navigating it past a series of cliffs. Each cliff passed will grant a point and with enough points, players will earn a medal. The medals increase in value the higher one's score, up to a shiny gold medal! And who doesn't like shiny thing!?
If you don't have hyperPad yet, you can download it from the App Store: https://itunes.apple.com/app/apple-store/id886106438?mt=8
You can learn more about hyperPad from our website at http://www.hyperpad.com
So without further ado, let's get started!
Part 1: Getting Started
Creating the project:
The first thing we need to do is begin a new project. Upon loading hyperPad you should see the project screen. Here you will find all the projects you've made as well as any you have downloaded. For now, we wish to start a new project. Tap on the New Project button in the top right of the screen shown below.
Once that's done, you should see a pop up window appear. Here we will name the project and create a cloud backup if so desired. In addition, you can tap the “Get Started with a Sample Instead” button to import one of our base projects. However for now we will not be doing that. Name the project Tappy Plane and then tap the 'Next' button.
In this new screen, we will determine the device we're designing for and orientation. For this project, set the orientation to landscape and the device support to the iPad. Don't worry if you need to change something later. These settings can be adjusted anytime in the Global Settings menu.
Finally we can now choose what type of game we wish to make. Currently hyperPad supports two types of modes, top-down and side view. Top-down, or Bird's Eye View, is typically used for games such as The Legend of Zelda before it transitioned to 3D, puzzle games like Bejeweled and top down shooter games. The Side view is commonly used for platformer games such as Super Mario Bros.
Both versions work identically with one small difference, Bird's Eye View will have the gravity settings disabled (instead it relies on air resistance to simulate gravity going into the screen), so keep that in mind when creating your project. You can always change this later in the Global Properties menu.
For this tutorial, we will be using the Side View so make sure that is selected. Next, we have the Gravity settings and the PTM Ratio. By default, Gravity will be set to 0 and -25.
These are the x and y values, or more simply the horizontal and vertical of our game world. X representing the horizontal, or left and right, while Y represents the vertical, or up and down. The defaults of 0 and -25 means that there will be no gravitational forces pulling objects left and right, but they will fall down at a rate of 25 meters per second. For this tutorial, the default values are fine as they are.
The PTM Ratio stands for Points to Metres, or in simpler terms, how many pixels (points) are in 1 hyperPad metre. By default this is set to 32 pt/m or 32 pixels per metre. This is important to know when creating art assets and all art assets should follow this scale. In this tutorial we will be using free assets from the hyperPad asset library so we do not need to change the scale.
With that done, tap the create button and we shall get started!
The Editor:
Now that we are in the project, you should see a screen that looks like this:
This is our canvas and it is where we will build our game. In the centre of the screen you should see a thin green outline of a box. This represents our screen view. Anything placed in this box will be immediately visible upon starting the game while anything outside it will not be rendered. If you like, take a moment to tap around and see what things do before we move onto the next step.
Once you are ready, tap on the drawer icon in the bottom right to open up the Asset Browser.
The Asset Library:
This is where all the assets for our game will be stored. By default a new hyperPad project only includes a few starter assets. You need to import your own, or download a pack from the hyperPad Asset Shop. In this tutorial we'll focus on using assets provided from the hyperPad Asset Shop. On the left side there will be a bar with four buttons. Tap on the Get Assets button to open the Hyperpad Shop.
Here you will find free asset packs set up by us at Hyperpad to help get your projects started. Find and tap on the Tappy Plane Asset Pack.
Now, simply tap the 'Get' button to begin the import (Note: if an error occurs, simply tap it again to restart the import). Once that is done, you will get a message saying the assets have been successfully imported. Simply tap Close in the top right of the screen to return to Hyperpad.
And its as simple as that. You should now see a new folder in your Asset Browser called Downloads. Tapping it will reveal the Tappy Plane Pack folder and within that, our art assets.
Next we will begin assembling our game.
Part 2: Gameplay
If you are familiar with Flappy Bird, then you will be familiar with the gameplay style. Tap the screen to keep the bird, or in our case plane, in the air while trying not to crash into oncoming obstacles. These obstacles will spawn in random configurations so each play through is different than the last. Points are awarded for successfully avoiding obstacles and your high score is recorded.
Adding the Plane:
So now that you understand the basic gameplay, we can get started. First thing we need to do is get our player character on the screen. Go into your Asset Browser and open the downloads folder and navigate until you see your art assets. There should be a folder called Planes.
Open that folder and choose whichever colour you like the best. Then, simply select the first plane graphic. This will close the asset library and return you to the main editor screen where you should now see the plane in the bottom object dock. This section of the UI is known as the Object Dock. It will display the last 5 assets you have used. Now to get our plane in the play area, simply drag the plane from the dock onto the canvas.
With our plane now in the game, we need to make one quick adjustment. Tap on the plane to select it and open the properties tab on the right. What we want to do is set the plane to become a passable wall object. Simple enough, simply find the Passable switch and tap it to turn it on. We do this because we do not want the plane to fall before the player has a chance to start the game. We also set it to passable because we do not want it to have any collision for now.
With that done, let's dive into making it playable.
Falling Plane:
So we need a way to start the game. To do that, we will need a button. Now we could use a simple graphic to indicate where to tap, but for our game we want to give the player to tap anywhere on the screen. How do we do this? We'll make the entire screen a button!
The first thing we need to do to accomplish this is to create a new layer. But to do that, we need to deselect our plane. To do so, simply tap anywhere there is empty space. Once deselected, the object properties will close and you should see the layers tab on the right. If not, simply swipe your finger from the right side of the screen towards the left to unhide it.
As you can see, there are currently three layers by default. The Global UI, Scene UI and then Main after a separation line. A quick note that anything on the Global UI layer will appear in every scene in your game. All other layers are specific to their individual scenes. To create a new layer, simply tap the + icon at the bottom of the layers tab. This will prompt us to name the new layer. Type in Button and hit OK.
By default, the active layer will change to the newly created one. When using layers, only objects in the active layer can be selected. This is a great way to keep things organized when building your game as you won't accidentally move things you don't wish to. Always keep track of what layer you are currently working on. Also keep in mind that layers placed above another will render on top of that layer. This way you can avoid having your background cover the game area.
Now to create our button, this is very simple. Tap on Special Objects button (the beaker icon) in the bottom right of the Object Dock. This will prompt a menu to create a type of object. We want the Empty Object. Tapping it will create a small, empty square in the centre of our project. However, we want this to take up the entire screen. Tap the inside of the square to select it.
Notice that, when selected, small green dots appear around the border of the object. We can use these to manually scale our Empty Object. Simply tap and drag a corner to scale uniformly. Drag the corners until the object encompasses the canvas. The dots on the sides can be used to adjust the object for a better fit. In the end you should have something like this(Note: If you are having trouble scaling the object, you can zoom in by swiping two fingers away from each other and zoom out by pulling them together):
Return to the main layer by deselecting the empty object (tap any blank area on the canvas) then tapping the Main layer and select the plane again. Tap the button that says behaviours to open the behaviour screen.
This is the Behaviours screen and where the magic happens. Instead of traditional code, hyperPad uses visual logic blocks of actions and events to program the interactions. If you like, take a moment to go through the categories and see what options are available. Tap on one of the behaviours in the left tab to open a window giving a brief description of the behaviour. You can also check out the hyperPad documentation for an explanation of each behaviour.
What we want to do for now is simply start our game and turn our plane from a passable wall object to a physics object. Doing this will apply physics to our plane and thus, fall with gravity.
The first thing we want to do is use the Started Touching behaviour located under the Interaction section. Simply drag it from the menu and into the blank space. Once there it is now attached to our object. You can tap the behaviour to open its properties, but we don't need to change anything.
Of course, with just this, nothing will happen as there is nothing that follows after we touch the plane. Let's fix this. Go to the Physics category and scroll down until you see a section called Modes. Now drag on the Make Physics behaviour and drag it underneath our Started Touching behaviour. Now we just need to attach it to Started Touching. At the bottom of Started Touching, you should see a small lightning bolt in a circle. Tap and drag that and you'll see a line following your finger. Drag the line over the Make Physics behaviour to attach it.
And it's that simple. A quick note that in hyperPad, Behaviours follow a structure of Event -> action. In this case the event is that we Started Touching the plane and the action is that the plane becomes a physics object. Let's take a moment to test this and make sure its working properly. At the top of the screen, press the play button to begin testing. When you're finished, tap the three bars in the top right to bring up the menu and select Quit.
If all is working well, the plane should fall off the screen once you tap on it.
Now we want to end our game once the plane touches the ground. While we don't have any ground at the moment, we can fill it in with an empty game object. Return to the canvas by tapping the back arrow at the top left of the screen.
Deselect the plane and tap the Special Objects icon (beaker) in the bottom right of the dock to open the window and create another Empty Object. Now let's position it along the bottom of the canvas and stretch it so it covers the entire bottom.
Select the plane and open the behaviours window again. Now we are going to add our "Lose" condition. Let's think back to what I said earlier, hyperPad behaviours work on an Event -> Action basis. The event in this case will be the plane colliding with the ground. Let's set that up. Go to the Object tab and under Collision Detection, drag Collided into the workspace. Once that's done, tap it to open its properties. You will see two boxes at the top, one filled with our plane and the other empty. Taping the empty box will open the canvas view. Tap the empty object at the bottom of the screen to select it, then tap the check mark at the bottom to apply.
Next, we need our action. We want to load a game over screen once the plane collides with our ground object. Go to the scenes category and scroll down to the Overlay section and select Load Overlay behaviour and drag it below the Collided behaviour.
Connect the Collided behaviour to the Load Overlay. Now, tap the Load Overlay behaviour on the canvas to open its properties. On the behaviour properties tap where it says Select Overlay. A list of overlays will appear. Select Game Over, this an overlay that is automatically created by default (you can learn more about Overlays from the hyperPad documentation) If you so wish, you can also add in a transition for a bit of flair.
When that is done, press the play button to test. When you tap the plane it should fall and the Game Over screen should come up.
Game Logic:
Before we go any further, I should quickly explain a good way to keep things organized with behaviours. In order to avoid clutter and make changes easier in the future, we are going to separate the game logic from the plane. Basically, we will create our own custom event and broadcast a message when the plane collides with the ground rather than loading the game over overlay.
Why do we do this? Well as mentioned this helps to keep things more organized and it makes adjusting things later much easier. Let's try to think of it this way, if the logic affects only the game object it is attached to, then keep the logic within the object. If you need to start referencing other objects or aspects of logic not directly tied to the object, then separate it. An example would be when the plane collides with an object, it would play a crash sound. This we can keep on the plane itself. But if when it collided with an object, the object then changed somehow, that should be kept separate.
To do this, we will create a mediator, a sort of go between that organizes these actions into one area that we can easily access.
Go back into the plane's behaviours and select the Load Overlay behaviour. There will be a small tab attached to the properties. Tap the trash can to delete Load Overlay behaviour. We are doing this because instead of just loading the overlay, we are going to broadcast a message that our game logic will pick up and load our game over screen instead. While this is technically creating extra steps, it will benefit us in the long run.
To broadcast a message, go to the Custom category and under Broadcast section, drag Broadcast Message and place it under our Collided behaviour (where we used to have the Load Overlay). Attach Collided to Broadcast message and open its properties. Under the Event Key, type in Did Lose. In this situation we can leave Broadcast Value blank, since we're only broadcasting a lose state. If you had a situation that needed to know if you're alive or not, then you can have a value that has the state. (eg. Did lose: Yes/No).
Now that you've added the broadcast message, you can return to the main editor.
Next we need to create something to hold our logic. We could create another empty object but we want to be able to easily find our logic and an empty object can easily be lost as we add more assets to our scene. Instead we will use a label.
Creating a label is the same as an empty object. Select the beaker and in the window, select Label. A label is simply a game object containing text. Other than that it works just like any other object. Tap to select it and in the box under properties where it says Label, Type in Game Logic. If you want, adjust the alignment, outline and shadow properties to help the logic stick out and be noticeable. Please note however, the text will restrict itself to its bounding box size.
Now move the Game Logic outside the visible screen space (green rectangle) so it won't be seen by the player. Think of the Game Logic as the backstage manager. If they do their job right, you'll never see them but everything will run smoothly.
Now, open up the Game Logic's behaviours. What we need now is a way to receive our message. Under Custom, find the Receive Message behaviour and drag it in. Open the properties and tap the Event Key. Type in Did Lose and be sure the spelling is exactly the same as in the Broadcast Message. Next, go to Scene and drag in Load Overlay and set it to Game Over. Connect the two.
The "Receive Message" behaviour is a "Listener" type of behaviour. It will just sit there until it receives the message it was waiting for. In this case "Did Lose". As soon as it receives that message, it will trigger the connected action.
Press play and test. As it did before, the game over screen should pop up as soon as the plane hits the ground.
Jumping Plane:
For our game, we want our plane to remain stationary on the horizontal axis, this means it will not be moving left and right, only up and down. Instead of having the plane fly horizontally through the world, we will have the scenery move around the plane giving the effect that the plane is moving horizontally. This is to accommodate our one button play style. Tap the screen, the plane goes up, then starts to fall back down.
Go back into the plane's behaviours and under Custom the custom category add a new Behaviour Bundle. Open up its properties. Unlike other behaviours, the bundle is completely blank. We can however, change its name. At the top of the properties, tap the name Behaviour Bundle to change it. Type in Jump. Next, we want to have this bundle turned off by default. So in the little side panel attached to the properties, find where it says On and tap it to turn it off. The bundle should now turn grey.
A bundle is used to attach a group of behaviours together. In addition, they will be executed in order of left to right in sequence. This way we can better control how and when certain behaviours happen. We have this bundle turned off because we don't want it, and the actions we will attach to it, to activate until after the game begins.
Now we want to attach some behaviours to our bundle. First, Set Velocity which is under the Physics tab. Open its properties and set the X and Y to 0. We do this so that we can remove the force of gravity on the plane and cancel any previous jumps still in action.
Next we need to Apply Force, also under the Physics tab. Leave the X value blank but change the Y value. For now let's set it to 5. We can play around with this number later to find the best effect for our plane.
Above the behaviour bundle, add in a new Started Touching behaviour. Attach it to the Jump bundle. Now we want this Started Touching to react to our button we made earlier. To change it, open its properties and tap on the plane to go to the canvas. Change the layer to Button and tap the inside of our button.
Your behaviours should now look something like this:
There is still a few things we need to do however before we can test. First, we need to activate the bundle. So navigate to the Custom category, then add a Behaviour On and attach it to the Started Touching button. Open its properties and tap the Select Behaviour section and select the Jump behaviour bundle from the list. So now, when we first touch the button, the Jump bundle will activate and start applying force to the plane. Of course, we will run into issues with the first Started Touching behaviour we already created. Let's fix that.
Under the first Started Touching, add a Behaviour Off behaviour (under Custom) and attach it to the original Started Touching. Under its properties, select the same Started Touching as the behaviour you want to turn off. Now, it will first make the plane a physics object, then disable the ability to touch the plane. We're not done with it yet though. Next we need to add a Broadcast Message to indicate that our game has started. Add a Broadcast Message and attach it under the Make Physics behaviour. This will ensure the message will send before disabling the behaviours. Set the Event Key to Did Start.
Finally we can add the last bit of behaviours. Add a Receive Message behaviour, but don't bother attaching it to anything. We want it to do its own thing. Set its Event Key to Did Start. Next, add a Behaviour On and attach it to the Receive Message. Have it turn on the second Started Touching we made.
But wait, you may ask, that behaviour is already on! You're right! Let's turn it off. This way, we will no longer have that overlap of buttons that can cause errors. With all this said and done, your plane's behaviour's should look something like this:
Let's test it out. You may notice that your plane drops like a rock even after tapping. Well that's because our Apply Force is set to 5, but gravity is working at -25. If we want our plane to fly, we'll need to overcome gravity. Open the properties for Apply Force and change the Y value to 50 and the multiplier to 5. This should give our plane just enough lift to stay airborne for just a moment. Take some time to adjust the numbers until you find something that feels right.
Adding Obstacles:
Moving onto the next step, we need to add the obstacles for our player to avoid. For our game there will be two main obstacles. The cliffs and the ceiling. Yes a ceiling. No we will not set this in a cave. The reason for this is quite simple, without a ceiling the player could theoretically just tap the screen like mad and have the plane not only fly off screen, but completely bypass any obstacles. That's no fun now is it?
Let's begin with the ceiling since that's pretty simple. Just like the ground we are going to use an Empty Object. Make sure you are on the Main layer and add the empty object, then create and scale it to the width of the screen and move it so it sits just above our canvas. This way, the plane will be able to fly within the screen space but will crash when going beyond those limits. In the Empty Object's properties, under the behaviours button you will notice three images. A rocket ship, a box of bricks and a landscape portrait. These buttons determine what kind of object our Empty Object will be. In order from left to right it is Physics object, Wall Object and Scenery Object.
Physics objects are objects that are affected by physics. We don't want that. Wall objects are solid and have collision, but cannot be affected by outside forces. Scenery objects have no collision and cannot interact with anything. As a rule, any objects that are just there for decoration should be set to scenery to save on memory and improve game performance.
Set the Empty Object to Wall object and underneath those buttons where it says Passable, turn the switch on. This will make it so that the box won't just fall to the ground, but the plane can still pass through it. This way the plane doesn't just stop upon touching the box but will allow it to go slightly off screen before it begins to fall.
Just for good measure, with the Ceiling object still selected, let's rename it to ceiling. At the top of the properties menu, tap where it says Empty-# and type in Ceiling. It never hurts to be organized.
Next up we are going to add a Tag to our Ceiling. Tags are a way of referencing multiple objects at once so long as they share the same tag. For example, say you had a light switch and when used, it would turn on several lights in a scene. By giving all the lights the same tag, they can be referenced all together and be turned on simultaneously. In our case, we want our plane to fall when it collides with the ceiling and cliffs so we're going to give it a tag to cause that and save us some time assembling behaviours.
With our ceiling object selected and the properties tab open, look to the bottom to see a series of five buttons. The first should be greyed out followed by a rocket ship (opened by default), four arrows, a stack of four lines and finally, sales tags. Tap on the tags to open the tags window. Here you can search for preexisting tags or create a new one. In this case we want to make a new one. Tap the + sign and enter the name Wall and hit Ok. Wall will now appear under the search bar with a green circle to the right of it. This circle indicates the tag is attached to the object. Should you wish to change tags, simply tap on the name of the tag to remove it.
Now we want our plane to be able to collide with objects that are tagged as "Wall" and when that happens, we will disable the player's input. Thus causing the plane to fall to the ground and end the game. To do this, select the plane and go into Behaviours. Under Objects, select Collided and open the properties. Now, instead of tapping Select Object and selecting our ceiling on the canvas, we want to instead check for the tag. To do that, go to the bottom of the properties where the tag icon is and select it. This will bring up a list of tags. Currently we only have Wall. Select it, then tap the icon with three sliders on horizontal lines to go back to the main properties window. You will now see the tag icon in the Select Object box.
With that done, we can now simply add a Behaviour Off from the Custom tab and in its properties, select the Started Touching that controls our Jump bundle. This will disable our ability to fly when we touch the ceiling. Let's test this. Press play and tap on the screen until the plane flies out of bounds. You should see it then fall to the ground and the game over screen load.
By now you might be wondering “Why does the plane only go up and down? How will we fly through things if it can't go forward?”. Well, that's simple. We're going to have the world move towards our plane. If that sounds weird, don't worry, you won't notice once it's playing.
Time to add in our cliffs. Go back into the asset browser and scroll down to find our cliffs. There are multiple versions so simply choose your favourite. I'm going to stick with the basic rock for this tutorial.
Drag the cliff onto our canvas, then move it over to the right so it won't be seen. Next, make it a passable wall object. Now we want to change the anchor point. The anchor point is what hyperpad will assume is the centre position of the object. So when doing calculations for position it will
reference the anchor rather than the actual physical centre.
To change it, we need to open the transformation properties. Down at the bottom of the properties window, select the four arrows to open the transformation options. Find the anchor point and unlock it. You should see a blue anchor appear on the cliff now. Tap and drag the anchor and place it as close to the top tip of the cliff as you can. Once that's done, lock the anchor again.
Now we need our cliff to start moving towards the player. Open the cliff's behaviours and add a Set Velocity behaviour located under Physics. Set the Y velocity to 0 and the X to -2. This will cause the cliff to slowly move to the left. As a quick note, for the X axis, negative values will cause objects to move to the left while positive values to the right. The same applies to the Y axis with negative going down, positive going up.
This speed however, is far too slow and it can quickly become annoying constantly having to go back into the cliff's behaviours to adjust the value. Instead we can use something called an Attribute to make this process quicker. Let's go to our Game Logic label and open its properties. Remember the icon at the bottom with the four stacked lines? Tap it to open the Attributes window. Attributes work similarly to Tags in their creation, so let's make a new one and call it Speed.
You will notice however, that unlike Tags, there is an input box underneath our new attribute. We can use this box to input values that other objects can then reference. For now, let's set Speed to 5. Now we can return to the cliff behaviours and add a Get Attribute behaviour under the Objects tab.
Open up the Get Attributes properties and tap on the cliff icon that appears. On the canvas, select our Game Logic label and under Attribute Key Type, set to Predefined and select Speed for the input box.
Next we need to make sure the cliff will move to the left. Remember how I said that positive values on the X axis move to the right? Well we're going to change that. Go to the Logic tab and select Multiply Values. Attach it to our Get Attribute and open its properties. You will now see two input boxes. The first box will be our value and the second is what we will multiply it by. Notice how, when Multiply Values is selected, small green circles with upward arrows appear on the corners of some behaviours? This means that we can use them in the input boxes. To do this, simply tap and drag the circle on our Get Attribute behaviour and place it in the first input box in our Multiply Values properties. (to learn more about this check out the Sharing Values documentation)
Next, in the second box, type in -1. So now we are multiplying our Speed with a value of 5 by -1 resulting in -5. This the cliff should now move 5 meters left every second. Well, it will in a moment. Go back to the Set Velocity behaviour and where we wrote in -2, replace it with the output from our Multiply Values. Leave the Y value at 0.
Test the game and see the cliff move across your screen. The cliff is now moving at a good speed, however you can always adjust it quickly by going back to the Game Logic label and going to its attributes. Much quicker than going into cliff behaviours every time, right?
Notice however, that our plane will simply pass through the cliff? That is because we set it as passable. We want to leave it this way but we can still have our plane crash into it. All we need to do is apply our Wall tag. Open the cliff's properties and go to the tags tab. Select Wall and test the game. Be sure to fly into the cliff.
Something weird happened right? The plane just started falling uncontrollably before we even touched the cliff. This is because the cliff's collision box is not properly set up. By default, an object's collision is set to the same dimensions as it's bounding box (the area that you can touch to select it). The bounding box is defined by the object's graphic maximum width and height. So regardless of the shape, the bounding box, and thus collision, will be stretched to enclose the entire object in a box.
How can we fix this? Simple.
hyperPad has a built in collision editor that allows us to easily fine tune an object's collision. To access it, open the cliff's properties and on the left of the properties you should see the familiar mini window containing 3 options. Two arrows pointing towards one another, two boxes overlapping each other, and a trash can.
We want the first option. Tap it to open the collision editor.
Immediately you'll see a series of tools on the side bar. The first two are for navigation and moving. With the arrow selected, we can easily edit the collision of our cliff by simply scaling the box like we would the object. However, you probably notice that a box may not be the best shape if we want our collision to be as accurate as possible.
The next three tools can help with that. The first two, the sphere and square, can change the bounding box to the respective shape. The third tool, which looks like an odd polygonal shape, allows us to create custom collision boxes by simply tapping our finger and connecting the dots. Let's use this one.
Select the tool and tap on the tip of your cliff. You should see the old collision disappear and a small green dot appear. Now tap on the bottom left corner of the cliff to create a second dot connected by a black line. Do this again for the bottom right corner and finally connect back to the original dot. Its okay if you aren't perfectly accurate, we can easily fix that. Simply tap on the arrow tool and now you can drag your dots to better fit your cliff. In the end you should have something like this:
Lastly, tap the check mark to save these changes. If you've made a mistake, simply use the eraser tool, or simply tap the X to cancel all changes and try again. Once that's done, test your game again. The plane should now fall properly when hitting the cliff.
Now this is still a bit too easy. There's only one cliff and its position is always the same. We gotta spice it up a bit! So the plan is to have the cliff's position on the Y axis be randomized upon spawning and have the Game Logic control both that and its spawn rate. The movement will be controlled by the cliff itself. This is where the earlier lesson of splitting the logic will really be put to practice.
To begin, let's go back to our Game Logic's Attribute list and create a new attribute called Cliff Bottom pos.
Now, go into the Game Logic behaviours and create a new Behaviour Bundle. Call it Calculate Positions. Next we need to go to the Logic tab and grab the Random Number behaviour. Open the properties and set the variables to 4 and 14. Connect it to Calculate Positions bundle.
Now you're probably wondering where I got those numbers from. Well, to find out, let's return to our Asset Browser and find our cliff again. Tap and hold your finger on the cliff for a moment to open up an options window. Tap preview and it will open the Frame Preview. Here we can see the size of our cliff is 8 meters by 16 meters.
We set the values of 4 and 14 because when we spawn the cliff, its position will be randomly adjusted between 4 and 14 meters on the Y axis, or up and down. We also set these limits so that the cliff won't spawn too high or too low on the screen.
Back in our Game Logic behaviours, go to the Objects tab and grab the Set Attribute behaviour. Connect it to our Random Number behaviour. Open the Set Attribute Properties and set the Attribute Keys to Predefined and Cliff Bottom pos. For the Attribute Value, take the output in the top right corner of the Random Number behaviour and place it in the Attribute Value input box.
We're done here for now, next we need to go back to our cliff's behaviours.
On the Cliffs behaviours, place a new Get Attribute behaviour from Objects tab. Change the target to Game Logic by opening the properties and tapping on the cliff image. Then, once you're back on the canvas, simply tap Game Logic and tap the check mark. Set Attribute Keys to Predefined and Cliff Bottom pos.
Now let's set the start location for our cliff. Under Transform behaviour category, we will need to open the Advanced tab. At the bottom of the behaviours you will see two options, Basic and Advanced. Tap Advanced to reveal all the behaviours. Scroll to Position and select Move to Point. Attach it to our new Get Attribute. Open Move to Point's properties. We'll leave the Transition and Position Type the same. For the X value, we're going to set it to something off-screen. For now, let's input 40. For the Y, we will assign it the Get Attribute for Cliff Bottom pos. Lastly, change the Duration time to 0.
Do a test.
Most likely the cliff's position hasn't changed. This is because the calculation was made after it spawned. So let's spawn in more cliffs to see our randomizer in action! To do that, we need to return to our Game Logic behaviours.
Let's grab a new Random Number behaviour (under Logic) and set the numbers to 1.5 and 3. These values are going to become our spawn timers so a new cliff will spawn sometime between every 1.5 to 3 seconds. So the shorter the time between spawns, the closer the cliffs will be together and vice versa. Now, let's grab a Wait behaviour under the Custom tab. In its properties, set the time to our new Random Number.
Next we need to grab a Behaviour On and assign it our Calculate Positions bundle. This way, we will have a new position calculated for each cliff that spawns. Now we need to spawn the cliffs.
Go to the Objects category, open the Advanced tab and find Spawn on Area. Drag it under our Behaviour On and attach it. Open the properties tab and you should see your Game Logic graphic. Tap that and select the cliff. Now we will spawn cliffs instead of more Game Logic. Next, at the bottom of the properties, turn the Recycle switch on and set # Alive Objects to 5. By setting Recycle to on, we make it so that older objects will be remove automatically once the maximum number of cliffs has been reached, in this case 5.
If you ever get confused as to what certain properties do, remember that you can always tap the i icon at the bottom to bring up the quick reference for that behaviour.
Next up, we need to get this looping so our cliffs will constantly spawn in. Add a new Behaviour On and set it to our Random Number for our timer.
Now upon completing the spawn, our Random Number will begin again, thus creating an infinite loop of cliffs trying to murder the player! Yay! Let's put it to the test.
We should now see the cliffs moving towards us randomly. However there are still some issues so let's clean this up a bit.
Create a new Behaviour Bundle (Custom category) and rename it by opening the properties and tapping the name. Call it Initial Cleanup. Now, go to the Objects tab and get the Destroy Object behaviour. In the properties, set the target to our cliff. There is also the issue that the cliffs will start moving before the player has even touched the screen.
To remedy this, first turn the Random Number controlling our spawning off by default. To do this, tap to open the properties window. In the mini-window, find the word On and tap it. To turn it on, we simply need to tell the spawner that our game has started.
Open the Custom tab and find Receive Message. For the Event Key, we already have a message broadcasting for what we need (back when we set up the plane). Type in Did Start. Now, simply grab a new Behaviour On and assign it our Random Number.
Press the Play button. Things should be working properly now... Although its still not that hard is it? Let's bump up the difficulty.
Back on the main editor, select the Game Logic and open the Attributes tab (four stacked lines at the bottom of properties). Create a new attribute and call it Cliff Top pos. Next let's go to the Logic tab and grab the Add Values behaviour. We are going to add this into our Calculate Positions bundle. Tap on the line connecting our Random Number (4-14) and the Set Attribute. This will break the two apart and allow us to squeeze our Add Values behaviour in. Connect the Add Value to the Random Number and the Set Attribute to the Add Value. Open the Add Value properties and take the output from the Random Number (top right corner of the behaviour) and place it in the first input box. In the second box, enter the number 8.
What we want to do is spawn a second, inverted cliff above the one we already have. Doing this will allow us to set the cliff to always spawn 8 meters above our other cliff, giving our plane space to fly between the cliffs. Next, go to the Objects tab and grab another Set Attribute behaviour. Connect it to the Add Values and open the properties. Set the Attribute Key to Cliff Top pos and the Attribute Value to the Add Value output (top right corner of the behaviour).
Still, with this we won't see any difference. First we need to go back to the editor and select our cliff. With the properties open, look to the object menu (on the Object properties) and the second icon (two boxes or papers on top of one another). This is the duplicate button. Tap it and we now have two cliffs.
Open the behaviours on the new cliff. As you can see, even the behaviours have been copied which will make things easier. Open the properties for our second Get Attribute (the one attached to Move to Point) and change the Attribute Key to Cliff Top pos.
Go back to the editor and with the cliff still selected, you should notice a curved arrow with two points in a circle to the top right. This is the rotate tool. We want to rotate the cliff 180 degrees so it points downwards. However if we just use it as is, it'll be near impossible to get a perfect 180. What we need to do is set the snapping on.
The snapping automatically turns on whenever the grid is activated. The grid tool is in the tool bar on the left, underneath the screen resolution. Tap it then rotate the cliff until it's upside down. (additionally you could rotate the object from the Transform tab in the Object Properties)
Almost done here. Go back to the Game Logic and to our Initial Cleanup bundle. Open the Objects category, grab a second Destroy Object behaviour, attach it to our bundle and target the new cliff.
Lastly, we need a second Spawn on Area to get this cliff working. To save some time, simply duplicate our existing one, attach it to the Behaviour On (Calculate Positions) and set the target to our new cliff.
Hit Play to test.
There's a chance that your plane may be too big to fit safely between the cliffs. If that's the case, like it is mine, let's fix that real quick. Go to the editor and select the plane. At the bottom of the properties, tap the four pointed arrow to open the Transform properties. In the Scale section, tap the broken chain link. This will lock uniform scaling so changing one value will also change the other.
While we could scale manually by dragging the corners of the object, this will be more accurate and simpler from the Transform Properties. With the uniform scaling locked, tab the input box for the X axis and type in 50. This will reduce our plane's size by half. Press play and test again. The plane should fit safely between the cliffs.
We now have a playable game! However, just flying through cliffs isn't quite exciting enough on its own. To give the player some incentive, we will next add points to our game.
Adding Points:
Why do we need to add points? Well, it's one of the oldest and most effective incentives for players in gaming. Points give the player a reason to keep coming back to your game again and again. Who doesn't want to try to best the high score? We'll be adding more incentives like medals based on the points earned, but that's for later.
So how are we going to calculate points in our game? Well, we're simply going to create a sensor that will read when we have successfully passed through a cliff and then add a point to our score. This will be done in a similar way that we made the top cliff. We are going to create an empty object (we don't want our players to see it, we just need the game to read that the plane has passed through the sensor) and add to our existing behaviours so the sensor spawns with our cliffs and always in the same relative position to them.
To get started, on the editor screen, select Game Logic and open the Attributes tab in the Object Properties (four stacked lines). Create a new attribute and name it Cliff Score pos. Now, go into the behaviours and back to our Calculate Positions bundle.
We will be adding a Subtract Values now as we will be calculating our sensor's position relative to our top cliff. First, detach our Set Attributes from our Add Values behaviour by pressing and holding the line connecting them.
Then open the Logic category and drag in Subtract Values behaviour. Attach it to our Add Values and then attach the Set Attributes to the Subtract Values. Now, take the output from Add Values and place it in the first input box of Subtract Values and in the second box, type in 4. Next, go to the Objects tab and grab a new Set Attribute. Attach it to Subtract Values, then set the Attribute Key to Cliff Score pos and the Value to the output of Subtract Values.
Now we can return to the main editor and create our sensor object. Tap on the beaker and select Empty Object. Then, in its properties, open the Transform tab (four arrows) and set the scale to 50x and 350y.
Now open our sensor's behaviours and we will be doing something very similar to our cliffs (they need to spawn and move together) so if you wish to look to them for reference, go right ahead.
First, grab the Get Attribute behaviour from the Objects category and in the behaviour properties set the target object to game logic and the Attribute Key to Speed. Go to Logic tab and get the Multiply Values behaviour and attach attach it to our Get Attribute. In the properties, set the first Input box to the output of Get Attribute (top right corner) and multiply it by -1.
Then go to the Physics tab and get Set Velocity, attach to Multiply Values. In the properties, set the X to the result of our Multiply Values (again the top right corner) and the Y to 0.
Now let's get a second Get Attribute from the Object category, once again select Game Logic as the target object in the properties and change the Attribute Key to Cliff Score pos. Then, under the Transform category, open the Advanced tab and grab Move to Point. Set the X position to 41 and the Y position to the Get Attribute output (Cliff Score pos). Doing this will ensure it always comes in after the gap in the cliffs and set the duration to 0.
Again, if you feel unsure, simply go back to your cliffs and double-check the behaviours. They are practically identical here.
Go back into your Game Logic behaviours and find the spawner behaviours. We need to create a new Spawn on Area for our sensor. Select one of the existing Spawn on Areas and duplicate it by opening the behaviour properties and from the side menu, tapping the overlapping boxes. Then, change the target object (Object A) from the cliff to our empty object.
Lastly, let's add to our Initial Cleanup bundle. Same as before, go to Destroy Object and attach it to the bundle. Open it's properties and set it to our Empty Object.
With that done, the next step is to create an event for when our plane has scored. Which means we need to create a behaviour that reads when the plane passes through our sensor and then increase our score counter.
To start, go back to our sensor object and open the behaviours. Open the Objects category and add the Collided behaviour. Set the collision Object B to our plane. We do it this way as otherwise, we would be required to use tags and that can get a bit too complex if we're using tags for everything. Then, go to the Custom category and get the Broadcast Message, attach to the Collided behaviour. Set the Event Key for the message to Did Score.
Now we need a way to see our score. For that we need to create a Label.
Go back to the main editor and change to Scene UI layer, then tap the beaker in the dock. Select Label and move it to the top middle of the game area. Set the size to 120 pts (you may need to adjust the alignment to see the text) with a 4 point black outline (be sure to increase the opacity to max). Then change the colour by tapping on the three coloured intersecting circles. At the top of this new drop down window, you will see the colour code, enter 9B8766FF.
Next, we need to change the font type. We want to use Futura Condensed Extra Bold. To get this font, we'll need to do a quick import. With the Score properties open, tap the box with the large Helvetica text to open the Asset Browser and on the left where it says Import, tap it to open a new window. Then, tap on System Fonts. Scroll down or tap the F on the right side and find Futura- Condensed Extra Bold. Tap it then tap Done in the top right. The font should now appear in your browser. To apply it, simply tap on it. Lastly, let's change the text that will appear in game. In the text box, remove Label and simply type in 0.
Open the behaviours for our new label and go to Custom category. Add Receive Message and set the Event Key to Did Score. Then, go to the UI category, get the Add to Score behaviour and attach it to Receive Message.
Press play and see how many points you can get!
High Scores:
Now we should probably save the high score, since as it is right now, the score is lost upon closing the game. High Scores also add an extra level of replay value. Players are more likely to return to your game and play it more trying to beat their previous score.
Let's go back to Game Logic and open the behaviours (don't forget to change back to Main layer or whatever layer you stored it on). Open the Custom category and add a new Receive Message, set the Event Key to Did Start. Next, scroll down to the Permanent Storage section and grab Load from File, attach to the Receive Message.
Open the properties for Load from File and set the Default Value to 0. Ignore the Key Type for now, we don't need to worry about that just yet.
Next, we need another Receive Message behaviour. Set the Event Key to Did Lose. This way, it will update our saves upon ending a session of gameplay. Open the UI category and grab a Get Label behaviour, attach it to the Did Lose Receive Message. Set the object to our score label (you may need to change layers when selecting). Next, go to the Logic category and grab the If behaviour, attach it to our Get Label. Now, take the output from our Get Label and place it in the first input box of the If behaviour. Take the output from Load from File and place it in the second input box. Then, change the centre text from Is Equal to to Is Greater Than ( the '>' symbol).
We do this because we only want to save our score if it's higher than our previous saved score. So now we need to actually save the value. Under the Custom category, scroll down to the Permanent Storage section and grab Save to File, attach it to our If behaviour. In the properties, set the Key Type to Existing. Then, tap where it says Select Key, in the new window press the + sign and type in Highest Score. We have now created a new Key that we can reference with our Load from File. Next, set the Value to Save to the output of the Get Label behaviour.
Go back to the Load from File, open the properties and set Key Type to Existing and Select Key to Highest Score.
We also should save the current score so we can call on it later.
Under the Get Label, add a new Save to file. Open the properties and set the Key Type to Existing. Tap Select Key and press the + icon. Type in Previous Score and set the Value to Save to the Output of Get Label.
Next up, we will make adjustments to our game over screen to show off our scores, medals and more.
Game Over Screen:
At this point, our game is pretty much done, the only big thing left to do is to set up a proper Game Over screen, everything beyond that will simply be polish. In this case, we want to add in the player's current score, their best score, a little achievement indicator for when they achieve a good score and finally a restart button.
The good news? We don't need to create the Game Over screen from scratch since we are already using the default overlay created by hyperPad. We do however, want to fix it up a bit as it's too plain and boring at the moment.
To access Overlays, we need to open the Scene Menu. To do that, when on the main editor, simply tap the three stacked lines in the top left. This will open a list of all the scenes currently in our game (at the moment we only have the one). At the bottom you will see a tab that says Overlays. Tap it to open and there we will find two default overlays created by hyperPad, Pause Menu and Game Over. Tap Game Over to change scenes and load it.