Hello and welcome to this Construct 2 Course series for the creation of the game Jetpack Rush.
My name is George Femic and I am a professional video game developer. I have been developing video
games for more than 9 years.
I have mostly worked on Flash, mobile and HTML5 games. I am an experienced programmer and
designer and I am highly proficient in Actionscript 3.0, C# and Unity, Construct 2, Object Oriented
Programming, video game design, math and testing.
I started working as a programmer intern in a local game development company and I now work as a
freelancer and under the name GGames.
Lecture 1
Hello and welcome to the first Lecture of this Construct 2 Course for the creation of the game Jetpack
Rush.
In this Course series you will learn how to create a professional quality HTML5 game from scratch. It will
be a cross-platform browser game compatible with desktop and mobile devices.
Construct 2 is a great tool for creating games without having to write any code. It uses a powerful event
sheet system for programming.
This series will cover the Construct 2 editor, assets, event sheets, variables, logic, functions, event flow,
mathematical equations and everything else that is needed to develop Jetpack Rush.
--Gameplay
Jetpack Rush is a casual arcade game where the objective is to score as many points as possible.
The player can be controlled using the keyboard, mouse or touch control. By navigating the player, the
user needs to collect as many gems as possible, while avoiding the enemies. The games speed is
progressive and flows through 10 waves.
At the end of the game the player is awarded a 3 star rating based on their performance.
The game also features 10 achievements which the player can unlock.
--C2
In this Lecture we will go through the basic set-up for this game. You will learn how to set the project,
layout and margin size and import sprites and animations.
To begin, create a new project in Construct 2. Go to project properties and set the project size to 720,
400. The project size is the base resolution of the entire game. The optimal embed size is usually this
resolution. The size of the game will always scale proportionately to the size of the browser window.
Click anywhere on the layout to go back to the layout properties and set the size of the layout to
870x400 and the margins to 720x400. The size of the layout is larger than its margins, because in this
game the whole level will cover more than 1 screen. The solid border which envelopes the white
rectangle is the entire visible layout, while the dashed and transparent border represents the margins of
the layout.
Rename the layout to Game and its event sheets to Game events.
Next, we will import the background objects. [Importing, Names: HillsBack2, HillsBack1, HillsFront]
Set the position of HillsBack2 to 239, 339. This object should be behind the other hill objects. [Setting
depth on the same layer]
HillsBack1 should be positioned at 625, 339 and HillsFront should be positioned at 456, 348.
Create a new layer called Player. [Selecting layer], [locking, visibility of layers]
[Importing player animations: Default, Hit] [25, 56 origin] [448, 240] [Player].
The origin point always appears at the X and Y position of the object. If a rotation is done, the object
rotates around that point and when an image is mirrored or flipped, it is in relation to that point.
---------------------------------------Create a new layer called Gems. [import gem frames] [Name: Gem]
Place this object outside the borders of the layout. We will create all of the gems procedurally, through
the event sheets, so we do not need any gems inside the layout at the beginning of the game.
There needs to be at least 1 instance placed within or outside the borders of each layout where we need
to use that type of object. If there isnt an instance and we try to create a new one, Construct will
generate an error.
Create a new layer called Enemies. [import enemy anims: Appear[34, 38], Fly[36, 51]] [Call Enemy]
As these 2 initial objects will not be used at the beginning, we can destroy them when the layout starts.
Go to the event sheets for this layout and create a folder called OnLoad. [Add an On start of layout
event]. This event only occurs when the layout is loaded.
[Action destroy Gem] [Action destroy Enemy]-----------------------------------------Next, create a new layer called HUD. Set its parallax values to 0, 0. This will keep the objects on this
layout in a constant position, regardless of scrolling. This is perfect for HUD or User Interface elements in
games with an active camera.
We will now import the current wave indicator, which is composed of 4 objects.
[Import wave indicator assets Left Origin: WaveHudBack, WaveHudFill, WaveHudText] [Order of depth]
[Origin] [17, 30] [Text: 107, 31]
[Insert a new Text Object] [Name: WaveText, Pos: 77, 17, Font: Arial 18 bold, Text: 1]
Text objects can hold and display a string of characters, which can be altered. This particular text object
will hold the number of the wave the user has reached.------------------------------------------[import score sprite: 633, 33, ScoreHud] [Text object 597, 18 ScoreText Arial 18 bold, Text: 0]
We have now imported all of the core assets for this game. ---You have learned--This concludes the first Lecture for this Course series. We have now set up the basic objects in the game
and are ready to begin with the programming.
------------------------------------------(Distance diagram)
Distance is a mathematical function which calculates the distance between 2 points represented by X
and Y coordinates.
The player will move faster if the touch location is further away from the Players position and slower if
it is nearby. This can be achieved with 1 action.
Create a constant called MIN_MOVEMENT_SPEED and give it a value of X. This will be the minimum
player movement speed. Create another constant called PLAYER_SPEED_DIST_DIVIDER and give it the
value of X.
Add an action for the Player object -> [Move] [max(MIN_MOVEMENT_SPEED * dt, distance(Player.X,
Player.Y, Touch.X, Touch.Y) / PLAYER_SPEED_DIST_DIVIER * dt)
Angle: angle(Player.X, Player.Y, Touch.X, Touch.Y)
------------------------------------------The way this all works is that the distance between the player and the touch location is divided by a
constant. This makes the players movement speed proportionate to this distance.
Max is a mathematical function which gives the highest of its 2 parameters. The parameters are divided
by a coma and are used as entry inputs for the function. Based on these values, the function calculates
the appropriate return value.
This way, the minimum movement speed is the value of MIN_MOVEMENT_SPEED * dt.
[Angle diagram]
The angle function is a mathematical function which returns the angle between 2 points.
------------------------------------------Create a new constant called MIN_DIST_TO_FACE_DIR and give it a value of 10.
Add another condition nested inside our previous block [abs(Player.X Touch.X) >
MIN_DIST_TO_FACE_DIR]
Abs is a mathematical function which returns the positive value of its parameter. If a value is negative, it
returns the equivalent positive value of it.
This allows us to check if the horizontal distance between the touch location and the player is large
enough to cause the player to turn left or right.
Add another condition here and check [Touch.X < Player.X]. If this condition is true, then the player is to
the right of the touch location and should be facing left. [Set mirrored]
Add an else block and [Set not mirrored], for when the player should face right.
Add an empty block within the touch event. Action [Scroll to Player]
Add an else event on the scope of the PlayerMovedWithKeyboard = 0 condition. [Scroll to Player]
Within the general scope of the player movement group, add 4 empty conditions.
These conditions will check if the players position is outside the imaginary borders of the game map.
If the X or Y value is lower than the minimum border value, or higher than the maximum border value,
we will set the players position to that value.
[Values X: 23, 831; Y: 63, 357]
//Testing game
This concludes Lecture 2 of this Course. We learned how to program a basic game mechanic, by using
events, conditional control, variables, object properties and mathematical functions.
In the next Lecture, we will introduce parallax backgrounds, functions and arrays.
We will need to create 3 variables, which will hold the starting Y positions of the 3 background sections.
[Hills1StartingY HillsFront, Hills2StartingY HillsBack1, Hills3StartingY HillsBack2]
[Start event set to corresponding values]
We will use a function to reposition these objects. Functions are a set of actions which occur when the
function is called. They can also have parameters and return values. Parameters are the function inputs
and they can be assigned different values whenever the function is called. Return values are values
which the function returns as its output. For example, in the previous Lecture, we used a function called
distance. Its parameters are the coordinates of 2 points: X1, Y1, X2 and Y2. Its return value is the
distance between those points.
To use custom functions, we need to [Import Function object]
[Create a folder called Functions]
[Create a folder inside Functions called Parallax]
[Add function event Parallax]
We will now set the Y position of each hill object.
[HillsFront SetY = Hills1StartingY + (400 Player.Y) / 20]
[HillsBack1 SetY = Hills2StartingY + (400 Player.Y) / 50]
[HillsBack2 SetY = Hills3StartingY + (400 Player.Y) / 100]
As you can see, the Y position of the hills is their base position with an addition proportionate to the
Players position. Each addition is divided by a certain amount for each hill, making them move at
different speeds.
[Call Parallax function in PlayerMovement folder] [Call Parallax function in Start function]
--Test game-As you can see, the game now has parallax scrolling. The HillsFront object moves at the fastest rate,
while the HillsBack2 object moves the slowest.
Next, we will initialize a few arrays which will hold values for the game. -----Array chart----Arrays are a type of objects, which hold a collection of values. Each of the values is accessible using an
index number. The index numbers start at 0.
[Create preloader layer place at top of layouts folder] [Insert array objects: WaveTimerResets,
GemTimerResets, EnemyTimerResets, EnemyExtraSpeeds, MaxGemSpeeds]
Each of these arrays will have 10 values, for each of the waves in the game. We will use these values in
the next few Lectures.
All of the arrays which have Timer in their name will have their values used as timer values. We will use
delta time for timer countdowns, so the values we will assign now will approximately be equal to that
many seconds.
[On start event] [Create folder Array initialization] [Create folders for each of the arrays]
[WaveTimerResets: 0.9, 1.2, 1.5, 2, 2.8, 3.7, 4.5, 5.5, 7, 7.8]
[GemTimerResets: 0.1, 0.05, 0.05, 0.04, 0.034, 0.025, 0.025, 0.015, 0, 0]
[EnemyTimerResets: 10000, 10000, 10000, 1.42, 1.2, 1.1. 0.7, 0.5, 5]
[EnemyExtraSpeeds: 0, 0, 0, 0, 0, 0, 6 = 100, 7 = 100, 8 = 200, 9 = 300]
[MaxGemSpeeds: 120, 140, 155, 180, 180, 180, 210, 210, 245, 300]
[Blank event Go to layout game]
For now, we can have the preloader layout instantly switch to the Game layout, for quick testing.
The game will always need to be started from the Preloader layout, in order to initialize the array values.
This concludes Lecture 3 of this Course. We learned how to create a parallax background, functions and
arrays.
In the next Lecture, we will introduce the progressive wave system.
10
[Else]
This block will occur when the timer drops to less than or equal to 0.
[Condition Wave < 9] ->
[Set Wave to Wave + 1];
[Set WaveText.Text to str(Wave + 1)];
[Set width of BarFront to 179]
[Set TimerNextWave to WaveTimerResets.At(Wave)
If the wave is lower than 9, which represents the final, 10th Wave, the Wave will get increased by 1 and
the Wave Text number will be updated. Str is a function used for converting a number to a string. A
string is a value type comprised of characters and numbers.
We will also set the width of the front wave bar to its Max size, as a new wave will begin.
The Wave timer is also reset to the appropriate value from the WaveTimerResets array. The Wave
variable is increased by 1 before the other actions, because we need to set the timer to the new waves
amount and the wave display text to the new wave index.
[Else block]
This block will occur when the last wave has finished.
We will fill this section later to redirect the user to the end screen.
----------------------[Preloader layout]
[Import WebStorage] WebStorage is an object used for saving and loading data.
[Var TimesFinished, TotalGems, LocalHighscore]
[Local key exists] => [Val = int(WebStorage.LocalValue(key))]
Int is used for converting a string value to a number.
This concludes Lecture 4 of this Course. We learned how to create a progressive wave system, progress
bar and timers. Feel free to practice your new skills by creating things with what you have learned so far.
In the next Lecture, we will introduce procedural gem generation and program the gems.
11
Lecture 5 - Gems
Hello and thank you for watching Lecture 5 of this Construct 2 Course series for Jetpack Rush.
In the previous Lecture we covered the progressive waves system, timers and percentile calculation.
In this Lecture we will add procedural gem generation and program the gems. We will cover instance
variables, rotation, random values and visual effects.
We will use some of the array values from Lecture 2.
[Var TimerNextGem] [Start -> TimerNextGem = 0]
This timer variable will serve as a countdown for creating a new gem.
[Folder NewGems] [Blank Subevent -> TimerNextGem > 0 ?] -> [Set TimerNextGem to TNG dt]
[else block] This block will occur when the timer has reached 0.
[Gem instance variables: RotationDirection = 1, Speed, RotSpeed, Collected = 0, Scale = 1]
Instance variables are variables which belong to an individual instance of an object. Different instances
can have different values for these variables.
We will create a function for creating new gems. Functions are useful for tasks which need to be
repeated and for managing larger chunks of events and actions.
[Function Folder NewGem] [on NewGem]
[Create object Gem on Layer Gem at ViewportLeft(0) + random(1) * 720, 20]
This will create a new Gem instance. The X position will have a random value between ViewportLeft(0)
and ViewportLeft(0) + 720. ViewPortLeft(0) is the position of the left corner of the screen, relative to the
camera. Its parameter determines which layer we need. In this case any of the layers, other than the
HUD one will do. By using this function, we can make sure that the gems spawn in the players field of
view.
Random is a mathematical function which returns a random number between 0 and its parameter.
[Gem] [Set opacity to 0]
An objects opacity value determines its transparency. At 0, the object is invisible and at 100 it is fully
visible and non-transparent.
Next, we need to make gems have variety. Each gem will be assigned a random color, starting angle,
rotation direction, rotation speed and falling speed.
[Set animation frame to round(random(4))]
12
This action will set the gems animation frame to anywhere between 0 and 4. Animation frame indexes
start with 0 and since the gems have 5 frames, the last frame will be indexed as 4.
Round is a mathematical function which returns the nearest rounded value of its parameter. For
example, if we have 3.7, the rounded value of this number would be 4.
[Stop animation] We dont want the gems animation to be playing, as we only need individual frames.
[Set angle to random(360)] This will set the gems initial rotation to anywhere between 0 and 360
degrees.
[Set RotationDirection to -1 + round(random(1)) * 2]
This action will set RotationDirection to either -1 or 1. The way it works is that we assign the rounded
value of random(1) multiplied by 2 to the number -1. The rounded value is either 0 or 1. If it is 0, we get
-1 and if it is 1, 2 gets assigned to -1 and we get 1.
[Constant GEM_MAX_ROT_SPEED = 220]
[Set RotSpeed to GEM_MAX_ROT_SPEED * max(random(1), 0.25)]
This will set the gems rotation speed to a value between 0.25 times the max rotation speed and the
max rotation speed.
-----------------------------------------[Constant MIN_GEM_SPEED = 80]
[Set Speed to
max(MIN_GEM_SPEED + Wave * 5, MaxGemSpeeds.At(Wave) * max(0.2, random(1))) ]
The speed of the gem is set to a value of the array MaxGemSpeeds based on the current wave,
multiplied by a random number between 0.2 and 1. If this value is lower than the first parameter, it is
set to MIN_GEM_SPEED plus the current wave multiplied by 5.
[Back at else block] -> [random(1) <= 0.5 Or Wave = 9?] -> [Call NewItem]; [Set TimerNextGem=arr(w)]
This will ensure that a new gem is created whenever the timer has finished counting down and we get a
random value lower than or equal to 5, or if the player is on the last wave.
After the gem is created, we also reset the gem timer.
Next, we need to program the gem behaviours.
[Folder GemsLoop]
[For each Gem]
13
A for each block is a type of control block, which loops through every instance of a certain type of
object. This entire cycle is done during 1 frame of the game. This is very useful for managing multiple
instances of an object.
[Set angle to Gem.Angle + Gem.RotSpeed * Gem.RotationDirection * dt]
This will cause the gems angle to increase or decrease by its rotational speed, based on its
RotationDirection variable. We multiply this value by deltatime to make it framerate independent.
[Set Y to Gem.Y + Gem.Speed * dt] This will cause the gem to move downwards on the vertical axis.
[If Y >= 430 ?] => [Destroy] This will destroy a gem instance if it has passed the entire screen. It is an
important practice to destroy or recycle objects which are not used anymore.
[Game layout -> Var Score; Start -> Set Score to 0] [Var GemsCollected; Set to 0]
[Function folder Increase Score] [On IncreaseScore]
=> [Set Score to Score + 100] ; [Score text = str(score)] ; [GemsCollected += 1]
[Gem Scope -> Collected = 0 ?] This block will occur if the player has not yet collected the current gem.
[Opacity < 100 ?] -> [Set opacity to Gem.Opacity + 100 * dt]
Each gem start out at 0 Opacity. This action cause the gem to become fully visible over a short period of
time.
[Player is animation Default playing] This checks if the players current animation is the default one.
The player should not be able to collect gems when hit by an enemy.
[On collision with player] This event triggers when a gem collides with the Player
[Set collected to 1] ; [Call IncreaseScore] ; [TotalGems += 1]
[Else on Collected = 0 scope] The else block will occur if the gem has been collected by the player. This
block of actions will make the gem disappear with a programmed animation.
[Set Scale to Gem.Scale + 3.3 * dt] [Set scale to Gem.Scale]
This will increase the gems size by a certain value on each frame. The default Scale value in Construct 2
can not be accessed directly, so we need to have a helper instance variable, which we called Scale.
[Opacity > 10?] Set opacity to Gem.Opacity 200 * dt] [Else] [Destroy];
This will cause the gem to slowly disappear and destroy it when it is nearly invisible. These 2 effects
combine for an interesting disappearance animation.
[Waves block -> Waves < 9 block] [ For 0 to 7 + Wave ] => [New item]
14
A for loop is a cycle of repeated actions. The number of cycles depends on the start and end index. This
block will cause several gems to spawn at the beginning of each wave.
[Test]
This concludes Lecture 5 of this Course. We learned how to create a procedural object generator,
randomize objects and use visual effects.
In the next Lecture, we will add the enemies.
15
Lecture 6 - Enemies
Hello and thank you for watching Lecture 6 of this Construct 2 Course series for Jetpack Rush.
In the previous Lecture we covered procedural gem generation, gem behaviors, randomization and
visual effects.
In this Lecture we will cover the enemy generation, behaviors and player hit state.
The enemies will appear after wave 3, at random locations and certain intervals. After a short
appearance animation, they will move aim for the Player and start moving in that direction. If the Player
is hit by an Enemy, they will not be able to collect gems while the Hit animation is playing.
To begin, create a variable called TimerNextEnemy. [Start -> TimerNextEnemy =
EnemyTimerResets.At(Wave)]
This timer will serve as a countdown for creating new enemy instances. Its reset values are the values of
the Array from Lecture 2 called EnemyTimerResets.
[Constant ENEMY_MIN_Y = 100; ENEMY_MAX_Y_ADDITION = 200; MIN_ENEMY_PLAYER_DIST = 200]
The first constant will denote the lowest possible starting position of an enemy. While the second one
will be the maximum addition to this value. The third constant is the minimum distance an enemy can
spawn away from the player.
[NewEnemies Folder] [Wave > 2 ?] Enemies will only spawn after wave 3.
[Enemy.Count = 0 ?] Count gives us the number of instances of a certain object which are
currently present in the layout.
[TimerNextEnemy > 0 ?] => [Set TimerNextEnemy to TimerNextEnemy dt
[Else] => [Create Enemy on layer Enemies at
(ViewportLeft(0) + 80 + random(1) * 560,
ENEMY_MIN_Y + random(1) * ENEMY_MAX_Y_ADDITION)
[TimerNextEnemy = ETR.At(Wave)] [Set animation to Appear] [Set anim speed to 17]
This will set the current animation for the enemy to Appear. The animation speed denotes how fast the
animation will play.
[distance(Player.X, Player.Y, Enemy.X, Enemy.Y) < MIN_ENEMY_PLAYER_DIST ?]
[Player.X ViewportLeft(0) > 360 ?] => [Set X to 50 + ViewportLeft(0)]
[else] => [Set X to 680 + ViewPortRight(0) 50]
16
These 2 blocks occur if the distance between the Enemy and the Player is lower than the minimum
amount specified by the constant value of MIN_ENEMY_PLAYER_DIST. We check to see if the player is
closer to the left or right side of the screen. Based on this, we set the enemys position near the edge of
the opposite side of the screen. This ensures that the enemy is at a good distance from the player.
[Instance variables: FlyingAngle, HitPlayer, FlyingSpeed]
FlyingAngle will be the angle at which the enemy will move after it appears. HitPlayer will be equal to 1
when an enemy hits a player. FlyingSpeed will be the enemys movement speed.
[Folder EnemiesLoop]
[Is Fly playing] => [Move Enemy.FlyingSpeed * dt at angle Enemy.FlyingAngle] ; [Set animation to Fly]
This will cause the enemy to move in the specified direction. We will also set the animation to Fly, so
that it keeps looping.
[HitPlayer = 0 ?]
[On collision with Player event] => [HitPlayer = 1]
This block sets the value of HitPlayer to 1, when an enemy collides with the Player for the first time.
---------------------------------------[Var TimesHit; Start set to 0]
This value will keep track of how many times the player has gotten hit during the current game session.
-------------------------------------------------------[Function folder HitPlayer => On HitPlayer] =>
[Score = max(0, Score 500)] This will cause the score to get deducted by 500, while limiting its lowest
possible value to 0.
[Score text = str(Score)] [Player set anim to Hit] [Speed = 17] [TimersHit += 1]
--Back to collision block
[Call HitPlayer]
[Else on HitPlayer = 0]
This block will occur if the enemy has hit the player. It will disappear over a short period of time.
[Opacity > 10 ?] => [Set opacity to Enemy.Opacity 1000* dt] [else] => [Destroy]
17
[Same scope as Else] [Is outside layout] => [Destroy] This will destroy the enemy if it is outside the
layout, which will always happen if the player is not hit by it.
[Else on main scope] This scope will occur if the enemy is still appearing.
[Animationframe = 7 ?] => [Set anim to Fly]
=> [Set FlyingAngle = ang(e.x, e.y, p.x. p.y)] ;
=>[Set FlyingSpeed to ENEMY_MIN_SPEED + EnemyExtraSpeeds.At(Wave) * max(0.2, random(1)];
This will set the enemys speed variable to the minimum speed with an addition of a random percentage
of the current waves extra speed.
[cos(Enemy.FlyingAngle) < 0 ?] -Cos diagram--This will check if the Enemy is moving
towards the left.
[Set Mirrored]
[Else] => [Set not mirred]
[Delete player anim actions]
[Folder PlayerAnim]
[Is Hit playing ?]
[Animation frame = 18 ?] => Set animation to Default
This will ensure that when the players hit animation finishes playing, the players animation will switch
to the default one.
[Else] => [Set animation to Default] ; [Speed 17];
This concludes Lecture 6 of this Course. We learned how to create another game mechanic and
determine if an angle is facing towards the left or right side on the X axis.
In the next Lecture, we will create the End Screen and pre-game intro.
18
19
[Local var StarsEarned = 0] A local variable only exists within the block it is created in. This is perfect for
temporary variables.
[Folder StarsEarned]
We will now check how the users score compares to the score requirements for each rating.
[Score >= SCORE_REQUIREMENT_3 ?] => [StarsEarned = 3]
[Else Score >= SR2 ?] => [StarsEarned = 2]
[Else Score >= SR1 ?] => [StarsEarned = 1]
[Else] => [StarsEarned = 0]
[Folder StarsInit]
[For 0 to 2] => Create object Star on Layer 2 at STARS_START_X + loopindex * STARS_X_SPACE, STARS_Y
For each new star, the loop index increases by 1. Since we are multiplying this with the STARS_X_SPACE
constant as an addition to the base x position, each next star will appear to the right of the previous
one.
[StarsEarned > loopindex + 1]
This checks if the current star should be filled, depending on its index and the stars the player has
earned.
=> [Set animation to Full]
[else] => [Anim to Blank]
[loopindex = 0] [Set StartedAnimation to 1]
The first star needs to play its animation immediately.
[else] [Stop animation] The rest of the stars should remain invisible.
[Block] => [Set star index to loopindex] ; [Speed 20]
[EndLoop folder] [Every Tick]
[StarsRolling folder]
[StarsRollIndex < 2 ?]
[For each Star]
[Index = StarsRollIndex ?]
20
21
Lecture 8 Menus
Hello and thank you for watching Lecture 8 of this Construct 2 Course series for Jetpack Rush.
In the previous Lecture we covered the end screen and pre-game intro.
In this Lecture we will cover the creation of all game menus.
We will begin by creating and setting up all of the menu layouts.
[Duplicate end screen] [Delete objects] [New event sheet]
[Insert a layer between the 2 layers]
[Import MenuForeground 357, 310] [Import Title 362, 70]
[In top layer]
[Import PlayButton 359, 225] [HelpButton 359, 290] [TrophiesButton 359, 352]
[Import EraseSaveDataButton 58,240] [HighscoresButton 58,291] [CreditsButton 58,339]
[Duplicate end screen Help] [Delete objects] [New event sheet]
[Insert menu button at 363, 367]
[Import HelpScreen 363, 185]
[Duplicate Help Credits] [Delete HelpScreen] [Same event sheet]
[Import Credits 363, 185]
[Duplicate Help Trophies] [Delete HelpScreen] [New event sheet]
[Import TrophiesScreen - 360, 181]
[Duplicate Help Highscores] [Delete HelpScreen] [New event sheet]
[Import Local 366, 254]
[TextObject TxtLocalHs 295, 267 ArialBold 14]
[Preloader events] [Go to Menu instead of Game]
22
[Menu events]
[Folder MenuOnStart] [On Start of layout]
[Stop animation of each button]
Every button will stay on its first animation frame, until it is tapped or clicked. When it is tapped or click,
its animation will switch to the second frame. When the mouse button is released, or the user raises
their finger from the touch screen, all menu buttons will switch to the first animation frame.
[Folder MenuOnTouchStart]
[On any touch start]
[Is touching for each button] => [Set animation frame to 1]
[Folder MenuOnTouchEnd]
[On any touch end]
[Is touching Button && AnimationFrame = 1 for all buttons ?] => Action for each button
[Blank subevent]
This subevent will be used later when adding sounds to the game.
[Blank subevent in main scope] => [Set animationframe to 0 for every button]
[Highscores]
[Trophies]
[Credits]
[Help]
[End]
This concludes Lecture 8 of this Course. We learned how to create menu buttons for the game.
In the next Lecture, we will learn how to add trophies to the game.
23
Lecture 9 Trophies
Hello and thank you for watching Lecture 9 of this Construct 2 Course series for Jetpack Rush.
In the previous Lecture we covered the games menus.
In this Lecture we will cover trophies.
[Trophies layout]
[Import Trophy object]
[Preloader]
[Array TrophiesEarned] This array will have 10 values, each denoting whether a particular trophy has
been earned or not. A value of 0 will indicate that the player has not unlocked the trophy, while a value
of 1 will indicate that the player has done so.
[Start event Folder TrophiesStorageLoad]
--For each trophy:-[Local key TrX exists ?] => [Set TrophiesEarned at X to int(WebStorage.LocalValue(TrX))]
This will assign the saved WebStorage value of Tr0 to the arrays first value, if the value exists.
[else] => [Set value at X to 0] Otherwise, if there is no save data, the arrays value is set to 0.
[Trophies layout]
[Layer Trophies on top]
We will need to procedurally create the 10 trophies in the layout. For the Trophy positions, we will use
constants:
[Const: TROPHIES_Y_SPACE = 132, TROPHIES_Y1 = 100, TROPHIES_X_SPACE = 119, TROPHIES_X1 = 124]
24
25
Next, we will need to check if all Trophies except the last one have been earned. If this is the case, the
player will receive the final trophy.
[Local number LoopContinue = 1]
[for 0 to 9]
[loopindex < 9]
[Trophy earned value at loopindex = 1] => [LoopContinue = 0]
If a trophy other than the last one has not been earned, the loop will be interrupted in the final block.
[else]
[LoopContinue = 1 ?] => [Set TrophyEarnedID to 9]; [Ar[9] = 1] ; [Local key Tr9 = 1]
[Empty block] => [Set Trophy animation frame to TrophyEarnedID + 1]
[Empty block]
This empty block will be used later when we add sounds to the game.
We also need to fade out and destroy any Trophy object that is created.
[Loop -> Folder TrophyPopUp]
[Trophy is visible ?]
[Opacity > 10 ?] => [Opacity -= max(0.2, (100 Trophy.Opacity) * dt); [Op for txt]
[else] => [Set Trophy and TrophyEarned invisible]
Now we need to program each trophys earning conditions.
Lets begin with the first, 6th, 7th and 8th trophies. The conditions for the first 3 are to collect 1, 30 and
195 gems in one game. The condition for the last one is to collect a total of 1500 gems in more game
sessions.
26
27
28
29
Ending:
We learned how to create a full featured casual game which is suitable for commercial use. The game
works on both desktop and mobile devices.
Throughout this tutorial we covered assets, objects, variables, logic, loops, game mechanics, functions,
mathematical calculations and a lot more.
I hope that this Course has helped you in learning Construct 2 game development. Practice your skills
and make great games!
Thank you for watching.
30