How to Build a Sonic Themed Infinite Runner Game in TypeScript With KAPLAY - Part 1/2
In this tutorial, I’ll teach you how to make a simple Sonic themed infinite runner game in TypeScript using the KAPLAY game library. You can play the game here . The final source code for it is available here . In this game, you need to collect as many rings as possible. Jumping on enemies grants you a bonus of 10 rings. Continually jumping on enemies without touching the ground gives you a multiplier on each enemy. The first enemy grants you +10, the second +(10 x 2), the third +(10 x 3), etc… The challenge comes from the game getting progressively faster, making it harder to avoid getting hit by enemies. I really recommend playing the game to have a better idea of what we’re going to build. Since this tutorial is published in parts, I recommend subscribing to not miss out on future releases! I expect that you have basic familiarity with TypeScript or are, at the very least, competent in JavaScript. We’re going to write the game in TypeScript, but it’s going to be very easy TypeScript code. Since we will rarely, if ever, need to write custom types. You should be familiar with Node.js and NPM and have them installed on your machine before following this tutorial. I do not expect you to know KAPLAY. What is KAPLAY? Project Setup Initializing The Canvas Creating Scenes Loading Assets Implementing an Infinite Scrolling Background What are Game Objects and Components in KAPLAY? Implementing Movement With an onUpdate Loop Implementing an Infinite Scrolling Platform Implementing The Sonic Game Object How Animations Work in KAPLAY How Hitboxes Are Created in KAPLAY How to Add Methods to a Game Object Adding Sonic to Our Game Creating a Static Body as The Floor Placing Sonic in The Game Scene KAPLAY is an open source library for making games in JavaScript and TypeScript. Compared to the more popular Phaser JavaScript game framework, its API is a lot simpler making it easier for beginners to pick up. It also offers a lot of premade functionality out of the box. You spend therefore, less time reinventing the wheel. For those familiar with the Godot game engine, you might be accustomed to the concept of nodes which acts as building blocks containing out of the box functionality. KAPLAY has a somewhat similar concept to nodes called components. You can check the official KAPLAY website for more info here . Create a folder called . within using your terminal of choice and run : This command will scaffold a TypeScript project within the existing folder using the popular build tool Vite. Once the command runs, you’ll be presented with the following : Pick “Vanilla”. You’ll be presented with another menu to chose between JavaScript and TypeScript. Select TypeScript. Now let’s install the KAPLAY library. We will install the specific version called v3001.0.16. Run the following : This version is the latest stable version available at the time this tutorial was written. As long as you stick with this specific version, you shouldn’t have issues following this tutorial years into the future. Once installed, take a look at your file in your project’s folder. You’ll notice that KAPLAY was added to your dependencies. When we used the command, Vite created a bunch of files. Make sure that you have the following project structure. Remove everything within the folder as we’re going to write everything from scratch. Once everything is removed in , create two files within. One named and the other . You should have the following project structure. Finally, the last step of our setup is to bring in our game assets. Copy the contents of the folder provided in the game’s final source code available on GitHub. The repo can be accessed by clicking here . After having done so, you should have the following files in your public folder. Now that our setup is complete, we can initialize an HTML canvas in which the game will be rendered. This will be done through KAPLAY by initializing our context which will also allow us to use KAPLAY functions. In , write the following code : Our context is created by calling the function and passing an object containing various options we want to configure for our game. We first set the width and the height of the canvas. We set the property to , allowing our game canvas to scale regardless of the screen size while still retaining its aspect ratio. We set the property to so that KAPLAY functions can only be used via the constant . This will lead to more legible code since you’ll be able to easily detect if a KAPLAY function is in use by noticing . We pass an object to the property to define the action of our game. Since, we want to make the game playable on both desktop and mobile, we set the custom action to be mapped to the space key or the left mouse click. is an arbitrary name and you could have decided on something different. You can also add an arbitrary amount of actions depending on your game’s needs by adding a new property. For example : The property is used to convert touch input to mouse clicks so that the game is playable on mobile. The property is used to toggle on/off KAPLAY’s debug mode. This mode can be accessed on the webpage the game is running on by pressing the key or the keys on a Mac. It will display an fps counter along with the game objects’ hitboxes which makes debugging easier. We will use it later in this tutorial. Here, we’re setting to so that the debug mode is accessible. One thing to note is that by default, debug mode is available so you don’t need use this property initially. The reason I included it here, is that when you ultimately deploy your game, you might not want your players to access this mode. Therefore, setting this property to before deployment is a good idea. Finally, to make the game display sharply regardless of the screen we set the property to correspond to the pixel ratio of the current screen. You’ll notice that not using this property will make the game render slightly blurry on certain screens. We then export the constant containing a reference to the context, so that we can use it elsewhere in our code. Our game will have two scenes. The first, is where the game takes place while the second, is a game over screen displaying the player’s score. In KAPLAY, you can create mulitple scenes using the function. In our file let’s import the KAPLAY context and create our scenes. Here we created two scenes. The function takes, as the first param, the name you want to use to refer to that scene. The second param is a function that will run when the game enters that scene. Finally, we also need to use the function to tell KAPLAY which scene to go to when the game starts. This function is also used to navigate to other scenes when called within a specific scene. We will write the logic for each scene later, now let’s run our project to see if we have correctly initialized our canvas. In your terminal, run the command : When you open the localhost address in your browser, if everything went well, you should see a checkered canvas like shown below. If you try to resize your window, you’ll also notice that the canvas seems to always preserve its aspect ratio. This is exactly what we want so that the game is playable on any device. In let’s load the assets we need for the background and the platforms. This will be a good introduction to how assets are loaded in KAPLAY. Add the following code : Here we use KAPLAY’s function. It takes, as the first param, a string which corresponds to the name you want to use to refer to that specific sprite/image. For the second param, the function expects the path to the asset. Note that we don’t need to add the folder to the path since Vite makes sure to make whatever is in that folder accessible as if it was placed at the root of the project. In our game, the city background must scroll indefinitely. Let’s implement this in our game scene. Add the following code in : Let’s break it down. To achieve an infinite scrolling background, we need need to display the same background image twice. The trick is to reposition the first image behind the second one once it leaves the screen. The second image becomes the first and the first becomes the second. The same logic is repeated indefinitely. I previously wrote a post specific to infinite backgrounds with easy to understand visuals. You can check it out below. In the code above, we first set a constant holding the width of the background image when scaled by 1.5, which corresponds to 1920 x 1.5 = 2880 since the original image has a width of 1920. This is needed so that we can position the second copy right after the first one without leaving any gaps. We will display the background at 1.5 its original scale so that it looks nice within our game. We then set an array containing the two copies. Each copy is created using KAPLAY’s function which creates a game object, one of KAPLAY’s major concepts. A game object represents an entity rendered on the canvas and is composed of components. These components determine various methods and features that it has access to. KAPLAY provides these components out of the box but you can also create custom ones if you wish to (We won’t in this tutorial). The function used to create game objects, takes an array of KAPLAY components. Let’s break down the 4 we use here : comp : Renders a game object as a visible sprite/image. comp : Sets the position of a game object on the canvas using coordinates. In KAPLAY and in many other game libraries, the coordinate increases the further you go right and the coordinate increases the further you go down. The origin is set at the top-left corner of the canvas. comp : Sets the opacity of a game object using a value between 0 and 1. The closer the value is to 0 the more it becomes transparent. comp : Sets the scale of a game object. Is often used alongside the comp to change the sprite/image’s size on the canvas. As you can see, the second copy uses the same components. However, we set the position differently so that it is rendered right behind the first one without leaving any gaps. While creating game objects using the function will render them on the canvas, no movement will occur without an update loop. The update loop runs every frame and is used to update our game’s logic. If your game runs at 60fps, the loop will run 60 times per second. In KAPLAY, we use the function to set our update loop. We first check if the background image second copy’s position is < 0. In that case, we can assume that the first copy is offscreen and therefore, we can safely attempt to move it behind the second copy. This is achieved by setting its position using the KAPLAY method made available due to using the comp when the game object was defined. Using the array method we delete the first element from the array and return it. Finally, we push it back to the array so that the first copy is now placed as the second element of the array making it become the second copy. Another if statement is used to make sure the result of is not before pushing it to the array again. Otherwise, TypeScript will complain and rightly so. Regardless of all of the above, on each iteration of the loop, we move both copies to the left by using the KAPLAY method on the first copy and the method on the second copy to follow the first copy. Both these methods exists because we used the component when creating each respective game object. The method takes two params. The first is for setting the velocity of the game object on the axis while the second sets the velocity on the axis. By setting the velocity to -100 and the velocity to 0, we’re moving only to the left at a velocity of 100 pixels/second. If you’re accustomed to other game engines/frameworks, you might have noticed the absence of (corresponds to the time elapsed since the last frame in our game loop) being used to make our movement frame rate independent. This is because the method takes care of it under the hood. Now, looking at your browser tab (Assuming that you have localhost running) you should see the city background scrolling indefinitely. To make the background less distracting during gameplay, I opted to set its opacity to 0.8 instead of 1. Now, if you go back to your , we can set the background of the whole webpage to be black. This will result in the city background becoming darker and therefore less distracting during gameplay. We provide to the property an array of three elements each representing one of the RGB color channels. Each element’s value can vary between 0 to 255. This is what’s used to represent color. If you check your browser tab, you should notice that the city background is now darker. Implementing an Infinite Scrolling Platform Our game is based on one big illusion. Sonic isn’t actually running. The platform on which Sonic stands isn’t actually moving. The only things moving are the background and the platform’s image which are made to scroll indefinitely. If we were to remove all of the game’s graphics, we would be left with a game object representing the player that can jump up and land on a static floor. Our goal at the moment, is to implement infinite scrolling platforms the same way we did for the city background. The only difference is that the scrolling speed will increase the further the game progresses. In add the following code : We first set a variable that is incremented every second using KAPLAY’s function. This is similar to JavaScript/TypeScript’s function. The first param is for setting the time between each call and the second param is the function that will be called. Similarly to the city background, we create two copies of the platforms’ image so that we can achieve infinite scrolling. corresponds to the final width of the platforms’ image after scaling it twice. This is because we need to make the platforms bigger in our game to make it look good. We use this constant to know where to place the second copy behind the first one without leaving any gaps. The update logic is also similar, the only difference this time is that the function takes the variable as the velocity allowing for it to increase the platforms speed through time. If you run the project, you should notice the platforms scrolling slowly and then gradually increase in speed as time passes. Now that we have our game scene mostly done, we’re ready to work on adding Sonic to our game. Sonic, the rings he must collect and the enemies are all entities. Let’s create a file named in the folder. Then, let’s create a game object that will hold Sonic’s logic. In add the following code. Let’s break it down. We first import the KAPLAY context to be able to use the library’s functions in this file. We then import 2 types. and . As you can see, KAPLAY offers TypeScript types you can use, making development in TypeScript smoother. We then create a function who’s sole purpose is to create and return our Sonic game object. You can think of it as our constructor. We enable the function’s caller to set the position of the game object before it’s created. Positions in KAPLAY are Vec2 s (stands for vector 2). It’s a data structure offered by KAPLAY which has two elements, and . We use the , , , , and components to compose our game object. Note that generally the comp can be passed the and coordinates as two distinct params or be passed a containing both at once. In our code above, we opted for the latter while with our background and platforms game objects, we opted for the former. In the case of the comp, we not only display a but set an animation. You might be wondering where does this “sonic” sprite and “run” anim comes from since we haven’t loaded anything like that at the moment? Indeed, we put the cart before the horse in this case. Let’s add the asset loading logic in . It will be a great opportunity to explain how animations work in KAPLAY. In main.ts, add the following : The function can take an object as an optional third param used for telling KAPLAY how to split an image into individual frames. When an image contains multiple sprites, it is often referred to as a spritesheet. In our case, Sonic’s spritesheet looks like this. We have a total of 16 frames which can be viewed as a grid of 2 rows and 8 columns. The object passed to must first tell KAPLAY how to slice the image using the and properties. corresponds to the number of columns while corresponds to the number of rows. Then, an object can be configured to set the animations we need and tell KAPLAY which animation is composed of which frames in our spritesheet. If we take a look at the definition for the animation, the property holds the number of the starting frame of the anim while the property holds the number of the last frame. When KAPLAY slices the image into individual frames, it assigns a number to each of them starting from 0 and counting from left to right, top to bottom. The property set to makes the anim run indefinitely unless manually stopped while the property is used to set its frame rate. The frame rate values used in the code above are arbitrary. I came up with these values based on what looked good during gameplay after tweaking values. For more details on how animations work in KAPLAY check the post below. Looking back at the components used for creating the Sonic game object in , you’ll notice that the comp takes as the first param the name of the image you want to display while the second param can be used to set the default running animation. We use the comp to increase Sonic’s sprite size by 3. Which is what looked good during gameplay. The comp is very useful because it allows us to easily create a hitbox for our player enabling us to call methods like , , etc… useful for dealing with collisions. In KAPLAY, just passing the comp to the components array is enough to create a box surronding the player’s sprite if the comp is also used. You might need in some cases to configure the position, width and height of the hitbox but in our game, this isn’t necessary at the moment. We will tackle this later. Now that we have used the comp, we can use the comp to set the origin of our game object. By default, game objects are rendered starting from their top-left corner. This might not be very intuitive for game objects representing characters, that’s why I like using the comp in those cases to set the center as the origin instead. Finally, the comp is used to give the game object a physics body allowing them to be affected by gravity. Using the comp is crucial since it will give us access to the method which allows the game object to jump. In our comp usage we set the game object’s jump force to be 1700. This is an arbitrary value which I arrived at after extensive testing during gameplay. I explained earlier that a game object is composed of components. However, the function which takes in an array of components can also be passed, to that same array, a JS object that you can use to set custom properties and methods for the resulting game object. We have an object containing two custom methods. The first one is used to set the player controls while the second is used to set what happens when Sonic hits the ground after jumping. In these methods, we can use the keyword, to access the sonic game object. In TypeScript, we need to specify what is. This is done by creating a param and typing it using the type definition imported from KAPLAY. When TypeScript is compiled to vanilla JS, this param will be removed. Taking a closer look at our custom function, we can see that we call an KAPLAY function. As the name implies, this is used for handling when a specific button is pressed. It takes, as the first param, the name of the “button” you want to listen on. The second param is the function that will fire when that “button” is clicked. If you remember, the “jump” “button” was defined in our KAPLAY context. This is where you need to define all the “buttons” you need for your game. Within our we check if the player is on top of a static game object using the method which is available because Sonic has a comp. At the moment, we haven’t defined any static game objects but we will create one later. When the player is indeed grounded, we can set the jump animation to play, make the player jump with the method and finally play a jump sound using KAPLAY’s function which is used to play audio. Unfortunately, it’s very easy to confuse the method which is used on a game object for playing animations VS the function which is used for sound. By the way, we need to load the jump sound in for it to work here. Add the following : The reason why we make sure the player is grounded before allowing any jump logic to run is so that the player can’t jump indefinitely making them able to fly away. Our second custom method is used to set event logic. In KAPLAY, when a game object has the component, you have access to the event method. That method runs a function every time the player hits the ground (meaning collides on top of a static game object). When the player jumps, the jump animation plays indefinitely. We want to switch back to the run animation as soon as the player lands back. The code above achieves this. To reiterate, and are custom methods we decided to create on our Sonic game object. They could have been named differently. We could have decided to only have one method that does all of the required logic. This is up to you when making your own KAPLAY games. Let’s create a floor on which to place Sonic. Add the following code in main.ts : To create a static game object, you simply need to create a game object with an and a component. Within the comp, set the property to . We use the comp to create a rectangular shape and we used the comp set to 0 to make it invisible. We also don’t assign the game object to a constant since we don’t need a reference. If you look at the webpage where the game is running (assuming your project is running), you will see that nothing has changed. However, if you activate the debug mode by pressing the key (or keys on a Mac), you’ll see an outline representing the hitbox game object we just created. For fun, you can try to put the opacity back to 1 and you’ll see a white rectangle at the bottom of the canvas. Placing Sonic in The Game Scene In , add the following : We call and set a position using the KAPLAY function, assign the result to a constant called Sonic which enables us to call our custom methods and , enabling our core player game logic. Everything should work now, but wait! Why is Sonic hanging in the air? That’s because we haven’t set our game’s gravity. In KAPLAY, gravity is set per scene using the function and passing to it a number determining how strong it will be. Add the following code in our “game” scene definition : I came up with 3100 after trial and error. You need to test during gameplay to see if the jump is floaty or not and that’s how I came up with this value. Now, if you run the project. You should see Sonic initially fall on the platforms and immediately start running. You can now jump and when you do, Sonic should curl into a ball and you should hear a jump sound. However, as soon as he hits the ground, the run animation should be the one playing. Up to this point we covered a lot of KAPLAY specific concepts and we made quite a bit of progress on our Sonic game. However, there’s still work to do. In the next part of the tutorial we will : Add rings for Sonic to collect. Implement a scoring system. Add Motobug enemies that Sonic can jump on for more rings. Implement a combo system allowing Sonic to earn extra rings by continuously jumping on Motobugs before hitting the ground again. Update : Part 2 is now available! In this tutorial, I’ll teach you how to make a simple Sonic themed infinite runner game in TypeScript using the KAPLAY game library. You can play the game here . The final source code for it is available here . In this game, you need to collect as many rings as possible. Jumping on enemies grants you a bonus of 10 rings. Continually jumping on enemies without touching the ground gives you a multiplier on each enemy. The first enemy grants you +10, the second +(10 x 2), the third +(10 x 3), etc… The challenge comes from the game getting progressively faster, making it harder to avoid getting hit by enemies. I really recommend playing the game to have a better idea of what we’re going to build. Since this tutorial is published in parts, I recommend subscribing to not miss out on future releases! Prerequisites I expect that you have basic familiarity with TypeScript or are, at the very least, competent in JavaScript. We’re going to write the game in TypeScript, but it’s going to be very easy TypeScript code. Since we will rarely, if ever, need to write custom types. You should be familiar with Node.js and NPM and have them installed on your machine before following this tutorial. I do not expect you to know KAPLAY. Table of Contents What is KAPLAY? Project Setup Initializing The Canvas Creating Scenes Loading Assets Implementing an Infinite Scrolling Background What are Game Objects and Components in KAPLAY? Implementing Movement With an onUpdate Loop Implementing an Infinite Scrolling Platform Implementing The Sonic Game Object How Animations Work in KAPLAY How Hitboxes Are Created in KAPLAY How to Add Methods to a Game Object Adding Sonic to Our Game Creating a Static Body as The Floor Placing Sonic in The Game Scene If you try to resize your window, you’ll also notice that the canvas seems to always preserve its aspect ratio. This is exactly what we want so that the game is playable on any device. Loading Assets In let’s load the assets we need for the background and the platforms. This will be a good introduction to how assets are loaded in KAPLAY. Add the following code : Here we use KAPLAY’s function. It takes, as the first param, a string which corresponds to the name you want to use to refer to that specific sprite/image. For the second param, the function expects the path to the asset. Note that we don’t need to add the folder to the path since Vite makes sure to make whatever is in that folder accessible as if it was placed at the root of the project. Implementing an Infinite Scrolling Background In our game, the city background must scroll indefinitely. Let’s implement this in our game scene. Add the following code in : Let’s break it down. To achieve an infinite scrolling background, we need need to display the same background image twice. The trick is to reposition the first image behind the second one once it leaves the screen. The second image becomes the first and the first becomes the second. The same logic is repeated indefinitely. I previously wrote a post specific to infinite backgrounds with easy to understand visuals. You can check it out below. In the code above, we first set a constant holding the width of the background image when scaled by 1.5, which corresponds to 1920 x 1.5 = 2880 since the original image has a width of 1920. This is needed so that we can position the second copy right after the first one without leaving any gaps. We will display the background at 1.5 its original scale so that it looks nice within our game. We then set an array containing the two copies. Each copy is created using KAPLAY’s function which creates a game object, one of KAPLAY’s major concepts. What are Game Objects and Components in KAPLAY? A game object represents an entity rendered on the canvas and is composed of components. These components determine various methods and features that it has access to. KAPLAY provides these components out of the box but you can also create custom ones if you wish to (We won’t in this tutorial). The function used to create game objects, takes an array of KAPLAY components. Let’s break down the 4 we use here : comp : Renders a game object as a visible sprite/image. comp : Sets the position of a game object on the canvas using coordinates. In KAPLAY and in many other game libraries, the coordinate increases the further you go right and the coordinate increases the further you go down. The origin is set at the top-left corner of the canvas. comp : Sets the opacity of a game object using a value between 0 and 1. The closer the value is to 0 the more it becomes transparent. comp : Sets the scale of a game object. Is often used alongside the comp to change the sprite/image’s size on the canvas. Implementing an Infinite Scrolling Platform Our game is based on one big illusion. Sonic isn’t actually running. The platform on which Sonic stands isn’t actually moving. The only things moving are the background and the platform’s image which are made to scroll indefinitely. If we were to remove all of the game’s graphics, we would be left with a game object representing the player that can jump up and land on a static floor. Our goal at the moment, is to implement infinite scrolling platforms the same way we did for the city background. The only difference is that the scrolling speed will increase the further the game progresses. In add the following code : We first set a variable that is incremented every second using KAPLAY’s function. This is similar to JavaScript/TypeScript’s function. The first param is for setting the time between each call and the second param is the function that will be called. Similarly to the city background, we create two copies of the platforms’ image so that we can achieve infinite scrolling. corresponds to the final width of the platforms’ image after scaling it twice. This is because we need to make the platforms bigger in our game to make it look good. We use this constant to know where to place the second copy behind the first one without leaving any gaps. The update logic is also similar, the only difference this time is that the function takes the variable as the velocity allowing for it to increase the platforms speed through time. If you run the project, you should notice the platforms scrolling slowly and then gradually increase in speed as time passes. Implementing The Sonic Game Object Now that we have our game scene mostly done, we’re ready to work on adding Sonic to our game. Sonic, the rings he must collect and the enemies are all entities. Let’s create a file named in the folder. Then, let’s create a game object that will hold Sonic’s logic. In add the following code. Let’s break it down. We first import the KAPLAY context to be able to use the library’s functions in this file. We then import 2 types. and . As you can see, KAPLAY offers TypeScript types you can use, making development in TypeScript smoother. We then create a function who’s sole purpose is to create and return our Sonic game object. You can think of it as our constructor. We enable the function’s caller to set the position of the game object before it’s created. Positions in KAPLAY are Vec2 s (stands for vector 2). It’s a data structure offered by KAPLAY which has two elements, and . We use the , , , , and components to compose our game object. Note that generally the comp can be passed the and coordinates as two distinct params or be passed a containing both at once. In our code above, we opted for the latter while with our background and platforms game objects, we opted for the former. In the case of the comp, we not only display a but set an animation. You might be wondering where does this “sonic” sprite and “run” anim comes from since we haven’t loaded anything like that at the moment? Indeed, we put the cart before the horse in this case. Let’s add the asset loading logic in . It will be a great opportunity to explain how animations work in KAPLAY. How Animations Work in KAPLAY In main.ts, add the following : The function can take an object as an optional third param used for telling KAPLAY how to split an image into individual frames. When an image contains multiple sprites, it is often referred to as a spritesheet. In our case, Sonic’s spritesheet looks like this. We have a total of 16 frames which can be viewed as a grid of 2 rows and 8 columns. The object passed to must first tell KAPLAY how to slice the image using the and properties. corresponds to the number of columns while corresponds to the number of rows. Then, an object can be configured to set the animations we need and tell KAPLAY which animation is composed of which frames in our spritesheet. If we take a look at the definition for the animation, the property holds the number of the starting frame of the anim while the property holds the number of the last frame. When KAPLAY slices the image into individual frames, it assigns a number to each of them starting from 0 and counting from left to right, top to bottom. The property set to makes the anim run indefinitely unless manually stopped while the property is used to set its frame rate. The frame rate values used in the code above are arbitrary. I came up with these values based on what looked good during gameplay after tweaking values. For more details on how animations work in KAPLAY check the post below. Looking back at the components used for creating the Sonic game object in , you’ll notice that the comp takes as the first param the name of the image you want to display while the second param can be used to set the default running animation. We use the comp to increase Sonic’s sprite size by 3. Which is what looked good during gameplay. How Hitboxes Are Created in KAPLAY The comp is very useful because it allows us to easily create a hitbox for our player enabling us to call methods like , , etc… useful for dealing with collisions. In KAPLAY, just passing the comp to the components array is enough to create a box surronding the player’s sprite if the comp is also used. You might need in some cases to configure the position, width and height of the hitbox but in our game, this isn’t necessary at the moment. We will tackle this later. Now that we have used the comp, we can use the comp to set the origin of our game object. By default, game objects are rendered starting from their top-left corner. This might not be very intuitive for game objects representing characters, that’s why I like using the comp in those cases to set the center as the origin instead. Finally, the comp is used to give the game object a physics body allowing them to be affected by gravity. Using the comp is crucial since it will give us access to the method which allows the game object to jump. In our comp usage we set the game object’s jump force to be 1700. This is an arbitrary value which I arrived at after extensive testing during gameplay. How to Add Methods to a Game Object I explained earlier that a game object is composed of components. However, the function which takes in an array of components can also be passed, to that same array, a JS object that you can use to set custom properties and methods for the resulting game object. We have an object containing two custom methods. The first one is used to set the player controls while the second is used to set what happens when Sonic hits the ground after jumping. In these methods, we can use the keyword, to access the sonic game object. In TypeScript, we need to specify what is. This is done by creating a param and typing it using the type definition imported from KAPLAY. When TypeScript is compiled to vanilla JS, this param will be removed. Taking a closer look at our custom function, we can see that we call an KAPLAY function. As the name implies, this is used for handling when a specific button is pressed. It takes, as the first param, the name of the “button” you want to listen on. The second param is the function that will fire when that “button” is clicked. If you remember, the “jump” “button” was defined in our KAPLAY context. This is where you need to define all the “buttons” you need for your game. Within our we check if the player is on top of a static game object using the method which is available because Sonic has a comp. At the moment, we haven’t defined any static game objects but we will create one later. When the player is indeed grounded, we can set the jump animation to play, make the player jump with the method and finally play a jump sound using KAPLAY’s function which is used to play audio. Unfortunately, it’s very easy to confuse the method which is used on a game object for playing animations VS the function which is used for sound. By the way, we need to load the jump sound in for it to work here. Add the following : The reason why we make sure the player is grounded before allowing any jump logic to run is so that the player can’t jump indefinitely making them able to fly away. Our second custom method is used to set event logic. In KAPLAY, when a game object has the component, you have access to the event method. That method runs a function every time the player hits the ground (meaning collides on top of a static game object). When the player jumps, the jump animation plays indefinitely. We want to switch back to the run animation as soon as the player lands back. The code above achieves this. To reiterate, and are custom methods we decided to create on our Sonic game object. They could have been named differently. We could have decided to only have one method that does all of the required logic. This is up to you when making your own KAPLAY games. Adding Sonic to Our Game Let’s create a floor on which to place Sonic. Creating a Static Body as The Floor Add the following code in main.ts : To create a static game object, you simply need to create a game object with an and a component. Within the comp, set the property to . We use the comp to create a rectangular shape and we used the comp set to 0 to make it invisible. We also don’t assign the game object to a constant since we don’t need a reference. If you look at the webpage where the game is running (assuming your project is running), you will see that nothing has changed. However, if you activate the debug mode by pressing the key (or keys on a Mac), you’ll see an outline representing the hitbox game object we just created. For fun, you can try to put the opacity back to 1 and you’ll see a white rectangle at the bottom of the canvas. Placing Sonic in The Game Scene In , add the following : We call and set a position using the KAPLAY function, assign the result to a constant called Sonic which enables us to call our custom methods and , enabling our core player game logic. Everything should work now, but wait! Why is Sonic hanging in the air? That’s because we haven’t set our game’s gravity. In KAPLAY, gravity is set per scene using the function and passing to it a number determining how strong it will be. Add the following code in our “game” scene definition : I came up with 3100 after trial and error. You need to test during gameplay to see if the jump is floaty or not and that’s how I came up with this value. Now, if you run the project. You should see Sonic initially fall on the platforms and immediately start running. You can now jump and when you do, Sonic should curl into a ball and you should hear a jump sound. However, as soon as he hits the ground, the run animation should be the one playing. Conclusion Up to this point we covered a lot of KAPLAY specific concepts and we made quite a bit of progress on our Sonic game. However, there’s still work to do. In the next part of the tutorial we will : Add rings for Sonic to collect. Implement a scoring system. Add Motobug enemies that Sonic can jump on for more rings. Implement a combo system allowing Sonic to earn extra rings by continuously jumping on Motobugs before hitting the ground again.