Transcript for:
Tutorial on Building a Metroidvania Style Game with JavaScript and KaboomJS

learn to use JavaScript and Kaboom JS to build a metrov Vania Style game in this tutorial from JS Legend Dev you'll learn everything from setting up your development environment to implementing complex game mechanics like enemy Ai and boss battles you'll learn how to load assets Define scenes manage game objects and more all while creating a dynamic and engaging Game World by the end of this course you'll have the skills and knowledge to bring your own metrov Vania game to life and deploy it for others to enjoy hi everyone welcome to this new tutorial today we're going to build a Metroid Venia Style game so Metroid Venia is a style of game where mostly there are they're usually Platformers and uh the difference between a normal platformer and a Metroid Venia Style game is that in a Metroid Vania you don't have levels you explore one big map and some parts of the map are not are cut off or not available to you if you don't have certain abilities so the whole point is to explore the map unlock new abilities or find new items as you explore and this will unlock certain parts of the map that you weren't able to access before and here is the simple version of that so here we have a little robot with a sword attack and for now we cannot go to the right uh because we don't have the double jump ability so as you explore the game so here is a health pack uh as you explore the game for example I go here the goal of the game is to exit find the exit which is uh so basically if I start the game from scratch you have this um escape the factory use the arrow kease to move X to jump and Z to attack so here if I explore you can see for example the second room and there's something down below we want to see what it what it is so I'm going to go to uh continue my exploration and here we have drones so drones uh will follow you and self-destruct so I'm going to teach you how to code that as well so here I have so just to show you a full overview of the game before we start building it so here's the layout Etc and now here I have I don't cannot double jump here if I do I'm going to die so now let's beat the boss which is going to allow us to unlock this ability so the boss we're going to build uh beat is this one so as you enter the boss room you cannot exit out of it so so that's a bit like the souls games and then this little boss has a frame a flamethrower and uh basically the way is we just avoid his flames and we hit it so I'm just going to do this this very quick quickly and then after that going to see that we're going to unlock a a power up which is you unlocked a new ability you can now double jump and then here I can go here and this was previously unaccessible it's a shortcut and I I should not die here I just died anyway uh the game will save uh so you still have the double jump ability and now that we have unlocked this we can go go back to where we couldn't proceed and then I'm just going to beat this one and here get access to the second room and as you see like the camera is dynamic uh it will follow uh when when the player uh passes through certain things it's going to follow I just died here it's going to follow the player or not not follow but just change angles and positions to better show the rest of the level and that's the game now to draw this level to so actually to make this game I'm going to use Kaboom which is a library for making games in JavaScript it's very easy to use and yep so I'm going to teach it to you as well so the prerequisite for this course is or this tutorial is that you know at least the basics of JavaScript we're also going to use til which is this program I have here to draw our level layout so because we're not using a traditional game engine uh that means that we don't have access to a level editor like in gdo and that means we need to use an external program for that otherwise it would be too tedious to draw the level layout in code so here tiled is a nice program that fills this Gap so I'm going to teach you how to how it works basically but I will not go into too much details so I'm going to teach you how to how this map that I made works so the these two rooms uh what are all these colliders Etc but I will not like I did in previous tutorials redraw the map from scratch and show you how it's done uh because it's going to be too tedious to replicate the exact same layout so consider those these Maps as assets they're going to be Json file in the description that you can download and you basically going to import them into your game however I have written a guide so I'm going to spend some time to explain how to um draw maps in tiles in til at a higher level but I'm not going to do go into the needy greedy details for this specific project however if you want to have a written written content I have written recently a blog post on how to use child with Kaboom JS so here is my substack it's where I write content um this is where I I do written tutorials so my YouTube channel is really good fit for Project based tutorials but sometimes you just want to know how to do a specific thing or you want to reference something that you found in my tutorials and referencing a video a specific part of a video is usually tedious so having a blog post nicely written like this is uh how I do things to like I I use this as well for myself so so I can reference back uh when I need it how to do uh how to import uh maps from til how to use til and then use them in kabong so if you're interested uh give me a subscribe here to not miss on future written content so the link will be in the description all right so now for this setup I'm going to use vs code for this project and I recommend that you also do uh because we're going to use the go the live server extension which can be found in the extensions Marketplace live server and then install it here uh it's written uninstalled uh because I've already installed it and this allows us to start a local server for a project and it's very easy uh however if you you have your own setup feel free to use it you can start servers in other ways one one example would be through python uh you can start a local HTTP server with it so let's jump right into the project so I have my workspace here I created a folder I called it Metro Vania tutorial but feel free to call it however you'd like all right so now I'm going to create an assets folder and this is where we're going to put the assets for our game so the ass assets are more mostly coming from an asset pack on .io so I'm going to provide the link for that in the description uh however there are two sprad sheets within that I'm going to replace with my own and those two will be in the description as well the reason I'm replacing them with my own is I just reformatted them so they fit better and can be imported in Kaboom easily all right so let's create an assets folder here if not already I'm going to also create another one which is going to be the lip folder which is where I'm going to put the version of KaBoom so for this tutorial I'm not going to use nodejs I'm just going to use the simplest setup you can for uh Kaboom which is just taking a the GS file and then importing it into your project using native JavaScript modules so if you're if you want to use V for example or or a nodejs based uh setup feel free to do so and if you're not sure how to do that look at my previous tutorial where I made a 2d developer portfolio this is where I used vit and uh npm so you can just take the setup portion and then follow along the rest for this tutorial all right so I have the lip folder here I'm going to put later on the the library here that I'm going to download this also will be linked in the description I'm going to create a Maps folder which is where we're going to put the maps so the two Json files that I I show I've shown you earlier here then I'm going to have the source folder which is going to contain most of our code an index.html which is important because it's the entry point of our program and that's basically it so for the index.html I'm just going to write the code uh start writing the code so I'm going to write the HTML tag a body tag it's not very important for a game to have this uh markup to have like really deep markup uh like uh a lot of boiler plate Etc so I'm just going to use a simple markup HTML body tag and then within we import our script from The Source folder so I'm going to do dot source. main it's important to use a relative path because if you're going to put this on h. it it uses relative path uh paths to be able to load your game so that's why I use a DOT here instead of just writing the absolute path uh this file does not yet exist so let's create it so main.js and then here in index.html we need to also add the type of it to be module the reason we're doing this is because we can without this we cannot use the import syntax we cannot use import X from y this is called native JavaScript uh modules I think all right so now that we have this let's um save everything all right and then I'm going to import the files now so let's see if this work can I just drag and drop can I cannot okay so I'm GNA have to do this differently so I'm going to drag and drop the versions so here what I like to do when I'm not using npm is just to have a a simple text text version that tells you where to get the library and the version of it and here the MGs file is what you need to install uh to download so the way you do that is you go to this link it's going to be in the description hopefully and then you're going to be brought to a page with random code so let me just open it up uh it's not random code actually it's the the code for the library what you do here is you right click and you click save page as and it's going to save it as in Kaboom mg GS file then put it that put that file into your project all right now for the assets I'm going to do the same thing so I'm just going to import everything so uh we're also going to have some Sounds by the way uh those sounds are free uh of use but there is one sound that I put the credits of so yeah every for the sounds a link will be in the description as well so the two Sprites the two Sprite sheets that I've personally modified myself is the burner which is the boss and the u.png which is the player I had to tweak uh the jump animation and uh the placement of the jump animation and for the burner I had to Center everything otherwise that the the character that the spreadsheet wouldn't uh be displayed properly the animation were weird yeah so it's a bit hard a bit hard to explain what the issue was but if you have the original and you try with the original you're going to soon realize the issue we also have this glyph ms. ttf which is the font we're going to use this is provided by the asset pack so everything here is provided by the asset pack in the description but as I said for burner and u.png replace these with my custom ones all right so here you have the sounds Etc okay now let's go to the maps and let's import them as well so there's actually there's four things so I need to explain something here so here room. one. Json is the the file uh basically with all the data needed to draw the map this is from til there's also room 1.png and room 2.png and the reason we have room one and room two here is because in Kaboom Jazz strangely enough it is more performant to just go to tille and then export the map as an image and then just uh it would be one single Sprite and display it as a single Sprite rather than drawing every tile as like as in your logic from the Sprite sheet that's why I have exported both a room one and room two as pgs and the reason and what the Json is for now is just to know where the colliders are so that's the the use for that so usually in game development libraries you would just only need the Json file and you can do that in Kaboom JS you just need that and not the the you wouldn't need the other ones but it would be less performant because the way you would draw is you would take your original asset so your Sprite sheet your tile set here and then draw from there but for some reason in Kaboom Jaz if you do that it's less performant than just having baking all your um your world your map into a single image and then just displaying it so with pixel art it isn't that big of an image but you also need to think um of the network considerations so since this this is web game uh maybe you don't want people to have to download two bigger images and if you could only use um a single small uh image it would be nice better in terms of like uh loading but I think with games people are more uh forgiving when it comes to these stuff rather than a normal website you shouldn't exaggerate but I think that's the usually the case you're usually more willing to wait a bit before playing the game rather than if it were a website that you need to use immediately all right uh now that we have that um I think we can get started with importing Kaboom into our project the way we're going to do this is I'm going to use a file I'm going to create a new file I'm going to call it the Kaboom loader. JS this file is going to to be the one importing Kaboom because okay so I'm just going to do it and then you're going to see why uh it's going to make more sense like that so what we're going to do here is I'm going to write an import statement I'm going to import Kaboom from and the nice thing with JavaScript modules is that you can just do um lib you can import the MGs file immediately like that without any script Tes so once you do this uh so just the path is from the lip folder so here we are in the source folder having dot dot that means we go up to the root of the project and then we go back in lib uh the lib folder and then Kaboom MJS and then here I'm going to have um a constant I'm going to call it the scale I going to scale probably the game two times I'm not sure actually if I use yeah yeah this is going to be a fix around an issue that's going to come up later so for now just uh have this constant up as the scaling and then here export const K is going to be the Kaboom context and the way you initialize the Kaboom canvas is by calling the Kaboom function and then passing it an object which is which can contains a bunch of properties you want uh for for example I can specify the width of my game I want it to be 6 uh 40 uh and the height I want it to be 360 and I want it to have the letter box option to being true so here if for now nothing happens but uh I also need to for I forgot something very important Global should be false so Global the reason is by default if you import Kaboom you just can use start using the Kaboom functions uh immediately but what I want what I prefer to do is to store the Kaboom context in a constant and and uh here K and all Kaboom function will have to be prefixed by this K Dot and then you call the Kaboom function you this makes the code cleaner uh in my opinion so now uh yep so now if I go to main.js and import the um yes so you need yeah so I'm I'm going to import k so import K from Kaboom loader because we're using JavaScript modules and not using an npm based workflow we need to specify the file extensions otherwise it's not going to work so kabum loader loader. JS and then here just by doing this if I click on the go live button which is at the bottom right of vs code you should be able to see the canvas being initialized now one thing I want to add for this project is in the index.html um I'm going to add a bit of styling I want the background to be black basically I think it it's going to be better than white so body and then I add the background not necessar color just background and then black and now if I go back and look at the result you have a black bar so it we can we nicely like see the difference between the canvas and the rest now there's one thing I wanted to do before and the reason I had the scale here is because I want the canvas to be scaled as well so this is a shorthand in JavaScript when you have a property that is the same name of a variable you don't have to do scale not scale you can just use scale like that as a short hand now and also I need to multiply by the scale here the reason I'm doing this is that in kabas uh the pixels certain pix pixs can um it's a bit hard to explain so I'm going to make a schematic XC all right so we have excal draw maybe dark mode here as well uh do we have dark mode all right so in Kaboom Jaz and not necessarily only in that but I've noticed it in Kaboom is that when you have pixel art so imagine this is one pixel okay and imagine that we have a drawing like that with a multiple pixels so let me just zoom in uh it's not going to be perfect here okay we have the this um letter I guess so yeah so we have this letter Let's see we have zero imagine this is a Sprite the issue is that in Kaboom some times a pixel will take more space than a pixel and you will have like a bit of padding like that a bit of padding like that and that means that this pixel and this pixel in theory like in the Sprite art should be the same size but somehow it's not the case and this issue is not entirely resolved so if I go back to the original game uh is it working okay I need to refresh the G sorry um so maybe you can notice it uh so this is with a fix even with a fix there's an issue but if you look here um here you see uh you're probably not going to notice it but this pixel right here ah I think it's better it's more visible here so maybe go full screen this pixel is not the same size as this pixel even though they're supposed to be the same and this is something a random during padding issue that Kaboom adds some padding and this caused this and this is the less worst variant of it so this is bar barely noticeable and it's barely noticeable because of the fix I I the hack I used here but if uh yeah so but the hack is basically you set a scale value which can be two here you multiply your width you multiply your height and then you also set the scale as well so this hack allows us to reduce the um to not have this issue but to have it less less visible so something in Kaboom I cannot I didn't want to modify the source code itself and even even when I tried to fix it didn't work so uh if you're Kaboom maintainer maybe I fix this that would be great so yeah so maybe you cannot unsee this anymore so yeah sorry sorry for making making you notice something like that all right let's go back to yep to the project so now in the Kaboom loader the reason I call this the Kaboom loader. JS is because not only we're going to load the Kaboom uh Library here but we're also going to load our assets from this file so in previous tutorial tutorials I would use Kaboom context and then just have this one and then do the loading in the main.js but I thought to have everything that relates to loading things from Kaboom to be in the Kaboom loader file all right so let's load the various assets we're going to need um I'm trying to think maybe it's not the best to do this directly um I think we we could do yeah if we do this once and for all and then we won't have to worry about anything related to animations so this is something that is very tedious to do I would recommend that you just copy and paste the source code so by the way the source code is available on GitHub so this is something I would not like to spend much time typ it out so I'm just going to explain everything so how we import Assets in kabo so the way assets are imported in Kaboom depends on the assets of course we have the load uh the way to load fonts is by using the load font method provided by Kaboom and that's why I like this pattern of having cab uh Kaboom as being non- Global is because we can you can immediately see that if the the method is prefixed by K that means it comes from kabo so so the way you load a font in Kaboom is by using the load function method here and then you pass in the name you want to use to refer to in your code for this specific font and then the second one would be the path to that font so this how you load a font there's also load bit F uh bit map font I think is another one where your font is an image and then you specify each character uh the value but this is not relevant to this tutorial uh to load Sprite uh so or Sprite sheet that Etc you use the load Sprite method and it's basically the same thing if it's a single image you want so let's say you have only one frame in a PNG file you would only need to First specify a name for your Sprite that you want to you uh to refer to and then pass in the path and that's it you would close the the parenthesis uh however in this case we have a spreadsheet that means that we have multiple frames located in the same image and uh to know to tell Kaboom how to slice it we have to pass in a third param which is an object that is going to contain all of this information with also the the animations we're going to Define so let's uh have a look at the Sprite so here we have the player Sprite um Sprite sheet which is located under the Sprites folder and under u.png and here we have a bunch of frames and I realized one thing is that it's not going to be very visible unfortunately because uh the colors you know uh okay maybe I should open a Sprite so this is aprite which is the or yeah aprite which is the software I use to draw pixel art so here we can better see the Sprite sheet uh so the way kaboon uh slice Sprite sheets is first of all you need to specify the slice x value property and the slice y property so slice X is B basically the amount of frames per row so in our uh in our spreadsheet here we have 1 2 3 4 five 6 7 eight we have eight slots uh per row so that's how we determine the slice x value to be eight by nine uh slots per column because this is how 1 2 3 4 5 6 7 8 and nine as you see there is a lot of animations here we're not going to use all of them uh so here it's slice n now for defining animations you specify the anims property and then you pass in an object and each of the these entries are going to be the various animations so for the idol animation so those names here are names that I have arbitrarily so those names are names that I have arbitrarily chosen for myself so you can decide to to name them however you'd like so here I decided to name it the idol animation and by the way it doesn't have to be a property like that it could be a string uh with uh like I don't know maybe uh idle uh dash player you could have decided to name it this way but we're not going to do this here so here Idol and then you pass in another object and this object needs to have the from Key the to key and the Lo whatever or not you want to Loop and this is optional uh but the two main things is these two you need to to basically specify that however you can specify an animation as being a single frame so for example I don't know indle idle um idle one I guess and then I would just specify frame zero like that you can do that one you need to just have one frame so here from 0 to 7 what does that mean so this animation this animation that we Define as Idle is going to start at frame 0o so the way fra uh frames are counted in Kaboom once the uh the you have specified slice X and slice y properties is as follow so you have um zero you start at the bottom uh the top Corner 0 1 2 3 4 5 6 7 and by the way you don't count the frame you count the slots because even this empty frame is considered frame so you would have 0 1 2 3 4 5 6 7 8 9 10 11 12 uh 13 14 15 16 so here for the idle animation it's basically 0er 0 1 2 3 4 5 6 and seven so the first row would be the animation so from 0 to 7 and here I specified the animation to be looping that means it will always play uh when you start playing it it will not stop playing until you stop it manually certain animations like running jumping falling and Idol itself are good to be uh we want them to be infinite like that and we decide when to cancel them but as for explode or attack when an enemy explode Etc it's just a oneandone animation and for the attack animation also it's a one andone we want the attack animation to run and then and then to stop when it's when the attack animation is done the attack is done and here you also see that you have other optional properties like the speed property which you can specify the frame rate her 16 was a good uh uh what was a value I thought would made the game look good so that's basically it um uh you have also another one called the load Sprite Atlas uh so the the difference between a load Sprite Atlas and another another a normal load Sprite is the following so with a load Sprite Atlas you're loading uh you're basically cutting out a specific portion of an image so for the UI you have this whole thing and I only need this part but instead of just like cutting it off what you can do is just use a load Sprite Atlas in your code you specify the file you want to load and then here you can cut out a specific uh sprite from it so here I decided to have a Sprite called health bar it's going to start uh from within the image at coordinate x uh 16 and Y6 so you take your image the coordinate 0 0 at the uh is at the bottom uh at the top Corner top left corner and as you move here 16 and then you drop down 16 here and from this part from this point onward you're going to cut it cut the image with a width of 60 and a height of 40 so this is going to cut the image like that and only keep this portion and then after having done this I'm going to also slice the specify slice y as being true three uh that means I just want to cut out the uh um basically set this as a Sprite sheet so first of all I cut out from the rest of the image only this portion and then I set it as a Sprite sheet by specifying the slice y value that means that every frame so there is only three frames in this uh in this uh this portion and it's going to be the health bar so the first frame is going to be frame zero frame one and frame two so this how you would do it uh if you had um for example this part if you wanted to cut out this part you would specify different X and Y values and then from there different width and height value to just keep this part and then here it will be slice X3 because there's three uh slots per row and by three slice y will be three by three so 3 by3 hope that was clear and that's basically it so here for the sounds it used the load sound uh fun uh method and then you specify the name and then the the sound as easy as it gets so copy this from the source code on GitHub I think it would be better that way than me typing it out so assuming you have this done our assets are all loaded so yeah I might come back here to tweak certain animation but I shouldn't have to do that because this is taking taken from the final project so if we go back to our browser Tab and we still have our canvas nothing changed and that's pretty normal all right now let's um wondering what we should do next is continue creating our folder structure so I'm going to collapse this collapse this collapse this and then here in our source source folder I'm going to create an entities folder this is for the player the drones the boss I'm going to put the logic there for them um also going to you create a scenes folder which is going to be the various scenes we only have two scenes here we have the room one which is the big uh map here and then we have the room two which is going to be just a smaller one so you can see that if you were to expand this project you would have a uh multiple um images like the multiple rooms like this that would comprise the whole world so after the scen folder is created I'm going to also create a state component uh State uh folder this where we're going to hold the global State uh yep so I think the finally the yeah sorry I forgot we need the UI folder for the UI so now we have a neatly organized uh folder structure so let's start with the scenes I think this is the most important part so for let's define our first scene so our scene uh I'm going to use the concept of rooms even though this is much bigger than than a room but I started with this initially I didn't think Kaboom could handle a bigger map so I thought that I would just have multiple rooms stitched together but in the end it was able to so that's great so that's why I I the name stuck because I it felt too much of a hassle to just change everything now so let's create a file called room room uh oops room one. JS and in this file I'm going to have to export a function a sync uh it's going to be a sync I'm going to explain why later on that's probably because we are going to have to import the map actually I don't think we're going to need this Inc here so you know what instead of writing s Inc and not knowing why I will just write a normal function and then when a time comes and we we see that we need it I'm just going to add it back so why why I'm doing this so for now let's create an empty function called room one and it's going to contain all the log defining our fun our scene this scene so yep and uh I'm going to leave it empty for now let's create another file in the scenes folder and I'm going to call it room 2. JS and it's going to be again the same pattern export const uh not const export function Room 2 and it's going to be empty not page transition sorry ah I messed up so export function room to ah come on I'm struggling with my own keyboard and I made a typo as well all right so another function here and also like with room one it's going to contain all the logic we need for our scene and then in main dos I think it was in main dos yeah so in main.js we're going to Define our scenes so here I'm going to create a function I'm going to call it main actually you know what let's do it directly so to define a scene in Kaboom JZ use the scene method and the scene method takes a name which is going to be the name you want to use for your scene to refer to that scene it's a key basically it can be anything you want as long as it's a string and then the second param is a function uh an arrow function but just a function and this function is going to run when the scene is called so here for now I'm just going to import room one from that file and just call it for now there's nothing that Happ that will happen from this optionally you could have decided to just pass in room one without the Arrow function and just the name and uh because we're passing because room one is a function definition it's going to call that function definition but the reason I'm using an arrow here an aror function is because we want to have like the previous data of the scene at one point which is Kaboom is going to pass it to the to the um it's going to pass it to the to this function and later on it's going to be clear so for now just I'm just going to uh leave it empty so I'm going to Define another scene I'm going to call it room two and I'm going to have an N function as well and room to uh I should import it y so bubble should the your editor should s here we go I have room two and I'm going to call it okay that's uh for now and let's have a the intro scene which is the scene you saw that just tells you the control I know it's a bit lazy to have a scene like that but because this is for a tutorial I felt I didn't felt like having a whole menu and uh yeah all that stuff so I just stitch together a simple entro scene that just tells you the controls all right and then finally we going to use the the go method which basically tells uh boom to go to a scene this is important when you define scenes you need to use that go function otherwise uh actually you don't have to I don't think you have to you could have a the the the the default code for example it could start writing your logic here and it's going to display but usually the the patterns that you define your scenes and and then you call the default one call one otherwise you're going to not know why your scene is not displaying if you don't call it within the main.js F all right so we have this here and I think we're ready to see if anything changed in our uh project I don't think anything changed but you see the loading bar that means that the assets are indeed being loaded the loading bar sorry all right so now let's go back to room one and here for room one I'm going to first have our first pram which is going to be the K instead of having to import k from the K Lo loader often times I will just you know pass this around pass this K around here that way I don't have to write this import state but I think uh uh I think both approach could work you could decide to import every every time you need K you just import it from this file but for some reason I find myself doing this and I think uh it uh it's more convenient I guess you don't have to import anything extra all right so I'm going to import the context here and just to test things out let's create our first game object so if you're not familiar with the game what game objects are in Kaboom well it's time to explain this so uh Kaboom allows you to create game objects think think of game objects as entities for your game uh they can be platforms they can be players enemies drones Etc but most importantly uh than not is that a game object is an array of comp components it's made of an array of components those components are all mostly all but you can make your custom components are offered by Kaboom and this is what one of the driving force uh strengths sorry of KaBoom is that it makes creating game objects very easy and it speeds up your game because there's ton of functionality that you get for free so that's why Kaboom J I think would could be like literally called a game engine rather than the library because it offers that that much uh so so to create a game object in Kaboom you can use two things uh two functions uh two methods you can either use the add method or you could use the make method uh the make method creates the game object but does not add it to the scene so it won't be visible while the add method creates the the game object and then display it on the scene as well so here for just testing we want to add to the scene so to the canvas and we're going to use the ad method the ad method takes one peram which is an array of components so components um so for example you can have the text component this is offered by Kaboom you can just pass in some text hello world and then you can have you pass a second component which is the positional component this is also offered by Kaboom and it's where you want to put this on the canvas let's put it at 100 by 100 just to test things out so here we are we have our first game object which is a text basically text based game object so if I go to see the result and uh it's not going to display because we write we wrote this code in room the room scene but we first went to the endro scene so let's change this temporarily to room one so we go immediately to the room one scene so here we can see Hello World in the default font now because we already imported the font in here we can just use glyph mess here so something specific to the text components that can take a second param which is where you define the uh the font with font property glyph mess oops and there's a bunch of other properties like the size the text wrapping Etc but for now let's use one uh one property so now if I go here you can see Hello World written in the font we're going to use for the game so this how we we create a game object so but this is not what we actually want to do for for this project uh what we want is the actual um to actually display the the room level so this is what we're going to do in the next portion of this tutorial we're going to write the logic to display the maps I'm going to spend some time hopefully explaining how til work and how all these layers Etc how to make sense of all of this uh I also recommend just also reading the blog post I wrote which is going to which is a stripdown very simplified version of this just to explain how til work and I think it does a better job than I could do right now but I'm going to try to explain those also okay so now we're going to write the logic to load the map and the way you load a map well before that let's first color the background so uh the background color I usually don't do that in tiled so if you see the map here in tiled it's transparent here the the uttermost layer and that's because it's better to just do uh color the map uh color the background in the game itself so to do that I'm just going to create a small utility so for all logic that is going to be common to both room one and two or just rooms in general if you decide to expand upon the project is to create a room utils JS file here and in that file I'm going to create a function that I'm going to call Export first we're going to export that function I'm going to call it set background color and it's going to take the context the Kaboom context so that we can use Kaboom relative functions and the second param is going to be the hex color code which is going to be the color uh that we want to display so here I'm just going to create use a game object that is going to be a rectangle is going to take the whole width and height of the screen and color it a certain way uh it's better to use that than the set background uh method from Kaboom because the set background method from Kaboom is going to color everything including the rest of the body of the page which mean we won't have the nice uh looking bars here uh in the game by the way the game is responsive I mean the three sizes because we activated the letter box option in case I for got to to explain this sorry but letter box is really so that on any screen size it retain the same aspect ratio so here letter box here all right so now that we have this I'm going to go back here and I'm going to create the rectangle I'm going to use the rectangular component which is just rect specify a width and a height and you can get the height of the current canvas and the width of that canvas by using the height and width uh method so you have the width method uh width width method and height so like that and then I'm going to use the color component which allows us to color a given game object with a single color and I'm going to use the color I think it's an abstract class uh but the from heex method which allows us to color it by specifying a hexadecimal uh value which is used usually it's most used for colors it's the the thing here in aprite for example and uh the reason we need to do this is because by default the color component takes a uh three params which is the RGB values and not an hexadecimal value and now we have this more and then one thing we need to also use is the fixed component this will make sure that the camera uh not the camera this game object in particular is not affect by the camera so that means it will always remain at the same position regardless and this is what we want for the background we don't want the this rectangle to basically not cover the whole world because as we the player moves and the camera moves the part that cover the rectangle covered is not going to be there anymore it's not going to be um uh covered anymore because the camera has moved on from the position of the rectangle by default if you do not specify a positional component what happens is basically that uh the the the game object will be placed at 0 0 in your canvas so that's why I haven't specify a positional component here because it's not really needed all right I save this and I'm going to call that inside this um the room one logic so I'm going to pass in the K here the context and here the hexa decimal value we're going to use is it's going to be a specific value I don't have it uh memorized but it's this one uh oops I should have done this properly so this is the color so now if I go back to the game and there's an issue and the issue is because we forgot to add ajs in room U actually in the import remember because we're not using npm it is required to have the JS here because if we if you don't do that the error to have let me just see if I can zoom in it's going to be uh a blocked because of disallowed MIM type text/html by specifying ajs extension it basically tells uh tells us or tells the browser Etc that this is a JavaScript uh mime type so it will allow it to run now we have the the background all right so we're making progress and that's great okay so now the next thing we're going to need is to load the uh data so I'm going to do this outside of the room logic so I'm going to have a room data uh pram and then back in the um main.js file we created earlier on main.js here is where we're going to need to use a syn we and we're going to have to wrap both these two scenes inside inside of an a sync function because we cannot use top level weight and we cannot need that so I'm going to have an X not export I'm going to Define an async function main I'm going to call it this way main may be a better name but for now let's just call it main uh and I'm going to take those two scene definitions I'm going to put it here and the reason for that is going to be clear very early uh we don't really need to put the inro scene here uh because the reason I'm going to need to use a Sync here is because we want to first load the data from our Json file it contains the map data from til uh so let me just write the logic for that and then after that I'm going to explain how do you actually get the Json file so I explained earlier you can find this in the description but for the actual map like how you draw it Etc I'm just going to do the explanation now so A8 fetch so this is a similar like how you do in web development where you want to request an API but this time you just request a Json immediately so we're going to take this from the maps do uh do/ maps and then the name room one. Json so room one. Json and I'm I'm going to just do this on one line so usually people what they do when you see example how to make a fetch request is they first put this inside of a variable they call it response and then they Jon jsonify it later on but I'm just going to do this in one p swoop so 08 uh Fetch and then that means as long as the fetch call is not resolved we won't move further and this is what we want and that's why I'm using a s we a s weight because as long as we don't haven't uh loaded the data for the room we don't want to display the room data so here we have the Json as well so here we after you have fetched the data it's going to give you a response and then you need to actually convert that to Json so if I go to room uh the actual content of room 1. Json you can see this is the content we have for this project we don't need uh really to dive into the uh tile layers so tile layers are layers where the data is basically the tiles placed uh we don't need that because we don't actually uh need to render those tiles in caboom uh because we can just use the image that we have exported from til but for colliders you have have here uh how it looks like so I'm going to dive into this later on so now that we have this we have the room data we're going to do the exact same thing for Room 2 data and then 08 then 08 again oops then I'm going to fetch Maps slash and then room to. Json and then we do this all right so we have have both of these room data collected now for the room one I'm going to pass in for the room one data so now if I go back to there is one issue though is that we have defined the main function but we actually have to call it so that it fetches the data so the reason I'm actually doing all of this inside of a main function as I explained earlier I cannot use a weight outside of a function in JavaScript I don't think that's possible so that's why I'm doing so I'm calling the main which def collects the data for both rooms and then Define the scenes for both rooms and then we Define the scene for the intro and then we go to the intro but for now I have replaced it with the room one for now just for to make our development easier so I go here and I have an issue seene not found room one okay now that's because it's called before this is resolved because it's an async function okay so maybe I'm going to go back to the intro and then here let's let's actually take some user input so the way you take a user input you can use the Onkey press method in Kaboom and then here you can specify as the first peram the key so here I'm just want the player presses enter I'm just going to um let me just do this like that so when the player presses enter I'm going to call the go to the room one now so now if I look back I have an empty scene because that's normal because that's the intro scene there's nothing by the way we should probably just uh n let's do that later on but for now let's leave it empty with just this uh event handler within the scene so event handlers like these are scoped to the scene so you have to reenable them recall them when you move on to another scene so that's one thing that you have to keep in mind if you make a for example game where you can move in various scenes so every time you load a new scene you have to recall those methods so yeah you can write a reusable function for that okay so we have a Onkey press when the player press enter we go to the room one so let's try it out so here press enter and then everything is loaded Etc everything works so if I refresh and do that really quickly does it actually work all right yeah it works okay nice uh so let's go back to room one uh now that we have the data it's time to print it out so uh actually I'm going to store the room layers first and I think this is a good time to stop writing code and start explaining where do I get all of these so I'm going to go back to til so til is an editor like I explain so let me explain what we have here so we have our room uh with which contains various layers so the layers in Spector is on the top right it's all the layers I have created you create a layer by clicking on this button and then selecting the type there are basically M two major types that I use are the tile layer and the object layer tile layers are for placing tiles so here down below you have tile um a little tile so yeah what I'm going to do is I'm going to explain uh just how the current room setup in work but feel free to please reference to the blog post which gives you a better picture so here um I have okay so I have the title sets here defined so the way you do this is basically when you create a new project new file new map and then you can import the I said this is all covered in in the blog post so here we have multiple layers so by the way this is hidden so tile layers are for placing tiles uh for example I'm going to hide everything and just show you one by one so the first layer I created was the platform layer which contains only the platforms Etc and the various things here now I should have probably created this inside of a props layer instead but sometimes mistakes happen so that's that and then here uh I have the SEC so those are tiles you basically select the tile you want and then you draw make sure to to select of course the the the layer you want to draw and then you can just start drawing like that but this so yeah the second layer I created was the props layer which adds various props and then here you like I said you can select multiple ones like that and you just draw place them so this is the advantage of tile layers is this is how this is what they allow you to do now I have background one which is again a small things and then background two which is basically some buildings Etc same logic here just I used this a second tile set you can load more than one tile set so to add a new tile set you click on here and then you browse and then you click on okay so that's how you do that okay now we are done with the tile layers so layers used to draw things and render things out now the collider the second type of layer is is the object layer and those are used for colliders so the platforms invisible stuff basically it's more efficient to do this than to um have every tile have their own colliders otherwise H it's going to be more performance intensive so just drawing the rectangles here by selecting so when you create a object layer you have a bunch of tools here above and if you just select the rectangle you can trace a a a collider so I'm just going to control Z here and one thing I want to uh also mention is that uh if you go to view you can go to snapping and make sure to have snap to Grid or no snapping depending on the situation so here for example is a collider where which is very small and the SN if the snapping is set to grid it won't allow you to draw a rectangle that is smaller than a tile so that's why sometimes you need to en disable to no snapping or snap to fine Grid or snap to pixels Etc so yeah and one thing is that when you draw a collider you can have so if you click on this uh pink white rectangle thing I don't know how to explain it if you click on that you have to the left side the properties tab which contains a bunch of properties and those are the actual important data the X and Y coordinates of where the collider should be placed and the width the height of it is important and it's data that is imported uh exported to Json and is going to be imported in our game and this is how we know we this is the data we use to draw those colliders in our game and to make them basically uh so by the way once you have your map you need to save as and then you save as to your specific uh to the folder where you want to use those maps and then you just write it a Json extension by default it will give gives you the option to uh save as a TMX but just doing doing it as a Json is fine so here one example of how this properties tab come in handy is that for example here if I click on that there's a dog outside barking so sorry if you hear that in the recording um so here when you click on that you can give a name or a class to any of your colliders and this is useful because I want to give a class of pass through this is a name I have this decided for myself but it's important to be consistent because you're going to use that name in your code to know how to uh what logic needs to be applied to this collider and pass through here is logic that I'm going to apply so that the player can jump through that platform and land on it which is important here and uh yep so we have this is the collider lay colliders layer the positions layer is a bunch of pins you place those pins here and basically those are x and y coordinate they can have a uh I think if I select this they don't have a width and height they just have an X and Y coordinates and they're mostly useful to know where to place things so here for example this is I'm going to place a drone so depending on the situation here when you have multiple pins that are going to spawn multip like the same enemy type I prefer to just use a class and call it drone otherwise if it's only unique thing I can give it a name so basically the only thing that changes is in your code how you access those those properties in your code you can access the name property by just having a DOT name on the object I'm going to show you the code for that later but for the class you just use a DOT type property to have access to the the class so this how it works for example I've placed the boss here uh there's only one boss so I used a name instead of the class and as for the uh yep those drones there the pins and for the health pack also it's a class because it's the same thing repeated over and over again and that's basically it now the cameras is something new to this project I haven't done in the previous project those are colliders that when the player will collide with them they won't cause a collision or anything like that but they will change the camera uh most importantly they usually change the Y position so something you can do in tile is create custom properties you do that by just having for example this one doesn't have custom properties you just right click add a property so here if I go back to the cameras layer so I've put this in a different layer so just to not confuse I'm going to hide the collider layer so here if I have a property I I want a new property I do add property and give it a name and a type and here I used the in type so this is a value so when the the player collides with this camera collider I'm going to take this property and the value for it and then set the camera y position to that value so that's how I can make sure that the camera shows specific things and slides Etc so there's a bunch of them here so for example we drop here the camera will move when you drop here you going to also move or go up Etc depending on the situation so here it's going to go up here it's going to go up so it mostly just affects the Y positioning so only the wi position of the camera so actually yeah so in um in uh if you're not familiar with game development usually when the Y value is high that means we're going up the canvas so we're down yeah I'm confus confused yeah actually the least the no the least the value of y is the higher on the canvas you are that's because the the uh yeah so the the higher the value of y the lower you get on the canvas that's something I've explained in previous tutorials but that's how how it's it is done in game development uh in yeah Graphics Library Etc okay uh now what I want to uh yeah so there's a bunch of colliders here and um yep and finally we have the exit collider exits collider and I think one thing before that for the position the camera collider actually the colliders itself there's this specific boss barrier which is a specific specific colliders so if I go back to the colliders here and this one I have specified a unique Campa X property this time around this is an arbitrary Name by the way I forgot to mention because when you arrive to the boss gate uh barrier I want to move Slide the camera to the x axis not necessarily the y- axis as I used to do with other cameras and uh yeah it's a collider because it's going to be an actual collider because the barrier is going to be visible as you fight the boss and you cannot move and that's why I've put it into the colliders layer and that's basically it and then finally so we have position I've explained this and then the exit exits uh layer which is another TI uh object layer and this is just to know um where to spawn the player in the room two so I've named it exit one and I've name it Nam named it sorry exit 2 and uh yep so so when you hit the player is going to hit that I'm going to know that the name of the exit and I'm just going to spawn you either in entrance two or actually this is the spawn point here entrance two spawn point or entrance one so that's how I link those scenes together and here again it's the basically the same layers uh so feel free to explore open those up in tiled because they were just Json file you can just open them up uh and play with them so I'm not going to spend more time on that but I'm just going to explain one thing though so to do the exporting as a single image what you do is you hide every uh object layer uh yeah object layer because you just want the graphics so and you go to export as image and then once you click on export that image you have the the path to it uh to it and then you can you you must check this to only include visible layers and keep all the other things unchecked and then you export and it's going to give you the room one or room 2. PNG uh depending on which one you export here and there so that's an overview of how to use tile so like I said the blog post goes into more details on how to do this from scratch so give it a read all right so now let's look at the export to the Json so the do Json that it was saved so you don't have to click export you just have to save your map as a Json and you can immediately access the various properties so I go to room 1. Json maybe room two is going to be easier to parse because it's smaller so uh if you were to use a tile so every tile layer has the data props so first of all let's collapse everything and let's go get go at it uh one step at a time the most important part here the most important property is the layers property the layers property contains all of our layers and here it is I'm just going to collapse everything so each object here is a layer and Y let me just collapse so we have one 2 3 4 five 6 7 eight layers and this corresponds to what we had entit which is 1 2 3 4 five 6 s eight layers but it's reversed so the first layer here in the the array is going to be the lowest layer because uh the way usually uh Graphics Library works is that the first thing drawn is the the the thing drawn at the lowest level the the lowest layer so if you have a tile layer and not an object layer what you will have is the data property so this data property specify for each uh tile which tile in the Sprite sheet to draw if it's zero it's going to be uh zero so it's going to be the absence of the tile so nothing and here the number it corresponds to the frame in the Sprite sheet but because we aren't drawing the the the tiles in Kaboom but rather just using a PNG that contains everything because somehow it's more performant and I don't know exactly why how K Kaboom implements this and why it's the case uh we don't need to parse this layer at all so any tile layer we have here we can just safely ignore it so we're going to ignore that and yep so the way I'm going to do this in the code later on is I'm just going to check the type here so you have this property called type that is either tile layer or object layer so if we see that we have a type of a tile layer we can just continue in the for Loop so we're going to write some code to iterate through that so the second layer also is a tile layer the third one the fourth one the fifth one is where things get interesting we are now having a object group so the object layer is named in the actual Json file as object group and the difference is that it does not have a data property like with the ti layer it has instead an objects property and it's an array that will contain every object so here every collider with the width the height and the X and Y coordinates however if it's a pin it's just going to contain the X and Y coordinates so Mo mostly for the positions layer it's going to be that and using this information this data we're going to be able to uh draw uh the hitboxes and place the the players positions Etc so here I'm going to con I'm going to put in a constant the layers of our room datas and by just using the layers property accessing that we don't need the rest and then here I'm going to create a game object that is going to act as the parent of everything it's going to be the map game object for the scene and the way I'm going to do that this is by having the add function and placing this at positional 0 0 uh you do not need to do that I think because by default if you don't specify it's going to put it at z0 but just you know if in case you want to move the map elsewhere like the whole map you're just going to modify this value anyway so I'm going to set it to z0 explicitly but feel free to not do that I don't think it's going to cause an issue and here we're going to load the room the image the room one so if you remember when I told you to copy and paste the code from GitHub uh we loaded the images for the room one and Room 2 PNG here and using the room one and room two uh Keys here and then if I go back to room 1js we can just use the Sprite that you have already loaded by using the Sprite component Kaboom so this will work also for all the other things that need Sprites and specify this the Sprite name so here we have an object that is going to act as the parent of all game objects so in Kaboom J you can create game objects that are going to act as children of other game objects so you have here for now this game object the map doesn't have any parent the reason we're doing this by the way is because the positions are relative to where the map starts in the tiled export so in t in the Json file so if you were to just create the game object separately you would have the positions of everything being off that's why I prefer to just use a map uh a parent game object which is represents the whole map and then put everything uh Rel uh relative to that as a child of that game object okay so now we can just continue so then the next thing is to create the colliders um to store in the constant the colliders which is just going to be room layers and then the actual number so in instead of like uh I'm just going to pick the specific layer that corresponds to objects uh and I'm just going to have the dot object so here uh if we go back to the export um I guess room two this is going to be index 4 so I'm just if I just clect everything here so one uh zero 1 2 3 and four zero because we are in an array so the fourth element is going to actually contain the objects for the colliders so the yeah the objects property is basically all the the the colliders uh data so that's why I use this maybe you shouldn't do this uh if you want more flexibility but for this project I don't think it's needed I have specifi I have decided to have eight layers but maybe if you decide to add more or less layers or replace them maybe you want a more flexible system where you just going to check you're going to iterate through the the layers and then check if the name correspond to colliders and then use that so actually we could write I could spend the time writing this logic like that so maybe we should do that actually uh yeah so if I were to do const for layer of uh room layers and then here I'm going to have instead a um a colliders I don't like that I really don't like that so I'm going to do this because you know in JavaScript an array even if you put it cont even if you put this as a const you can modify the content of the array it's not actually constant so if I do let here but I'm going to assume you you know JavaScript uh so here I'm going to have if the layer do name is colliders then I'm going to do colliders and I'm going to use the um um I'm going to put push it the room the layer itself layer dot objects so I'm going to spread it over and then push it all at once I think it's not going to do what I think it's going to do right okay let me just um if I put the spread operator it's just going to create an array within the array actually actually it should sprad it but anyway I'm just going to console. log the result I don't think this will work but yeah so this is something I think is a better coding practice layer. object uh I forgot typo here it's objects so I go here okay we have an array with all the elements in that's great so it works okay it works so here as soon as we do this we're just going to break and then if I make making sure the code actually works yep it works all right nice so this is a better way that means regardless of how you structure your til as long as you have the names right you can find the the layer it's more computationally expensive to do that because you have to do a for and iterate through the the uh the layers uh actually the name of the layers not necessarily every element in the layer but I think it's worth it so here we go and we break here because we don't need to do any more calculations as we go on okay so we have that and then now what we're going to do is actually we're going to write some UT Tails so in the r. UT Tails we're going to write in a if a reusable function the logic to place the colliders in the map so I'm going to call it set map colliders and in that I'm going to need a the constant of course I'm going to need the map Parent Game object and I'm going to need the colliders themselves to know where to place them and uh so here and then the okay so we have everything and then here we go we have the collider so for const collider of colliders and then so T through them so here we're going to have actually there's one thing I forgot to mention is that in our collider layer there's a specific kind of cider that is different from the rest it's the slope here it's not a normal rectangle that has been drawn with this and you won't find this in the blog post because I haven't mentioned it here we need to have a polygon so if I draw a polygon maybe I should U what ah so I need to select colliders so a polygon allows us to you know have slopes like that for example I have a triangle here the difference uh is the following so if I select that polygon we have an X and Y but uh wait a minute there's something missing it should uh does it actually do anything so XY rotation template there is another property for some reason it's not appearing so basically what I want to say is that for polygons it gives you um coordinates there is going to be coordinate a coordinates prop uh for some reason this is not appearing here uh in this part okay Parallax it okay that's strange but okay so I'm just going to delete that so if I go to the oh maybe that's what that was why so I'm going to redraw it here a triangle and then what happens if I do this okay so it doesn't seem to appear on its own in the inspector here but if we go to the title export and look for the slope this is not going to be in room 2. Json it's going to only be in room one so if I go to room 1. Json and I'm going to do a quick search here with contrl f and try to find the um polygon property you see okay so it's a polygon property that gives you an OP object an array of the coordinates of each of the point of that polygon this is a specific thing for those colliders that you draw using the polygon tool so the polygon tool if is this one here so that means in our room utils we're going to have to first iterate through all the colliders but now if the collider has the so if the collider has the polygon property then we're going to first create a coordinate um array and oops and then I'm going to have a for Loop and I'm going to iterate through each of the points of the collider do oops collider do poon so collider polygon which is the property that contains an array of each of the coordinates for each of the points of that polygon and then I'm going to push inside my coordinates array those coordinates but this time around I want to use a vector to so in Kaboom Jaz the way you specify positional components is by if I remember correctly here I I set to Z 0 but another option is to pass in a vector two so you could have done Vector 2 and then 0 0 uh so the the reason this using Vector 2 is useful is that when you want to the set the position after the fact so if you want to do this map and then set the position it's often handier to just do that uh you cannot do other than that or have to do map. pause. X and then a specific value and then map. pause. Y and then specific value so that's a way to make things easier for us later on so that's why I I push them into this coordinat uh array then I just collect 0.1x 01y so here we go and then here I'm going to add them to the map so the way you add child game objects to the main game to a game object is you take the game object and then you use the add function the add method on it so to uh later earlier on we used the add function in Kaboom to create a game object but this but each game object has the add method available to them to add child game objects to them so not only this add method creates a new game object but it it appends it as a child of that map at that parent of that Parent Game object sorry so here specify the position and then here I can just do um okay that was a a bit so in the original source code I just did collider X collider y uh Y which basically defeats the purpose of having created a vector 2 so I'm just going to use a um coordinate uh wait a minute okay that what's the point of it okay maybe I have created this for nothing uh ah okay no never mind never mind this is different because we have the the position of the collider which is defined in the collider properties X and Y but now we also need to have the area component and the so there there's two things to explain here sorry first thing what is the area component so the area component in Kaboom JZ creates a hitbox for your game object by default it takes the shape of your Sprite component or the rectangle component the wct component or any shape you have already specified earlier but if you don't have a shape specified you can specify custom shape by using the shape property passed inside of it and here I'm going to create a new polygon which is a class Constructor in kabz that allows you to create a polygon uh based on a coordinat an array of coordinates and this is where the coordinate constant we have here is useful because we we can just pass it as directly here and actually this is why here it was important to convert this to a vector 2 because this Constructor takes an array of Vector 2 that's why we had to do it as well it's not just because it's handy as well so yep we have this and another thing I'm going to use and this is to increase the performance is I'm going to have set the Collision ignore property which is something that Kaboom offers as well where you pass in an array of tags so each game object can have a tag a tag is basically a way to identify this game object um so the way you define tags is in your arrays of component when you Crea you are creating the game object you can just pass in a string as well and this is going to act as the tag and you can have more than one tag so here I'm going to pass the tag uh the tag collider it's just a name I have decided to identify all game objects that that are created this way uh and in the Collision ignore property in the area component I can pass in that name collider and it will make sure to ignore any collisions uh calculations Etc uh when two collider game objects collide with each other and this is useful for performance because we don't really want to calculate the collisions between this and this or this and this it's kind of useless so and it's going to be more performance intensive for no reason so that's a trick to have more performance and then finally we have the collider type uh here it's important to pass the collider type because if you remember uh not every collider has a type in our uh in our um map here but those uh oops I didn't want to create a new polygon so I'm just going to contrl Z so if I select it with the pink tool here if you select this the class here pass through is going to be referenced you can access this name through the type property I don't understand what why they're different maybe the class uh property is a reserved keyword in JavaScript I don't remember I don't know why exactly they decided to have different names but this is useful because now we can have create a new tag which basically is a string uh specific for the pass through platforms by just passing the type here so if a collider doesn't have a type it's just going to be an EMP empty string and an empty string is just basically not a tag not considered a tag in Kaboom so that's hope I was clear here feel free to ask questions by the way in the comment section if you have any issues and then we continue so the reason we continue continue here is because if it's not a polygon uh collider we we need to write a different logic so here the next case is that if we have a collider and the name of the collider is a boss barrier which is one of the exceptions here what we're going to do is um oops here we go so if the collider name is a quick boss barrier we're going to create the boss barrier but this time around we're going to store the reference to that game object it's still going to be a parent a child of the map game object so one thing is is Handy with the ad function and the make function as well you're going to see later on is that um it gives you reference it returns a reference to that game object when you use that so you can keep it here keep it handy here so here the boss barrier I think I'm going to actually you know what uh for now let's skip that I'm going to do to-do and we're going to do that later on and if going to continue if to the next iteration and then the last case uh yeah so all the other case are just normal colliders and we can just add them as a child of the map and specify collider X collider y but for all those normal colliders the shape we're going to Define is just going to be a normal rectangle you can specify this by using the rect Constructor here it's different it's different than the re component re component actually draws the rectangle while the shape the creating a rectangular shape is just going to make the hit box all hit boxes like this can be viewed uh if you press the F1 key and enter debug mode uh well actually enter debug mode by pressing the F1 key so if I do this so so here the for the rectangle Constructor the way you create a rectangle you have to pass three parameters the first one is the position and I'm just going to pass an empty Vector to uh this basically tells that there is no difference from because if you were to specify values here X and Y coordinates it's going to draw the shape uh the hitbox relative to the game object and in certain cases you want that you want the the the hbox to not be uh directly aligned on the same position as the game object but sometimes you don't want that so you just specify a 0 uh Vector two here as the first param and then the second param is the collider width and the collider he here so here we go and uh here we're going to use the body component so the body component is a comp component that can only be used when you have the area component defined so you first need to have the area component defined because you need the headbox and the body components for physics so here we want to have the physics of so by default if you just call k. body the go if you just add the body component it's going to make your game object susceptible to gravity if you specify though inside of it the is static property and set it to true it's going to be a wall uh basically a itic body it won't move when collided with it's going to act basically as a wall an obstacle and here I'm going to also have the collider tag and I forgot to here to add the Collision ignore as well Collision ignore oops collider so I've explained this already and uh we also pass the collider type um as I said for the past two platforms this is going to be useful because for some of them it's going to actually you know what since we have only one slope if we go back to the polygon uh we actually don't need to pass this type here because in case you want to in the future to maybe have passed through platforms that are also slopes like that I I I guess we can just let it be so yep um so yep we have done this and now it's time to call that function in room 1js so in room one uh yeah here we have the colliders not so right below I'm going to call it set map colliders it's going to import it from uh room .js make sure that this is ajs and here okay and then pass in the map so okay for the context and then the colliders we can just pass the colliders uh colliders here we go let's let's test everything out so if I go to the browser hit enter can see the map being fully drawn and the colliders also by pressing the F1 key now for now the the performance isn't very good but you're going to see later on we're going to do a bunch of stuff I think we're going to add a few things that makes it I think the offscreen component actually actually I think the the performance is good it's just it's just my PC where when it's unplugged it it runs at a lower frame rate H yeah and also the fact that when you open up the uh the debug mode it adds a bunch of drawing calls to draw the the layers and that's why the FPS count drops but the actual game performance as you're playing should be 60 FPS so now uh because this is not very inviting to look at because it's too small I'm going to uh do a bunch of camera operations so in kabz can control the camera relatively easily so here H I'm just going to call the cam scale method allows us to zoom the camera I'm going to zoom it four four times I think this is what will look good for the cam position I'm going to put the default position at 170 by 100 those are all arbitrary values I just came up with them by experimenting and then I'm going to set the gravity to being a value of 1,000 uh I don't know what the metric is the unit for that is but U 1,000 is what felt good but for now it shouldn't have any impact because we we don't have any kinematic body or any player or enemies yet so if I go here press enter you can see the map so in the next part of the tutorial we're going to hopefully start working on the player and the logic for that and making the player move Etc all right now that we have the map here displayed uh we could proceed on and work on the rest of the map cameras Etc or we could start and work on the player so I think a good we should actually go and work on the player logic I think that would be the best so we can start implementing movement Etc and since we have the map it's going to be easy to test things out so now what what I'm going to do is I'm going to go to the folder structure and then create in the entities folder a new file this file is going to be called the player. JS and it's going to contain all the logic we need for the player so here we go so here what do we need so I'm just going to collapse this so what do we need is first of all I'm going to create a function and this function I'm going to call it make player so in Kaboom JS uh usually uh there's nothing against objectoriented programming but usually don't use classes well I usually don't don't use classes and if you look at the examples on the dogs Etc usually don't use classes so here the make player is going to act as our Constructor but uh yeah so it's going to uh we're going to use the make function this time around the make method so yep the make method is like the ad method in kaboom but instead of creating a game object and then displaying it on the screen what it does it only creates the game object so later on you can take the game object and then put it inside of an add call to really add it to the scene so here I prefer to use this make function to actually make the game object and then in the room logic in the the actual scene I'm going to make the call to actually put it as a child of the map so here we go so here what are the components we're going to need to make our player so just to Circle back on the reason I object oriented might not be really use but you can actually use it but the reason is that when making a game object you have you can pass in an array of components you can pass a string that will act as a tag but you can also pass an object and is it this object can contain basically your methods for your game object so you don't need to create a class so for example here let F let's first create uh create add sorry our game object our components that we're going to need for this uh player uh character and then as we go on I'm going to add a bunch of methods for the actual Behavior Etc we're going to need dur in inside of that object so first of all the positional component is very important now one thing I forgot to mention is that you need to call this the you need to actually use the positional component even though by default it's going to just put the player at the position 0 0 and that's because if you want to modify the position afterwards it's important to have the positional component used here otherwise it's not going to work now I'm not really sure about that but I think I remembered it that way so maybe try it out and see if you can do without so now I'm going to also use the Sprite component and I'm going to here use the player Sprite this was defined earlier on in the Kaboom loader so if I go here Kaboom loader and to the actually the first load Sprite call here was where we loaded our player so here and uh yeah we just load the Sprite and then later on we're going to pick an an animation and play them okay what do we need else is the hitbox so as I said as I mentioned earlier on hitboxes can be um created it by using the area component by default if you just uh don't do anything uh except just using the area component just calling it you're going to have a default hitbox that takes uh roughly the size of the Sprite but I want more a granular control over that the reason I want more control is because I want to actually the hitbox to be the constant and the same regardless of the various animations and I want to place the hitbox in such a way that the player is going to look good uh in terms of movement Etc so the frames should be well positioned so here I'm going to use the shape property that I've shown earlier on and again call the new and then K and here of course I forgot to pass in the K the Kaboom context here so I'm going to use the react Constructor as I explained here for the first pram we're actually going to offset the hitbox to be at 018 so so this 18 y coordinate relative to the actual position of the game object and here I forgot a comma so maybe here I should probably have this to have it well formatted so shape new k. rect and then as the first peram here now this is a value I've played with um later on when we're going to actually look at the results you're going to see that uh like what what looks good the second Pam is going to be the width and here it's going to be a width of 12 and the height is also going to be of 12 this this way the the actual Sprites I think are 16 or 32 by 32 uh the reason I'm using 12 by 12 here is because it's uh the hit box is going to be small enough so that uh there are still some collisions the player cannot move in weird places but it's it's also small enough so that the player doesn't get hit uh all the time so it's a a generous I guess hitbox to be small okay now I think that's it for this one and we can move on to the next one the next component sorry so the next component we're going to use is the body uh the anchor component so the anchor component it's a new component uh that I haven't explained yet uh this allows you to Center um to determine from where the Sprite the the game object is drawn or centered by default all game objects are are placed or centered from the top left from their top left corner if we don't want that we want actually the center of the game object to be the position we can use the anchor component to specify that you can specific uh Center uh top left top right and you can even pass I think a vector two as well if you want more control I'm not sure about that last one but I think in the the platformer tutorial um the one my 8 hour uh 7 hour almost 8 Hour tutorial uh I think I did something where I control uh actually uh set the anchor to be a specific value I'm not sure though I don't remember that project that much anyway uh once we have this um I'm going to also use the body component this is very important because since this is since this Metro Vania is a 2d side scroller it's basically a platformer so we need to use the body component so that the player is going to be affected by gravity that means that it's going to be like it's going to fall Etc and here we can specify a bunch of other properties so we can specify the mass of our player I'm going to use 100 as the value how I came up with this was just by tweaking and we can also set the jump Force so this is when we're going to implement jumping uh you can set up in kabj as the jump force and here 320 was a value which I thought was powerful full enough uh so that the player can have a nice jump but not too much so that they hit the the ceiling of the levels so here we go and uh also we are also going to add the double jump components so double jump is a component that is provided by kaboon that allows you to easily Implement multiple jumps it's it doesn't have to be double so you could have more than that now here for double jump it's um I usually so I usually set it to one initially so I'm going to set it to one and then as we unlock the we beat the boss it's going to be set to two but the logic for this isn't here yet and actually you know what it's a good time I think to start handling our state setting the the groundwork for that so we want to have Global state to keep track of our players progress and I'm just going to create that in a folder called GL state I'm going to call the file global global State manager. JS and the way the pattern I'm going to use is going to be very simple so here what I'm going to do is simply I'm going to create two things I'm going to create first a constant that is going to be the state props enum and you're going to see why in an instant and the second one is going to be a function and I'm I'm going to call it init State manager and what it does it's going to return uh actually first we Define a state object which is going to contain a bunch of State we want to keep track of for example the player HP by default we want the player HP to be three then the max player HP uh we want it to not exceed three because for this project specifically the health bar in the the Sprite work the assets is basically three and it's not very flexible uh so instead of you know fighting this Etc I'm just gonna make sure the player only has three lives if you were to actually expand upon the game I would recommend just uh making your own UI uh components uh yourself or maybe tweaking those Sprite for example you could uh just take the the outer frame of the UI here you could take the outter frame so for example you would cut out all of this pixel art and have the all of this part transparent and then you would fill it in with color I actually I should have done this with a rectangle that grows in strings so yeah just some ideas you can uh yeah try it and then here I'm going to have it is double jump unlocked and I'm going to set it as false player is in boss fight another and I'm going to also set it as fault uh false and then is boss defeated defeated and then I'm going to set it as false so as you uh make this game grow in complexity you can have a bunch more events here that you want to listen on and state you want to keep track of now I'm going to return here I'm going to return one thing a current method so by the way in JavaScript you can Define functions like this with an object this is a short hand or this which you might be more you might be more familiar with so I prefer to just do that and uh here in this current method we're going to return a copy a readon copy of the state so while the user of that that's so the one who calls the current uh method can modify the object here it will not affect the actual state so for actually setting the state we want to use we want to create a Setter I'm going to call it set here it takes in a property as a string and a value you want to change and then here internally it sets the actual State here uh for the given property property to be the value here oops not value one here you go so here we go and here it's where things could get messy is that since this is a string you could pass in whatever you'd like that's why I created this state props enum where you can actually maybe I'm just going to copy and paste this you just have names like that player HP refers to the player HP string now this is isn't ideal in in terms of like if we were working with typescript we wouldn't have to do something like that but I think it gives us a a much nicer way and less error prone way of setting the state so just to explain if here I want to only unlock the double jump uh for the player who has defeated the well actually if I want to only enable the double jump if the player has the double jump unlocked then what I would do here is I would do state and then uh did I export it sorry I forgot one very important stuff is to have another export where this is the just the function that we call and then we have export const State and then this is what we're going to actually export so we're going to initiate the state manager and then this is the state um that we export so here in the jump I'm going to type state state and then import it here we go and then don't forget to add ajs then once you do that you can do State current which is the method which is going to give us the current state and then you can immediately just have access to the properties here so is the double jump unlocked and if that's the case we're going to use a tary here tary uh condition uh expression because it's it's Compact and if it's the case what we're going to do is simply set the number of jumps to being two otherwise by default the player can only jump once so double jump is a component offered by Kaboom Jaz it allows us to really build this feature out very quickly and that's great uh another component we're going to need is the opacity component uh this allows us to control the opacity of the game object this is going to be useful when we want to make the player blink when they hit the they get damage that that way uh when that happens we can just control the opacity otherwise you cannot control the capacity and then that's a I think that's it uh the last one is the health component so Kaboom offers the health component which allows you to manage Health very U easily and here what I'm going to do is initially you initialize the health component with the the HP for the player and this we're going to pick this up from the state so for example in if in room two the player uh in room one the player takes damage so in room two we want to actually keep track of the the player Health that's why um we we recreate the game object for the player every scene so when we go from from scene one to scene two the the the make player function is going to be recalled and that's why we need actually to keep track of the health so that's why otherwise it will reset to revalue if we were to hardcode it here to three even though uh the player is just exploring another portion of the same world so state. current and then player HP all right and then finally we'll have a player tag this is going to be useful when we want to have on cied events we can just use that tag so that other um entities can just check for that all right so now that we have this done it's time to actually uh fill this object so one thing the reason why uh objectoriented programming in terms of using class es is not that necessary when working with Kaboom J is because you can specify properties within here so here I created the speed property I want my player to move at a speed of 150 I also want the to set the is attacking property to being false so this is a property I created just to keep track of when the player is attacking for example when the player is attacking uh we want to make them uh un not vulnerable so they can't take damage where when the attack animation is running otherwise it would be um I think it it was a better way to go about for this project okay so here is our first meth method it's going to be set position now for this really I don't think this this one this method is really necessary we could just have a position here uh we could could call it initial pause I don't think I ever call this uh ever again except for placing the player so I can just do this like that uh so I'm not going to use that if if there's any issues I hope I will remember to just check here and re add it so okay so the first actual method we're going to use uh create for our player is the set controls set controls is going to be a method that is I always miss mistype and press the P key instead of the brackets which they're near each other so that's why and then it autocompletes with page transitions so um okay so this set control what is going to do is basically set the player controls one thing that's great with this um wait a minute yeah one thing is great with this creating methods within the object is that you can use this uh like in a class and create prop attributes that can be used by other methods so it's basically just objectoriented programming so here this control control I'm going to create a new uh sorry a new property and the way you could do that is just this and then the name of the new properties you want you want to create I'm going to call it control handlers and it's going to be an array that will contain um event listeners uh reference to event listeners for the various controls and the reason I create this is so that I can cancel all of these events event listeners when the player dies otherwise the player could die explode and then continue to move uh while the exploding animation is playing so here is the first call so I'm going to create this control handlers and going to push into it our first event listener that that I'm going to Define within this push call uh this push method I'm going to use the Onkey press event listener like I've shown you earlier and this time around I'm going to use a different form of the qess uh uh event handler from Kaboom instead of having specifying the key here for example enter like I did in the main.js file what I'm going to do is I just pass the arrow function and as the first Pam you can get the key uh by the way this is an arbitrary name the first Pam is going to be the key regardless of what it's named uh just for your information so here key on key press the key here so what I'm going to do I'm going to have an if statement and then if the key is for X let's say we have X and um if from within this. current animation so what what is this from so one thing is that this not only gives you access to the properties you created but gives you access to the whole game object and usually in kabon JS when you create a game object it has access to new methods and uh yeah new methods depending on the components you have used uh by default all game objects that use the that uses the Sprite component have access once they're created to the current animation Uh current anim method now this is Con that's this is going to be called when the game object is going to create so that's why we can actually start using them here so here this current anim allows us to know uh to check what is the current animation so if the current animation is not the jump animation then um wait a minute we want to play actually we can use the other uh method that is available for all uh game object that uses this Sprite component it's going to be the play function allows us to play the play Method sorry that allows us to play uh animations so here I'm going to play the jump animation all right so if you remember the jump animation is what we we defined earlier on in the uh where is it the Kaboom loader. JS so loader load Sprite player and here it is so from frame 51 to 51 so it's basically just one frame and you know what actually I realized this you could just have um set this up like that one frame and instead if it's one frame you don't need to um have all this you can just have one like that all right so let's do this if if the player I press the X the X key we first check if the current animation is the jump animation if it's the case if it's not the case we play the jump animation uh that's important because if the player press more than once the X key we don't want to cancel it but it doesn't really matter in this case because the animation is one frame so even if you spam again uh it won't matter because the the same frame will play however this would have been useful if the jump animation has more than one frame so I'm going to keep it in in case you want to modify the jump animation to have more than one frame and then finally we just call the double jump component and this is going to take care of either allow uh making the jump for the player so if the player is allowed to do more than one jump they're going to be able to do and it's the double jump component that takes care of that uh if you're new to Kaboom by default you also have the jump component so this jump component is unlimited so don't use it uh if you want to uh use this double jump mechanic uh uh one thing if if you use the jump animation uh the jump method what you need to do is check if the player is grounded so there is the is grounded method on every game object that uses the body component and by checking you can actually allow then the call for this to jump uh just for your information you can look at previous tutorials usually by default you implement the jump mechanic using the jump component but this is a special case where we actually want to allow more than one jump as part of the ability that the player unlocks after beating a boss here you could have decided to have a switch case statement but since we only have two cases I'm going to just go with one uh if statement so the next key is going to be the Zed key now depending on if you're in European keyboard uh The Zed and X key might not be the same in the same place as the quy layout so in that case uh either in Kaboom Jaz you cannot have the uh keyboard layout independent Keys you cannot set that on the on key press so as a as a workaround uh to this what I would recommend is maybe um allow the player to remap the keys in in a settings menu that that you can do all right so if the Z key is pressed and here we can also check so the reason this is in another if statement instead of being on the same one is that we want to allow the double jump if possible even if the animation was already playing but for this case if the Z key is pressed and the current animation is not on attack current anim is not the attack only then we will allow the attack to go uh otherwise yeah because the attack is already in motion if not the case and we also want to check that the the player is grounded so this is something that is particular so might it might sound strange why would the only be available on the ground well the reason for that is that the assets the asset pack doesn't have animations for jumping attacks and I didn't feel like adding an animation so uh just for the gameplay not to be weird uh the animation not to be weird I just decided you know you can this robot robot character that we play can only attack when they're grounded so what happens when an actual attack is fired so here is the logic uh we're going to you need to write this logic here so so first of all we're going to set the is attacking property to being true during the attack we are also going to create a new game object this this time around this game object is not going to be apparent of the map the reason for that is that um actually thinking about it it's not necessary um yeah I should have probably never mind never mind this game object is going to be a a CH a child of the game object the player which is a child of the parent so never mind we use the ad function the ad method to create a new game object it's going to be the hitbox for the sword attack so the way we're going to implement this is that when the player attacks we create an invisible hitbox that is uh that if the enemy it collides with it then we register an attack uh and we deal damage to the enemy so here I'm going to set the position of that game object to be this first flip. X I'm going to explain this line of going in an instant uh let me just or write it out so here we go so what does this do why why I'm doing this so flip X is a property that is available on all game objects that uses the Sprite component what it allows you to do is to flip like a mirror the the sprit is the sprit and the Sprite and uh that what that means is that uh instead of having a left facing Sprite and a right facing Sprite you can just get away with one and then just flip it around so if the flip animation so if the Sprite is facing left uh or yeah because by default the Sprite is facing right if you look at the images so if by Def if the the flip X attribute property is true that means the player is now facing left that means we need to move the hitbox to be to the left and that's why I have this Turner operation that does this it will subtract minus 25 to the current position of of the of the hitbox which is by default since it's a child of the player it's going to its position is going to be relative to the player so minus 25 is relative to the player H otherwise it's going to be zero and 10 so 0 10 is what looked good so the the hitbox is going to be drawn from remember the top left corner every game object by default is drawn by the top left corner it's only when you specify with an anchor component uh Center Etc that you can Center that instead of being drawn from the top left but for this uh the attack hit boox we don't need that all right then the second game object is going to be the area component so the area component is going to have a specific shape so here again it's the hitbox uh I'm going to use the rectangle it's the simplest shape here we don't need an offset for the position and we're going to make our uh sword hit Box 25 by 10 this is what looked good relative to the animation and then finally we're going to also have a tag so the tag is going to be not here outside here sword hitbox which is going to be used to create event listeners that listens on collisions with this particular tag all right we have this and then of course we need to play the attack animation again defined in the Kaboom loader that we did earlier on and then here we're going to have a on anim on anim end which is a event listener offered method offered by Kaboom for every game object I probably used a Sprite component and what it takes is the it gives you actually the animation name and if and then you can write some logic if the animation was the attack then you could we can first get the sword hitbox sword hitbox the way you can get a game object by its taging is by using the get function uh method function actually this is a function from kabo and we pass in the tag and since this sword hitbox is a child of another game object that means we're going to have to use recursive recursive true and the get meth function gets all game objects with this tag that means if there's more than one it's going to get and return an array so because it always returns an array even if there's only one I'm going to just pick the first element there's only any way going to be one uh sword hitbox created at a time so if the sword hitbox we first get a reference to it because we don't have access to this actually you could have decided to create another property within the uh here within but uh since we destroy that game object it's better to just you know use the get function get the the current sword hit box that exists and then destroy it so here we do this and then if only if the swords the sword hitbox actually exists because sometimes uh the sword hitbox might already be destroyed before a new one is created if the player hits the attack key again so in that time sword hitbox will be undefined so that's why we need to guard this with an if statement otherwise it's going to fail so here I need to and then only if sorry only if the sword hit hitbox exists then we can call the destroy function offered by Kaboom to destroy game object and we pass the reference to that game object and that's it and one thing we want to do is set the is attacking attribute now to being false since the attack is finished and uh we want to play the idol animation Back by default the idol animation always plays uh all the time when the player isn't doing anything so even after an attack we set it back to Idol only and then when the player decides to move or do something else then we will play other animations so this is our first control Handler uh and let's do our second one our second one is going to be again I'm going to call I'm going to push it to the array in much the same way this time around what I'm going to to do is um do a key on key down instead of Onkey press Onkey down and Y Onkey down and then again pass the key here and now here if the key is either left uh if the key is left so if it's the left key is is down and the player is not attacking this again it makes no sense uh gameplay wise it might be strange a strange gameplay decision design decision but as I said because I do not have the animations for the left and right attack As you move and it just looks weird because the the player is basically standing still and attacking so that's why I made sure that uh you can only attack when you don't press any other Keys except the attack button so if key equal equal left and uh this is attacking what we're going to do is we're going to have another if statement if this. current animation so this again is the animation guarding logic so if the anim the current anim is not the Run animation and we also need to make sure that the player is grounded before we play any Running Animation because uh otherwi running while in air is kind of going to look weird so because of that we need to use the is grounded again is grounded is a method offered by Kaboom for all the game objects that have the body component uh okay so we have that and uh if that's the case we can do this play and then actually play The Run animation so we have all the conditions to play The Run animations but we again this is an if statement within an if statement because we can conceive of a case where we want the player to still move even though we don't want to reset the Run animation because it's already playing so here we go and I'm going to make sure that you need to make sure actually that the flip x value is is false because the way that flip X works is that if you set it to True your player is going to be mirrored all the time unless you actually set it back to false and because the by default it seems here that the the the player is actually facing left by default and not right No actually that's that's contrary it's facing right so this should be true we want to always make sure that the flip x value is true so that the player is flipped when they press the left key and in the other F statement where it's going to be the exact same logic but for the right key we're going to make sure that the flip X is always true always is false set to false so that the player will return back to their original orientation I guess and then finally for moving the character we can just call the move function method again this move method is offered by all backa Boom for all game objects that have the body component and here the move uh method takes two prams the first one is the speed in the x axis and the second one is the speed in the y axis you want to go for because we want to only move left and right we're only going to do a negative speed value and then zero for the y coordinate so here we have the speed here defined here so we can only only need to modify the speed in one place and negative because we want to go left so the value of the the speed should be negative all right we have that and we can return early we don't need to go further down and the rest of the logic is the same thing but for the right uh Direction so here's the same thing you don't actually need the return statement only if you were to want to have uh some extra logic here but I'm going to keep it just for yeah consistency so here it is uh the second one just copy the code it's the same logic just two values you could um maybe have reusable block here um yeah you could have some reusable logic but it didn't didn't feel worth it so now that we have this I'm going to save and then I'm going to have the last uh control Handler so this control Anders and then push this time around is for when the player releases a key so to do that we're going to do on key release and then we don't need to actually check which key is released we want to run this Logic for any keys that is released so if this current animation okay this is going to be uh really tedious to write that's kind of necessary so I'm just going to paste it here and go over it so this is the logic so we want to make sure as long uh when the a key is released any key if the player is not idle uh if the current animation is not idle the current animation is not jump the current animation do not fall and the current animation is not attack if if any of those animation are not currently playing then we go back to the idol animation and I think that's it now let's go back to the um uh yeah let's go back to the main.js file uh actually no to the room one. JS and let's create our player here just so we can see something on the screen so what I'm going to do okay I see why I created the set position let's create our method here to set the position it's actually going to be used so set position X and Y value and then ah put page transition and then here so this position do X we set the x new X position this position doy we set a new position all right uh here we're going to remove the initial position here as well does not need it and here we go all right in room one what we're going to do is right after setting the map colliders I'm going to actually Define the player here and add it to the scene but without specifying a um a position so here I'm just going to call actually you don't need that you just call the make player function from within pass in K like that so when you use the make function you only need to call the add method on top and we actually actually need to add this as part of the map so now that we have a player created let's write the logic for the positions so in much the same way here I'm going to create another const I'm going to call it positions and it's going to be an empty array and then here instead of breaking I'm going to have a continue and I will have a second or first if statement that checks the layer name for position positions and if that's the case then we going to push to the positions array push um yeah going to push the layer dot dot dot we're going to spread the objects here so the spread operator uh look it up it allows us to take an array and then spread it back into another array without like having an area in an array so you take the element of one array and you put that into the second array uh rather than putting the the first array inside of the second so it's it's the basically instead of having this you'll have this and then every element one two so imagine three and then one two three so if you were to not use the spread operator like this three dot this is what you would get but because you use the spread operator it takes the elements of the first array and puts it inside of the second hope this was a clear explanation in case you're not familiar with this uh syntax okay so positions push there objects okay and then we should have all of our objects uh so I'm going to continue here as well so here for now this is not necessary okay so now what I'm going to do is for const position of positions and then here if the position for now let's do it simple if the position is of the player U position. name is the players is how we detect the player pin so this one if you remember uh here we go so here it's named player so by checking for the name so if it's the player name what are we're going to do is we're going to have the set position call to the set position method and we're going to take the data from this positional pin and set it as the position for our player now we also going to set the controls by calling the set controls method and for now that's it so if I look at the result let's see what we get presenter and we have our player and our player can move can it jump it can jump but this time yeah you see the animations aren't resetting properly because we didn't have we didn't have a we didn't add yet the handlers the the um not the handlers the events uh we going to see in a moment what I mean by that so one thing also if I press F1 you can see the headbox how it is positioned Etc and when I use the sword you can see how the hitbox change direction all right now that we have this I'm going to go back to the player set the events so the events are things it's a new a new feature that I've discovered in cunas it's not actually new it was probably there but it's new uh to me so uh okay be before doing that yeah okay so set events this is the method I'm going to call and within this we're going to set a bunch of events uh so onfall is an event offered by Kaboom it checks for when the player Falls after jumping and and this is where we're going to just play the fall animation when that happens so the onfall is something offered by kabo this on fall off though is another event offered by Kaboom but this time around uh those events are all specific to the game object so it's not a Global Effect uh event onfall off the different is that it's for when the player falls off a platform that means there there was no jumping before that here again we need to play the fall animation now we also have this on ground which is another event offered by Kaboom and when the player is in on the ground we want to play the idol animation and then finally when actually it's not finally there's there's a bunch of others but for now uh there is this the onhe head headbut on headbut event which is when the player hits his head on a platform or uh when the player hits um an obstacle with its head so for example when the player jumps and hits the ceiling of a level then we can this event will fire and here we're going to play the file fall animation so now let's just test this out so I'm going to go back to Mains I'm going to actually room one. and here I'm going to set those up so player. set events and now if I go and check the result hit enter if I you see the animation are now perfectly correct and then if I hit so this is a oops we don't don't have the camera system working yet but here is the natural progression we go if you hit headbutt immediately the fall animation will play and that's that we we have a bunch of other controls and that looks good uh now we want to make sure that the player can pass through uh these platforms so we're going to create another method I'm going to call it um what's the name I'm going to use it's going to be enable pass through so maybe where should I put it um okay let's put it right here so enable enable pass through through and here we go and here how to do this feature is there is something in Kaboom a method called the on before physics resolve what it does it gives us the Collision that happens as the first param here and then you can check for that Collision so if this Collision uh is a specific Target so if the Collision is is with pass through which was the tag you remember we had for those specific uh platforms where we want them to pass through uh that we set up in tiled and then add it to when we create the game object in in the set colliders uh method function and then here we make sure that the player is jumping as well and this again is a method offered by Kaboom to know when the player is jumping so and then if those two conditions are met so that the Collision is supposed to be with a pass through is happening with a pass through and the player was jumping we want to prevent the resolution of the Collision that means we don't want the Collision to actually take effect so that's why we call the Collision do prevent resolution okay so once you call that uh I think that's it the the feature is implemented for more details I have a blog post regarding this uh so go to my substack for that so if I go here to room one and call the player do um set pass through through method uh uh enable pass through not set pass through actually enable is a better name but set that would have worked as well so if I do this press enter and then let's try it out even though the camera doesn't work you can see I can pass through the platform and even here as well but uh here I cannot jump enough anyway so so here we go but when you're going to be able to double jump you should be able to pass through that platform as well all right um we have everything we need for our basic player moov there is a bunch of logic when it comes to dealing and taking damage that we're going to write later on now okay let's do the camera system so uh for the camera system what I'm going to do is we're going to have to go back to our room 1js and the same thing with what that we did for the colliders and positions we're also going to need that uh but this time around uh yeah we also going to need to get the um the colliders for the cameras uh the way I did it in my uh yeah that's strange um okay it's going to be a bit different um so let's go to room. utils and write the utility for that because it's going to be used for both the um room one and room two so here I'm going to create export a function this uh always make this mistake function set um set camera controls and then here we're going to pass in first player first Decay the for for accessing all the Kaboom functions the player the map and the actual room data and then here we're going to need first of all actually never mind this is not the this this function is going to to be useful and it's going to be mostly used to control the camera so I'm not going to write the body of it right now what I'm going to do though is right below I'm going to write the function for the camera zones so the camera colliders I just call them camera zones and we need to just have three params which is like we did with the colliders it's it's basically the same thing so we're going to have three param the first one is the kabo context the second one is the map object and the third one is going to be the cameras in much the same way that we did for the colliders so let's assume that we have all those three for this for the time being and then we will um uh write the logic for that in room in the room one. so we have a for Loop and then we have we're going to get the camera of cameras which is our colliders our data for those colliders that we had entitled and then here for the cameras for each of those camera colliders uh data we have entitled we're going to create a camera zone game object that game object is going to of course be added as a child of the map and we're going to have basically the same exact way we did for the um collider so I'm just going to copy and paste the code here and explain over it so an area component which is a rectangle with the width and the height and collision ignore being the collide with the colliders since the camera really don't have inter in collision with themselves we don't need to add a tag for cameras um okay so now the reason I created this and stored it in a camera Zone constant is to have our set our first event listener which is going to be our camera on Collide so when so I'm just going to copy and explain here so on Collide is a method available all game objects that have the area component so here here how it actually works so you have the your first game object you have its meth method the on Collide and you can pass in a tag as the first param which is what tag you want uh what game object with the following tag you want to listen on uh when when when regarding collisions in regards to collisions sorry and the second param is the function that is going to fire when that event happens so here when the player collides with the camera Zone we're going to run this logic this logic is simple we get the current camera position by using the campuse method uh function offered by Kaboom uh which returns in Vector 2 that means we can have access to X and Y properties for the camera position so we make sure that if the uh the X position of the camera is not equal to camera properties zero. value so okay so what this what is this so this is if I go to the export uh okay so the room one. Json maybe room two so let's go to room two because it's smaller and easier to uh detect parse because of its smaller nature so here in not positions but in we have positions okay in cameras you see here the custom property that I created called cause Y is is added to a new properties tab here with the this array and in that array for each new property you add it adds a new object with the name the type and the value since we only have one uh new attributes and I don't really need to check for the name of it I just decided to uh access the first element and access directly the value without having to check for the name in case you want to expand this game further and want to use more proper custom properties make sure to check the name first before accessing the value okay so here I go and then details so we get the value which is going to be the actual new camera position if you remember here uh when I click on the camera Zone uh campas Y is the custom property with a value that value uh is basically the the value we want for the camera and here we're going to use a tween so a tween is a way for gradually changing the value of something uh using a function a mathematical function easing function here we using a linear easing function so the tween in kabon JZ takes a uh 1 two 3 four five pams the first Pam is the uh the original position but actually no not just that the reference to modify the value so the the original value but a reference to uh the game object um or the thing controlling that original value um actually never mind that's not true it's here we do the modification so the first Pam is the initial value the second Pam is the final value you want and the third Pam is on in how much time you want the trans the in how much time you want the transition to happen so here I want to the transition to happen 0.8 seconds from this initial value to this final value and the fourth param is the function that will replace the uh the gradually to the new value so here Val is called multiple times as uh following this function's pattern the linear function and for each call it has an intermediate value between this and this that progressively gets closer to the final value and here uh in Kaboom to modify the camera position you can also call the Campa meth function and then pass in as the first param the x coordinate and the y-coordinate since we only want to modify the Y value of our uh camera we will simply put back the same uh x value X position for the camera and just tweak the the just set the new uh y position instead by using this so value here this is an arbitrary name you could have decided to name it however you'd like and then finally k.s. linear are the various easing functions you have access to if you look at the documentation you can have sign sign in sign out Etc linear is just the one I decided to use here uh it's the one looked good to me all right we have this and let's go to room one and here again we're going to do the exact same logic we did so const cameras and then empty array and then here we can either do it like that if layer. name equal equal cameras what you're going to do is or maybe you should do this on top it doesn't really matter that much in the end so if the layer. name is the cameras what are we going to do is we're going to push to the cameras array and spread from within layer. objects which is again going to give us the collider the the collider data for the cameras and then here uh now for the actual usage where did I use this I'm just going to make a call to set camera zones uh maybe right after this doesn't doesn't really matter so I'm going to do this here actually it probably is better to call this here so set camera zones from here K dot map do uh cameras here we go okay let's look at the results press enter now if I do this the camera slides downward if I drop down again it follows everywhere maybe not the left hand side because we only control the Y position we need to actually write the logic for the exposition so the exposition we just want the camera to follow the player and that's the role of the first utility function that I was about to rout uh right is called set camera controls uh so here what we do the reason we need also the room data because there is specific data that is allowed going to allow us to bound the camera to certain limits so here in room. utils let me just check it out okay so how we're going to do this is we're going to use a onupdate method Kaboom method so on update is called every 60 frames it's where you can write more granular stuff so here if the state. current and then player in boss fight then we return early why why we do this because when we're going to have the actual boss fight we want to um make sure that uh the camera isn't controlled is fixed basically uh to only the room the boss battle room here I'm just going to import the state from the global manager so player in boss fight I think that was this date uh let me let me look is boss defeated player in boss fight yep and here player is in boss fight I made a typo error later on so fix that in State Global manager Global State manager so here if state. current if players in boss fight we just won't run the the logic uh the what comes next because we don't want actually the camera to follow the player and then the next stuff that comes right after I'm going to copy and paste it is if the map position X is um plus 160 is inferior is superior to the player position then I'm going to clamp the camera position to be stuck at this value this is so that when the player cannot go too much to the left uh the camera cannot go too much to the left to the point that we can see outside of the the bomb the bounds of the map and then finally the last um yeah the last if statement here we need is this so if the player position. X is superior to the map position. X plus the room data. width this is the actual width of the the whole map multiply by the room data. tile width which is supposed to be like 32 or 16 minus a certain value this is what I looked good then we're going to prevent we're going to clamp the the camera but to the uh to the left uh to the right so it won't go past a certain point to the right and that way we will never allow the player to see outside the bounds of the map and otherwise if those conditions are not met so we just make sure that the the camera just follows the player uh from the x axis but the Y AIS is remains intact so that's why I only modify the x x coordinate and not the Y so the Y for the Y we just take the current camera position all right let's check the result for that so here we go if I move to uh maybe I should drop down and then okay I forgot to actually call the function so set camera controls needs to be called and where we're going to call it is in room. one. JS maybe right after here okay but this is an issue because the player isn't yet added to the Z team so we need to First wait for the player to be declared and then do this so now if I look at the result press enter set camera is not defined I forgot to import it here set camera controls now everything should work so let's look at the result press enter and now the camera follows us that's nice so if I drop down it also follows follows us on the Y AIS so here is we cannot go past this point we will never see the bounds the outer bounds of the C of the the map and then even if I go here everything works all right so yep uh we have the camera now done and H this is not done I fall so that's something we need to fix uh why let me check let me debug why why is this an issue if I go here we have a collider we have a collider but not no body component so we need to go back to vs code where we defined the in room. UTS the set map colliders if it's yep here we forgot to add for the polygon colliders the body component with is stat property because at the end of the day it's a wall type it's an obstacle so now if I look back at the result press enter and it should hopefully work so here I drop down and yep it works all right we have the camera system up and running that's great we can pass through those platforms as well let me see if I can go back here so now what is is left is to do the uh start implementing the enemies after the enemies the boss fight and after the boss fight the linking with the other scene so for now if I go here there's nothing that happens and I I'm out of bounce so now it's time to work on the drones so it's an enemy type that will follow the player and explode when entering in contact with the player so in the entities folder I'm going to create a new folder I'm going to call it enemy drone. JS here we're going to follow the exact same pattern I did for the player which is create a function that is going to act as a Constructor I'm going to call it make drone here I'm going to you as the first param set the K the context and then as a second param I'm going to have an initial position because here we're just going to create the Drone and set the position immediately um then here we're going to return a make uh call which is going to create the the game object but not but not add it to the scene and then here we're going to have a bunch of components so the the positional component is important here with initial pause uh we're going to need to have a Sprite component the Sprite component is going to be the Drone Sprite with the anim flying this was defined in the Kaboom loader function by the way uh kaboon loader file sorry and then next we're going to need to to have to set the hbox so the area component is going to be used here we're going to have a shape with a new k. rectangle and then k. Vector 2 we don't need an offset really 12 by 12 would be a good H box the anchor is going to be centered this time around as I did with I think we did the same thing for the player I don't remember and then here for the body here things are going to be different we're going to set the gravity scale so gravity scale is another property you can set uh within the body component and I'm going to set it to zero so basically we want our drone to have basically not be affected by gravity at all so it's going to be floating around I'm also going to use a a new component that I haven't explained yet called the offscreen component and set the distance to 400 so this what it does is that when uh the charact uh the sorry when the Drone is going to be off screen so that means as the camera is crawling and the player is moving around uh let's say we have a drone that was following the player and then the player was able to get away basically and what we want to do is that if the distance between the uh the camera the screen and the player uh the Drone is at at four 400 uh units I guess pixels whatever then we're going to respawn we're going to not respawn but reposition the Drone to its original position so here we just using the offscreen component then later on I think we're going to use some of the meth event listeners that comes with it so when you use the component you have access to a bunch of methods that you can use later on so not right now and then here we're going to play around with a state machine which is basically what we're going to use to uh code the AI so I'm going to explain what a state machine is in an instant but for now let me just teach you how to use the state component so the state component starts with a first state States here are just arbitrary names that you decide for yourself I decided to create one two three four five states here and I'm going to paste them has to not waste too much time so here are all the states I have decided to create and the you need to specify a default State and that default state must be one of the states you have decided to uh create here and the default state I'm going to pick is going to be the patrol right so what what is what is a state machine so a state machine is a way for you to code an AI uh so if I open up the excal draw and try to do a schematic so we have imagine you have a bunch of nodes and then for each of those nodes you have there are states Associated so Patrol Patrol right okay that's too big uh maybe um okay zooming out so I'm going to just here so we have our first state patrol right we have I'm going to just copy that around Patrol uh Patrol Patrol left yeah that's kind of strange why it's behaving this way Patrol okay that's that's strange okay my point here is that by having those names you're able to Define behaviors okay so here let's try to explain without the diagram so those are names that are arbitrary and for each of those names we're going to define a couple of events that happens when the entity the game object will enter or be in those States so here I have decided to name Patrol right Patrol left alert attack and Retreat and for each of those state that I've decided to name I'm going to write logic that is specific to them so when the the Drone enters a specific State a specific logic is going to run while they enter in the state while they're in the state and when they get out of the state depending on the state we want uh depending on the state we're going to do different things so let's just add the health component I'm not going to re explain here but basically setting the health one point one Health Point for actually we set did we set the health for the player um did I do that yeah we did okay so just I'm going to just set the health to be one and then add a tag to be of drone and then here is going to do the AI coding the state Etc so I'm going to you're going to understand this more in a in a moment okay so here are a few properties I want to Define so I'm I'm going to have a speed of 100 a Pursuit speed of 150 so this speed is going to be the one used when the player is is uh when the Drone is following the player the range is going to be 100 that's the range in which play the Drone is going to start is patrolling and is going to start following the player if they detect the player and then here I'm going to create a method called set behavior and it's where we're going to define the logic related to uh the state machine the state uh yeah the state machine so the first thing I want to do is I want to get the player because I'm going to have to to do a bunch of things compare the distance between the Drone and the player and one way to do that is just to have a constant called player and then use the get function to get the player by uh using the tag and as I explained earlier since the player is going to be added or is already added as a child of the map object we need to use recursive and true property and so for it to work and then here I'm going to set the we only want the first first element there is only one player by default get always gives you back an array okay this is where things get interesting since we used the state component we have access to a bunch of methods called the on state enter method it's an event uh listener that you pass in as the first par the name of the state you want to Define an event for here Patrol right and then the second param is going to be the logic that is going to run when the drone will enter this this state so here what I want to do I'm going to use an ASN weight here because what I want to do is I want to await and then call the weight function in kaboo so here what what it does the weight function basically Will Wait 3 seconds before uh running before running what comes next that's that's due to the await so await you have to wait for it before you can continue on uh I'm I'm not going to dive deeper into the async weight uh I have done so in previous tutorial so maybe reference that I might write a post on this but the reason we're using a waight here is specifically so that we wait those 3 seconds before running any other logic that comes after here within that function then we're going to have a check so if this do state is how you access the current state if if that that state is Patrol right what I'm going to do I'm going to call the enter State method again provided back aoom if you use the state component and I want to enter enter the patrol left State now this might sound strange you're already in the patrol right State why would you check that well actually you don't know because what comes after is another event listener and this one is called on state update and it runs every frame uh every 60 frames every frame 60 frames per second yeah every yeah I think every frame all right so here we have the onate update uh Patrol right so what is this it allows us to create an event listener on a specific State while that will fire the second param which is a function that is going to run all the time during the the time that the Drone is within that state so here while we are so imagine this is while we are on in the patrol right state run this logic and run it will run it every frame so here what we're going to do is to have an if statement that will check this position distance so this is a method provided by Kaboom for Vector 2 components it calculates allows us to calculate the distance between one positional one vector to with another so here player. is the position of the player and is accessible because we imported the player here and then if that distance is inferior to this do range that means we are within the range of the Drone and this time the the we want the the Drone to enter into the Alert state Alert state and then we return early otherwise we want the this. flip X to be false that means we want the make sure that the patrol the Drone is is facing right and then we want to make the Drone move at a normal speed so now I hope this makes a little bit more clear what we why we do the if statement here because when we enter the state this is this runs once and while we wait three seconds seconds here this is still this is running multiple times because it runs every frame so the the situation can change the state can change within this before we arrive to this line of code so I hope you understand that so just to repeat here it runs once when the Drone enters the state because it's the default State this is also going to run once without having to call an enter state by default and then here it's going to wait 3 seconds before moving on to this line however while we do that this state update is running multi every frame so in that time during it runs every frame the Drone is moving as long as the player is not within the range as soon as the player is within the range we enter a new state we enter the Alert state that means by the time that after the 3 seconds elapse we arrive here this state could potentially no longer be uh Patrol right now we're going to do the same thing but for patrol left so I'm just going to copy and paste and and do a mention a few things so here we have Patrol left same logic but instead of Patrol left here the right it's left and here it's left and the right and then here the the only difference here is that we want to flip because by default the Sprite for the Drone is facing right so we want to flip it to for it to face left and we move to the left by adding a negative sign to the speed so now it's time to define the logic for the Alert state so on state when we enter this Alert state we want to run the following logic we want to wait one second before initiating a Pursuit of the player once we have waited we want to check if the distance between the Drone and the player is still inferior to the range if that's the case we can enter the we're going to enter the attack state so attack is basically following the player you you could have named it suit instead so attack State and then we return early otherwise we're going to enter the patrol right again and reinitiate the loop of patrolling normally left right left right left right so just to diagram this imagine you have patol right here hope this works now we have have Patrol left what's the isue okay okay for some reason okay now it works so we have Patrol right Patrol left and then we have alert so here's the Alert state alert and then we have have the attack state so maybe better I put it here attack oops all right so let's diagram this out so initially we have the patrolling so patrolling is basically going from Patrol right to patrol left and from Patrol left to patrol right however sometimes if the player is too close we go into the Alert state so while patrolling right or patrolling left if the distance of the player is the the distance is the distance if is if the Drone is close enough to the player then the the Drone will enter the Alert state and then after one second if it's still the case the Drone will attack so hope that that illustrates the situation so we have that and then for the attack State we're not going to need to Define an on state enter but we only need to define the on state update for it because we just want the action to immediately go uh the movement the the following of the player so here if the player this position distance and then player position if that is superior to the range that means as soon as the player is able to get away is getting far enough away from the Drone we will enter back to the Alert state and then from the Alert state the after one second if it's still the case where the player is far enough it's going to go back to the patrol right State and then return early here now on the other hand if this. enter so if it's not the case uh wait a minute uh no never mind so we return early yes but now it's time to follow the player to attack him so this flip X is going to depend on the where the player is so we can just have this a Boolean expression where we check whenever or not the player position is inferior to the the position of the Drone if that's the case then it's going to to be true and if it's true that means the the player is to the left so that means the Drone should also be facing left same logic for the right so if it's false that means the player is to the right of the Drone and that means the Drone should be facing right and then here I'm going to use the move to method offered by Kaboom on body on objects that have the body component and you can specify destination so here I'm going to specify Vector 2 I want the player positionx but for the player positiony it's going to be+ 12 just to have a little bit of a gap and then I'm just I'm going to explain everything let me just finish typing and I'll explain things so Pursuit speed okay what happens here so move to is the function from Kaboom it takes two pams the first param is the destination the second param is at what speed you want the Drone to move to towards here uh instead of just taking the exact same position having a bit of an offset make sure that the the the the player the Drone will actually um how do I say will uh we'll try to collide into the to go outside of the player so um it's a bit hard to explain let me make a drawing so by having the target here so imagine this is a Target and this is the player by having the drone target this we we we are making sure that basically if the Drone arrives to the player it's going to collide with the player however however if we were to just have the exact same position here so depending on the situation the Drone could stop just right here and remain here so the Collision would uh would never end that that would be the thing because you have un Collide and then the Collision would never end well what actually never mind it's not the Collision would never end basically um I think that's this the reason I did it initially but thinking about it again uh maybe it doesn't make any sense so so you know what instead of trying to to justify it let's just remove it for now and then we'll see we'll re readit back when we see if uh if it causes any issues all right so we have this and then we have the attack State everything and then that's it that's basically that's the the AI logic now we also need to set the events for it so I'm going to create another method called set events by the way set events Etc and set Behavior are just methods that I created uh in which we use a bunch of methods offered by kabo so for set events I'm also going to have a reference to the player so we're going to have the exact same logic recursive true remember that because the player is a child game object of the map and then here we're going to have the this. on Collide which is an event listener provided by Kaboom when we collide with a player we want a few things so whoops not that if uh if the player is attacking uh that mean we want to return early we don't want to destroy the player that means it we want this un vulnerability to the player if however that's not the case then we first hurt ourselves the Drone because the Drone self-destructs and it has only one life so using the heart method which is provided by Kaboom if you use the health component and then here we're going to have a new feature in Kaboom called um well actually we can never mind it's not a new feature here for the player we can also call the heart function and reduce the Life by One why we do this uh how we can do this because remember remember the player also uses the health component that means it comes with methods to manage health so here by calling hurt it's a nice and easy way for you to deduct uh life uh from the player now here on anim and again another event listener provided by Kaboom we want specifically to check if the anim that ended was the explosion the explode anim again these animations are all imported at the beginning of the project in the Kaboom loader file if it's the case we just want to destroy the the Drone now here this.on explode so this is an a custom event and it's a feature in Kaboom that I discovered recently and makes your code very how do I say more clean so you can Define custom events by using this on function I have written a blog post about it again if you're interested I will put Link in the description hopefully if I don't forget so yeah and uh here so you the way you define custom events is you use the on method here and then you decide on a name and then the second param is what what is going to run when this event is triggered you can later on you use the trigger method to trigger a specific event I'm going to show it to you here I'm going to play a sound so you play a sound by using the k k. playay me function and passing in the name of the sound so here boom uh where does this come from it comes from the K Kaboom loader we imported those sounds initially here so here here is all the sound Imports all right then what we want to do is not only play the sounds when we have we trigger this explode event we want to also have a collision ignore we want to avoid the the Drone from colliding multiple times with the player by just like removing any uh making sure that any collisions with the player is avoided is negated or ignored when the Drone is exploded because we have already deducted life points one life from One Life Point from the player so we don't want to have a situation where we do this multiple times because the the Drone is is still colliding with the player while it explodes we also want to use the unus method which allows you to unuse a component uh that you added to a game object initially when you created that so here you can just use a a a string and refer to the name of the component so I want to unuse the body component and finally I want to play the explode animation so here be careful and to not mistake this and this this is for playing sound and is uh a method from Kaboom and this is a method offered by Kaboom but from the game object so this is for playing animation while this is for audio now here we're going to have another on Collide here we're going to have another on cide and then yeah so we have a sword hitbox so this is the logic we want to run when the player hits the with the sword the Drone and here we're going to do only hurt the Drone itself so by having the hurt one here it's going to reduce One Life Point basically similar to this but we don't have to worry about the player logic and then here is when we Define the so here it's not a custom event this the hurt event is a specific already existing event offered by kaboom what it does is that it offers um allows you to run something when you use the her function so when I say hurt when I call the hurt function it's going to trigger the hurt uh event also offered by kabo so here what I want to do is that when we reduce the life point of the Drone I want to check if this. HP HP gives you the current HP of the game object that uses the the health component if it's equal equal to zero so if it's equal to zero I want to trigger the explode custom EV event that I just created earlier on which is going to take care of exploding playing the sound and making the the Drone actually explode with the animation Etc and then that's uh that's it uh one thing left is this on exit screen on exit screen which is offered by the um the on offscreen component allows us to have this method available so when the the Drone is no longer visible on screen if this. pause. initial pause is superior to 400 then this uh I'm going to explain everything this do pause is equal to initial pause so here what it does um did I have the initial pause right Define oh I made a mistake at typo here initial POS pause position so what does this do well here is that uh when the off this will run when the distance uh the player is off screen with a distance of 400 and then here actually I don't think you need to have this you can just set the position to being the initial position basically respawning the Drone where it originally were was and that's it that's the whole Logic for the Drone so let's actually use it now uh let's place the so here I'm going to go in room one. J and then room one. yes and then here yeah so for room one. yes for the positions layer so here so I'm going to have a continue here now if the position type was drone remember for classes entitled you can access them access the the name with the type instead which is kind of strange but it stopped I think class is probably a reserved keyword anyway so here position. type equal equal drone we're going to create the Drone game object and but place it as a child here I'm keeping a reference to it because we're going to do some going to call the two methods we created so here map add and then here make drone and then here pass K and then position and then here we need to pass a vector two with the position dox and then position position y and then drone. set be Behavior which is the method we defined and then draw drone. set events all right now that we have this k 2 I think we the Drone should appear in our game so I'm going to refresh hit enter and and then we have a a l drone so let's see if we can yeah you see that's the issue that is that the the Drone remains kind of stuck above the player but not exactly colliding fully with the player that's why I added a initially here instead of following exactly I added an offset of 12 and now if we look back if I let the the Drone come to me it explodes you see so yep that's a a quirk of the move two method in Kaboom I think and then we have another now let's see if I can attack this one let's see if we can attack okay it's a yep I I was able to attack so that's pretty nice uh so not now what's left is the boss and after the boss I think we going to uh display the C cartridges with which are health pack and then we link the two scenes and then the game is mostly done I think uh we probably have to just add a an intro and Etc by the way if you cannot hear the sounds of the Drone exploding that's on me that's my setup sorry um maybe it's too late for me to verify if it actually recorded it properly but yeah just for your information I on my end I can hear the sounds of the explosions when playing the game so the first thing we're going to implement is the boss barrier so for the boss barrier we're going to go to the room one because it's something that is very like exclusive to this room where the actual boss battle is uh now I think it was in the room etails instead and here when I left the tutu so for the map colliders so if we have the boss barrier map collider what we're going to do is to have the following code so here here so I'm I'm first going to create a constant where I will hold a reference to the boss barrier so first we create a the game object uh that of course is a child of the map now here it's not that interesting but okay let's yeah I'm just going to copy and paste most of the concepts we have already seene so here are the components we're going to use for this object so a rectangle with a width and height the reason I'm using here the W component instead of doing this inside of the the area is because at one point we're actually going to see the rectangle and we're going to set this color for the rectangle for the gate and then the collider X and Y and then ignore collisions with other colliders and set initially the opacity to zero and finally the boss barrier tag now we're going to also have an object where we're going to have a a few methods so the two methods we're going to have is the activate method so this is a method uh which takes care of by using twins it's going to make the uh gate the the boss barrier sorry from invisible to visible uh so here we're going to first set the opacity uh from 0 to 0.3 in 1 second using uh the linear here I have already explained how to use twins here previously uh now here the twi is going to be the camera so as we are changing the opacity of the gate we we're also moving the camera so that we're going to make it we're going to make the the the boss battle arena take center stage and this is the reason I'm not using any await here because we're doing this at the same time so while so when you run this because tween is a synchronous it it will run on its own and then the the code execution will continue to the next one next one even though this is not done yet so that's that and then after this activate method we're going to have a deactivate method as well and for this one I'm also going to paste the code here I don't think there's much need to manually type it so here we have an async deactivate method that takes the current exposition of the player it will make the uh gate uh the boss barrier disappear so here and then it will move back the camera to the player's position and then it will destroy the gate after uh it is uh after it has fully disappeared so that the player can move out of the arena and then here are some other logic we're going to need uh so here this is within the boss barrier but now we have also content outside of it uh I mean not content I mean uh logic to write outside of it on in an un Collide event lessener so when it collides with the player we're going to have it in a sync and here one thing one thing in Kaboom JS is that when you use an on collide with the tag here uh on Collide will pass to the function you use as the second peram the game object that is collided with uh that the tag that the the game object is colliding with so here it's the player tag so it's going to give you the player game object so that means we don't have to use k. getet here so that's pretty handy so here I'm going to first have a current state constant just just as a short hand for this actually it's barely less characters barely less anyway I'm just going to keep it and then here we're going to have a first an if statement and then if the current state is boss defeated true whoops if that's the case then I'm going to set a new state so St state. set and what I'm going to set is here I'm going to this is where it's handy to have the state props enum it makes things less error prone I can immediately just select the as boss defeated and then set that to being true or actually it's not uh it's not that we want to set if the um if the player is in a boss fight so if the player isn't if player in boss fight I should have named this is M but anyway just do not generate any confusion I'm going to do this like that so now I'm going to set that to to be being true uh actually false because the the boss has been defeated sorry and then we're going to make a call to the deactivate method and pass in the player position X now after doing all of that we return so when the boss is defeated we set back the players in boss fight is a player in boss fight Boolean to false we deactivate the boss barrier then if it was not the case then if we also need to check another case if the current state. player in boss fight so actually if now the player is in a boss fight we also need to skip so we won't process the logic that comes after so we have two cases that we want to avoid going further the first case is if the boss is defeated that means means we just want to destroy the gate however if the player is in a boss fight in the boss fight we just want to return early so colliding with the boss barrier will do nothing uh special so now the the case here that we're going to write now the the default case is when the player first enter collides with the boss barrier so when that happens we are going to first disable the player controls so this is something I did not write in the player logic so I need to do that so if I go to player. JS and then from player. JS let's write a method maybe here right disable controls and this is where we're going to use the uh the uh control handlers that we had initially so what I need is simply to have a for Loop that will iterate through the various handlers that we we stored in this Dot control handlers and then cancel them so the way you do that is by calling the cancel method by default all of these handlers have access to that method and then of course don't forget to add the comma here all right so now we have disable control and um there's also another logic I should uh another method I should probably add is called respawn if out of bounds so we want make sure the player responds if they fall uh off the a platform so here I'm going to set three value the B bound value the destination three par I'm sorry the destination name and then the previous scene data and by default it's going to be exit name null so this is going to make sense in a in a moment so actually for now I'm just going to leave it to to do it it's it's going to make sense when we're going to link up the various scenes with each other so now I'm going to go back to the room utils and then from there after having written the boss player Collide I can write um okay first I make a call to disable the player controls because we want to basically Force the player to go through the gate and not not arrive with a situation where the player doesn't uh avoids the gate basically as the gate is sucking the player in it the player is trying to get could avoid it and move to the other direction we don't want to have this situation otherwise you're going to have a bunch of bugs so by disabling the controls of the player and forcing him to go to the gate through the gate if they collide with it uh to go to the boss battle and it's a bit like that in the Souls game once you commit to going through the gate uh there is there is no going back basically and then I'm going to play the idol animation while while we do this and then here I'm going to again have an await for a tween which is going to be responsible for uh changing the player position from this to player Pax but plus 25 pixels so that we make sure that the player goes through the gate we want to do that in 0.2 seconds and here we have the value function that basically do the the adjustments of the value until the destination is reached and then here with an easings linear and then once this is done we are Sav to do player. set controls again so that we give back the player controls uh the controls to the player so this is await so that as long as this is not done we won't proceed forward otherwise if you were to remove that this would run while this would also run so that mean the player could escape and go out of the gate uh yeah out of the Boss Arena while the transition would happen all right now another one so after having the UNC collide with the player the boss barrier we also have the uncollided end so not only can we in Kaboom J know when collide with something but we can know when a collision ends with a game object as well and then here we don't really need to have the player game object here what we want to do is that once the the the Collision is over first I'm going to hold the the current state like that just for it it's handier I guess and then I'm going to have current state and then if the current state is a um player boss fight so if the player is in b a boss fight or current state do so if either the player is in boss fight or the boss is defeated so is boss defeated then we return early we don't do anything and then otherwise we're going to set so state do set so State PR enum to make things less error prone and what we're going to set is the player in boss fight and here we're going to set it to true so that the the boss fight is actually starts and then the boss barrier will activate preventing any while preventing well what actually the activate does is just going to show the the boss barrier and then we're going to assign to the boss barrier a body component so the way you add a component after the fact after having creating created an object you use the use method and then here we want it to be static because it's an obstacle and here we go and that's basically it so now if I go back to the game and hit enter and I if I just go back to the Boss Arena then this is following me yep you can see the Boss Arena is here and I cannot Escape so maybe let me just retry this time around without activating debug mode so that you can have a can clearly see so here we go I'm playing [Music] around then as soon as hit I'm transported and I'm stuck here so now it's time to code the boss battle itself so the boss itself so how we're going to do that is going to create a new file in the entities folder that file is going to be called enemy boss. JS and it's going to take the exact same mostly the same uh uh properties Etc so what I'm going to do is I'm going to copy and paste a bunch of stuff but for now let's uh first write the Constructor function so make boss and then pass in K and the initial position as for the components we're going to of course return a k. make and then here for the components I'm just going to copy and paste the first few components here so we have a state machine with different states we have the idle State the follow state where the the the boss follows the player the Open Fire state where the player the boss starts opening fire from their flamethrower and then the fire state where it's firing and then the shot fire when the the animation to close the flamethrower will play and then finally the explode state which is where uh when the player uh the boss dies and then here we have a mass of 100 and a jump Force initially I made the the the boss jumping as well but I haven't used this anymore so feel free to remove it here it's again the same thing here the animation is burner the Sprite and the animation by default is going to be idle and then the health I gave him 15 points of health and opacity initially it's one but as with a player when it gets hit when the boss gets hit it's FL it flashes so it blinks so now what we have here is our various methods uh so let's first I'm going to copy and paste the various properties as well soy suit Speed fire range and duration of the fire and then right below we're going to have the set behavior and set events so set behavior and set events much uh of the same structure as I did with the player and the drones and Etc so here we go and uh yep um I'm going to before going onward I'm going to just uh Define a reusable function that will make the any game object blink uh as I explained it's when the player or the bosses or the enemies take damage uh except for the Drone because they immediately die when they jump on when they hit you so but for the boss and the player there is some reusable logic we can write and I think I'm going to write a create a new file in the entities folder I'm going to call it enti T shared logic. JS so what does this do it will make uh going to have a single function I'm just going to copy and paste it here and go over it so basically we have a make blink function that takes the context The Entity the game object and then it's time span by default it is 0.1 we can specify a different one if you want so it's an optional parameter and then here um we use twins to make first the opacity go from one to zero in a certain time span and then the reverse so the first one is important to have a weight so that this doesn't run as this is running but the second one there is no need to have no weight because it's the only thing here so hope I made this clear all right so now for the boss if I go to set Behavior Uh I'm going to actually first of all let's add the blank logic to the player so I in the set events here I'm going to add a bunch of events to handle that so for the player remember the heal and hurt events so we can we can use that so this do on heal event listener is something that is offered by Kaboom if you use the health component on your game object so here what I'm going to do is I'm going to set the this the health State uh as follows so State props enum and then here player HP and I'm going to set it to the current so this. HP of the component and then I'm going to trigger uh actually hit here to do health bar bar logic so of course we're going to have a UI element that is going to update or uh yeah so here we're going to trigger a custom event for the health bar we haven't created health bar yet so that's why I just going to put a Todo message here the other one which is actually why I came in this file first is because we wanted to make the player blank when they get hurt so we're going to do that inside of the hurt event listener that of course is offered because we when you use the heart function the heart method to reduce the life point of the player the life the health of the player this gets fired and here this is where we're going to call make blink and should normally automatically import it so if you go upward it should be imported all right so make blink is going to take um K and then this which is the game object itself the player itself and then here in this logic if the HP as long as the HP is superior to zero so if the HP is superior to zero I'm going to set the State of the State props en. player HP and then set to the new updated HP so remember the HP method gives you the upto-date um HP calling the hurt on the player fires this event because not only the hurt actually changes the value the health value but also by having this event we can make the player blink but also make sure to set the state for the global state so that when we move on to the second room it's going to keep track going to have the same health value otherwise everything is scoped so by default the comp uh the the the component HP health is scoped on the scene where the the player is created um actually I think there is maybe a method called stay in boom Jazz that allows you to have the same uh game object stay in the next scene I haven't yet learned about it much but I just remembered that it exists so maybe we could have gotten away with not having to deal with global State like that so something to check if you want on on kabon j.com which is the official Doc site here we're GNA also have a health bar update so I'm just gonna I leave a comment here and then we return early because otherwise we will simply have the following code so in case the HP is not Superior to zero I'm just going to copy and paste this part we going to set the state of the player HP to be the max player HP so the reason for this is that we're basically respawning now you could put this later on you could put this after so that first you have the boom sound then the explosion then the the health bar the health of the player is set to being full health because they were going to respawn and then right below that this on anim end anim go so if the anim is equal equal to explode which was triggered here right above explode what's with the weird spacing here we're going to go back to the same room one scene so it's effectively responding so I think we have this and uh yep we have everything we need so let's save that let's of course save this as well well so now if I look at the game press enter can let's see if we take them if we blank if the player is going to Blink yep they blinked so as you can see all right so let's do the state machine for the boss so much like the Drone it's going going to basically have the same pattern so a couple of this not uh on state update or on state enter so let's start with the idol state so on state update we're going to need here and then so for the idle State what we're going to do is make sure that if the state and then current all right so now we need to check for the current state if the player is in a boss fight so state. current and then player in boss right if that's the case we're going to move to the following so enter State and then we move to the follow so this makes sense because as soon as so when the player is not in a boss fight so that means they're not they haven't passed through the gate we don't want the boss to do anything we want the want it to remain idle however as soon as the boss uh the player sorry and has enters the gate this is set to true and that means that it's time for the boss to start following the player so here we don't really need a actually in fact this shouldn't be a on state update it should be an on state enter oh no it's an update because when the game the the room is initialized the the boss is placed so we need to check this every frame until it actually happens the the player actually enters the arena all right the next uh event we need to listen on is on state the follow event so on state enter follow what we're going to do is we're just going to play the Run animation so so here um so we have the play okay so we play The Run animation and then for this on state update for the follow as well with follow State we're going to in case you didn't copy here are the very State we we're going to use so here so for the follow State uh every frame what we're going to do is we're going to first set the flip x value in much the same way we did for the Drone so if the player position is inferior to the boss's position that means that the player is to the left and that means that the boss should face left that's why we do a flip x equal true because by default the Sprites are drawn facing right now here this do move two so we're going to use the move to again as we did for the uh drones and we're going to again do exactly the same thing so move towards the player position with an offset of 12 here so that uh we don't have this weird case where the player is the boss will basically be stuck with the player but nothing will happen so then here we're going to have a Pursuit speed as well actually in fact I don't think it's needed here for this specific case because at the end of the day even if the the boss gets stuck with the player the player can just move around so yeah now the pursuit speed is the same yeah for this boss for the boss we only have a Pursuit speed so we don't have a normal regular speed like with the drones and uh that's basically it for this logic uh we also o need to add an if statement which will determine if we move out of the follow state so if the position uh of the player position uh no if the position of the Drone um the boss sorry is uh if if the position of the player is near enough the position of the boss and this we we we do this by checking for a specific range so the fire range so 40 so if this distance is this distance is in inferior to 40 in this case what we're going to do is we're going to enter into a new state which is the um open fire open fire State and then for the Open Fire State on state enter open fire and then what we're going to do here is just play the Open Fire anim I made a mistake here it should be lowercase and now after this animation is done we're going to actually have it on anim end here but uh for now we're going to have this on anim end uh logic inside of the set events and not here so let's continue defining our various other states and and then we we will tackle this later on so here we could have um that this on state enter for the fire so let's define the logic for the fire state so what we're going to do here is create uh the flamethrower sound flamethrower sound which is going to be a reference to the sound of the flamethrower which we can play like this remember we imported this sound in the Kaboom load loader. JS file now what we do next here is to have the fire hitbox we need to create the hitbox for that and we're going to basically add it as a child of the boss game object and here again it's the same logic we did for the sword attack for the player just various different values here so I'm just going to copy and paste that to go quicker and then here for the logic for when the player hits the collides with the hitbox again this is very similar logic that we did with the sword attack but this time around we hurt the player and then if the P if the HP is equal to zero we set the state we said the the player in boss fight to being false that means that the player just died and that means simply that they're no longer in the in a boss fight and then here finally we have the K Weight which is going to wait this is another form of the weight variant so here I'm just going to put the fire duration so how long does the the fire attack lasts it's it's a property we created here one second and then we run this logic so the second param is the logic to run this is the SEC another form you could have used a weight here and then did your logic right after here but I I felt that it wasn't really needed to use a weight here because there's yeah we can just use this form and then here what happens is that when the fire duration so when the fire attack ends we will stop the sound so that's why I I stored the the sound here the sound listener reference so that I can easily use the stop method on it which is offered by Kaboom as well and then after we have stopped the sound the player uh not the player the boss will enter the shut fire State now for the Open Fire and shut fire we haven't defined anything for the shut fire and open fire we haven't defined any on State uh enter or stuff like that uh we're going to do this in the set events we're going to actually just in our on adim and event listener just run into like enter those States all right so now uh let's define those uh let's let's define the remainder the remaining uh on state enters on state end and on state update for the fire so this onate State end for fire state so this happens here and then inside of this the we we just use that state to delete the fire hit box so as we did with the sword attack you get the fire hit box and then you check if it exist before trying to destroy it and then finally we have actually we have two two things we have the Shut fire so sorry I was inaccurate later on I said we wouldn't Define a on state enter for shut fire but we actually do here we just play the shut fire animation here and as here the on state update for fire this is uh useful to Simply play the fire animation if it's not already playing as as we go here but here I realized that um we could have just defined this here so so yeah I think this is not a necessary State we can take this line of code I'm going to just comment this out and I'm going to paste it here so we just play the animation of fire right here and like that so now let's go to our set events here again we're going to get the player so as we did actually we didn't do this here so const player k. getet player and then recursive true and then index zero and then here we're going to Define an un Collide here so this time around it's the reverse it's when the boss collides with the sword hit box we play the boom sound and then we hurt the boss so we reduced its health and this is an important part that I referenced earlier on we're talking here about the this on anim end we we going to we're going to use a switch case statement here so if we are in the open fire State we enter the fire state so here open fire if I remember correctly we just play the Open Fire um animation this open fire animation ends it's not a infinite Loop uh the loop property wasn't set to true there if you look at the Kaboom loader. JS file if you remember so if we go here to the boss the burner Yep this the boss so for open fire there is no um Loop set to Tri so that means that the animation plays once and then when it ends it ends that's why we can use a in our code here where is it where is it here that's why we can use here um the the on anim and listener so we do the same thing for the shut fire here as well so when the shut fire animation ends we enter this the follow State and finally when the explode animation runs we after it runs actually we call the destroy method uh function from Kaboom to destroy the boss so the boss has been defeated and then right below that this is where we're actually going to define a custom event called this on explode this is exactly the same thing we did for the the Drone enemy uh so here we entered explode State now here explode State uh we haven't defined it I think uh did we do so the the purpose of this is just to have a state that is different than what is the the other states so it doesn't do anything really but yeah that's uh that's that's that uh it's just to if you we weren't to do this uh it would the the state machine would enter other states and then it would conflict so by having a dedicated state usess state quote unquote we were able to uh not enter this case and remember that here the explode we you need to add it as well here in the the state array at the beginning so what we do here we set Collision ignore to the player for the same reason we unuse the body we play the boom sound again uh we play the explode animation which after it's done it's going to destroy the enemy the boss we set the isbs defeated true state to true we set the is double job jump unlocked to true and then here I have enable double jump uh method we haven't written this so let's just write it out quickly so right it's a two one line basically on line method so I'm going to put it uh maybe at the end of the player so let me collapse this so it's clear like that so enable double jump uh the way you you have access to the num jumps property if you use the double jump component and you can set it to to a number you want and here we're going to set it to two so now if I go back to enemy boss it's going to do that we're going to play the notify sound which is a sound that basically will display this notification box now make notification box is does not exist yet so let's create it out let's create this UI element so I'm going to go here I'm going to go to the UI folder which is empty and I'm going to create a new file so this file is going to be called notification box. JS and what it's going to contain is the following so we first have as the first param the context as always and the second param is the content then here we're going to make a game object which is going to be a rectangle and with a darkish blue or purple color and then we're going to use the fixed component so that it is not affected by the camera we're going to Center the the position by calling k. Center which gives us the coordinates for the center of the C canvas the area component is important here because we want to set the anchor as a center and the method we're going to use is going to create is simply a close method that just destroys the the the notification box and then as a child of that container because initially it's a container we're going to put a text component so a child game object that is going to have a text component that is going to use the glyph mess font that I showed you showed you at the beginning of the tutorial and the size is going to be 32 this is what looked good as for the color of the text this is what looks good and fits with the color pallet uh here area and anchor Center again so that the text is centered and then we return the container so that's our notification box if I go to the enemy boss here we can see the text I have put you unlocked a new ability you can now double jump and then after 3 seconds the we going to call the close method the we defined here so that uh the the the notification box uh is closed so here we just add it to the general canvas instead of the par uh the map because it's a UI element and we just store it here so that we can have access to close we can call the close method all right uh now let's import that properly uh because it didn't do it for us automatically so here import notific make notification box remember to add ajs otherwise you're going to get a MIM type error and oops and that's it so now that we have that I think we have everything we need for the boss and it's now time to test it out so let me just make sure that's the case oh we have one last thing uh one last event so the hurt event for the boss so as I explained multiple times now the hurt event is something offered by Kaboom if you use the um health component and here we're going to make blink the um the boss if the HP is superior to zero though we return early as we don't want to trigger the explode event which will take care of destroying the boss all right and let's import that also import make link and uh that's it yep that's the whole logic so now in our room 1js so in room 1js if I go to the positions here and then here I'm just going to add a continue so the reason I'm adding a continue here is that if for this position we enter here there's no point in uh running the other if statement that comes next so because we already know that it's a drone here for this iteration so we need to go to the next iteration to have a to check for the other entities so if the position here name and then here I think it was boss yeah if we have a boss and of course we only spawn the boss if the state current that uh is I think is his boss defeated is false so only if the if the boss was is not defeated that we will spawn the boss and here const boss we add it as a child of the map and then we call the make boss now that we have the make boss we just put here k. Vector 2 for the position oops I can't seem to write it well and then position X position Y and here and then finally we call boss set Behavior which is going to set the AI for the boss and the boss set event events because it's going to set the the various events for it and that's it and also for the cartridge so the cartridge are basically Health uh but before doing that let's just test it out so if I look I refresh state is not defined okay where is that issue from State not room one okay we forgot to import the state so here uh let's import it here import State here we go now if I refresh press enter okay V okay I forgot Vector 2 uh room one line 64 line [Music] 64 yep I made a stupid mistake here a typo and then if I press enter what I mean state is not defined where an enemy boss forgot to import the state here as well so import State hopefully now it works press enter and yep so now let's play through the game all right all right let's see if we can fight the boss player is not defined come on players not defined enemy Boss line 35 okay line 35 where the enemy boss where's that player to position okay I guess I should have const player equal K do get player recursive true and then here we go and then now if I play the game normally everything should work all right and then here we go yeah the boss seems to work does he follow me yep H State prop enums is not defined so this is probably again in the enemy boss State props enum here we go so if I fight the boss again here we go and then I move forward there you go all right you unlocked a new ability you can now double jump and now I can indeed double jump so okay so the game works all right now what we need is two things we need the health bar and uh y we need to do the health bar and then after that we'll add the cartridge and then after that the only thing left is really the uh the um the room the second room so for uh room one uh actually no for the UI I'm going to create a new file I'm going to call it health bar. JS I think it would be better to just tackle the cartridge so for the cartridge what I'm going to do uh cartridge are basically Health packs and we can just go to room one. JS and then add a simple if statement here is again it's a single line if the position type is equal equal to cart rdge actually we're going to need to create a new entity for that map add and then we're going to add the cartridge here so in entities create a new file call it health C cart cartridge. JS and then here in health cartridge we're going to have a simple um simple component here let me just explain so make CD The Constructor K and then the position and then the position is just set here then we play use the Sprite cartridge with the default animation and then and we set the on collide with a player and then every time the player collides with the cartridge we play the health sound with a volume of 0.5 because the original sound was too loud and then if the player HP is inferior to the max player HP we allow a heal otherwise we do nothing uh we don't heal at either way we destroy the cartridge so if I go to room one now call make cartridge make cartridge pass in k pass in k. Vector 2 and then position X position Y and then that should be it so if I go and test this out we have our c Bridge here let's try colliding with one and you hear the sound so there is not much um let me just test something so there isn't much to do here to test uh without the health bar so the health bar is really key now so I'm going to go back to health bar. JS which we created here in the UI component and then health bar is basically simple as well in not a lot of line of codes so I'm just going to copy and explain everything so we have this Constructor which is makes makes this health bar component uses this health bar Sprite sets the frame to zero because we have three frames we don't have any animations for this one as I if you remember earlier on in Kaboom loader what we had here in the Sprite Atlas was the health bar with a slice y of three that means that we have three frames so so in Kaboom JJs you can just display a specific frame by using the frame property so that's why what I did here the frame zero and then here I scaled it four times because this we actually scale the camera I think four or two times uh but for the UI to look good here we need to scale this Sprite four times and here the HP mapping just tells you that for any amount of health so one one amount of Health we need to display the the frame two for two Health Point we need to display frame one and for three Health Point we need to display frame frame zero the reason this makes sense is simply that if you go to the ui. PNG you can see that this is going to this part whoops this is going to be frame zero frame one and frame two so when we have full health we have actually the frame zero and yeah frame two uh frame one is when we have two Health Point and frame uh three is uh frame sorry two is when we have one uh HP left and then here that's why I created this mapping so we can easily uh set it here so then I called the set events event listener I create I created the set events method sorry which is which is where we Define this custom update um method uh I mean event sorry and then what it does it takes the current HP and then if the current HP is equal to zero we destroy the health bar because we're going to just recreate it and regardless we set the frame the current frame to be using uh to be used to being the current HP mapping so here it go though this makes a bit less sense because you could maybe just go here if you're going to destroy the the health bar might as well uh not do that so it becomes pointless to to set the frames afterward and then we're just going to create one health bar here that we used that we use here so instead of creating that in our various rooms we just create one here and we import it where we need it so let's add this to room one. JS so we're going to add it at the end of our file here actually outside of the for Loop health bar then we set the event which is just one we call the trigger we actually trigger the update events event once Health bar. trigger the update and then of course remember that we need to actually add the health bar to the scene because we have only used it with make so we haven't added it anyway anyway anywhere in the canvas yet all right so now that we have that uh if you remember earlier on I had two two dos so to to do um no not not that one um health bar come on I had a a comment to do did I forgot about this seriously H okay never mind never mind so I think it was in the player logic in the events for it yeah okay so it was here health bar so here we're just going to have going to call the health bar then trigger an update we're going to do the same thing here as well so now if I look at the result press enter we have our health bar let's take some damage just just to test things out and then you can see our life is reduced and then when I get healed and damaged again and then let's get damaged again and then let's uh let let's let this Droid kill us here we go and then we respond all right sounds good to me and uh yep so the game is basically done except now we need to have the other room so yep let's work on that all right so one quick thing we're going to do before proceeding on to writing the logic for the other room is we're just going to write some logic that when the player Falls here so after a certain y position they respawn to do something like that we're going to fill this function that I left as a to-do so the way we're going to go about it is the following so if respawn if out of bounds so here I'm going to create a on update Loop this onupdate Loop what it's going to do is it's going to check every frame if the position of the player so here I'm in play.js in this method that we wrote but didn't write the body of previously and then here so if this so this is the player the position Y is superior to the bound value which is going to be the maximum y position we want to allow then um yeah Superior so remember in in a canvas in Game Dev usually the farther you go down the higher the value of y That's why we have this statement here so now what I do is that if I exceed if the player exceeds this bound value we can just go to the destination name which is going to be the the room you want to go to that we're going to Define later and then we're going to pass the previous scene data as the other by the way the go function in Kaboom J allows you to switch to another scene but it can also take uh in addition to the name of the scene you want to go to you can pass some data and here the data we going to pass is going to be the exit name so here in our what is exit name is going to refer to the exits of the um that we had on our map so here the exit layer in tiled you have exit one and exit two so the way we're going to do we're going to go about this is we're going to use this uh previous scene data to tell Kaboom when to spawn where to spawn in the other room in this particular case though what we do is that we're not going to add anything we're going to make the exit name null because we want to just respond in the current scene so here it doesn't make much sense for now uh but bear with me so here it's time now to use the respawn if out of bounds and you're going to we're going to call this inside of the room one. JS in this file I'm just going to have the player here [Music] player um respawn respawn if out of bounds all right so we have this respawn if out out of bounds so what that what we're going to do now is we need to actually pass in the param so I'm just going to pull the player. JS file for reference because I I need to find it just to know what to do so the bound value I think the bound value I did in my original was 1,000 so 1,000 will be the maximum y value want to allow otherwise we would spawn into room one so what we want to do here is to set the respawn if out of bounds uh value the bound value to 1,000 this is what uh looked good and then immediately go to room one if we go out of bounds so let's try it out so if I go here okay it's not a function why is that so here respawn if out of I made a mistake here in player. ja of bounds now everything should work so let's try it out now if I drop off I should respond all right everything is working nice so now we have finished the every like gam playay features and now what is left is just to make the scene transition to the other room and repeat some of the logic for the next room so room two so to be able to pass data between the scenes as I show show as I have shown initially by using this second param to the go function we can actually receive that data we haven't written the logic for it so if I go back to main.ts you can see that we just pass the room one data here but the room one data we can receive it here so if I go to main.js I can create a param here called previous scen data and then I can just decide to pass this as a third Pam to pre to this room one and I'm going to have to of course create a new pram here for uh for the room one function in our room 1js file so this can be passed by the go function by default we want to make sure that this is null um so you have to specify this by default we could have decided that here by default if it's not never mind never mind you have to so by calling K.O room one to go to the room and specifying an object as a second param it's going to be our previous scene data so this refers to this all right now you can see that for our case here we haven't had anything here so let's set the data we want to pass as exit name null we're just coming from the menu so there's no previous exit uh we're coming from but this is going to be useful for room two so here I'm just going to pass the exact same data but just in instead of room one it's going to be room two and then previous seene data here as well and now we need to actually write the code in room one or room 2. J which is pretty empty for now we're going to have to do basically the same thing so set the background color with the color I specified previously which was hasht A2 A5 remember to add the doj to the uh import the statement uh make sure to cam scale four times like we did in room one make sure to add to set the initial camera position to 170 by 100 like the initial cam uh the initial uh camera position we did for the room one and then set the gravity as well to being 1,000 like we did with the first scene the room one scene then we're going to get the room I'm going to store the room layers inside of room data do layers actually we're going to St going to um store the layers inside of the constant room layers sorry and then we're going to do the same thing we did so create a map game object add it to this scene and then set the position to being 0 0 as a reference or just uh you can easily modify it later on and then set the Sprite to being k. Sprite and then Room 2 remember we have this uh loaded from the Kaboom loader. J file and that's basically so now if I um okay yeah so that's basically it now we we can do the I'm just going to copy and paste the exact same logic we had here so I'm going to take room one and then copy all of these and then all of these as well and even the player as well so really everything comes except for the there there aren't any mobs there are cartridges so we're just going to modify a few things so let's copy all of that and then go here and then paste it right below now of course there's a bunch of import statements that are missing so we going to have to figure this out um I'm also going to remove the Drone here because there are no drone drones in this uh room and also the boss so what is left is the cartridge and the player and then here we're going to have to import everything so let's import um import the player the make player sorry function let's import the make cartridge function we also need to import um the state do do we use the state here not sure no we don't we actually need the health bar as well so let's import that as well health bar and then okay we have the health bar we have everything the and then the various set camera zone map colliders Etc so here again I'm just going to go here to room 1. JS and copy and paste this from room utils so take this import statement paste it here and then save and then I think we should have everything we need um let's try it out so so what I'm going to do now is I'm going to actually have to set the exit zones now so one thing that we didn't write in the room utils is a function to handle when you exit a given room Etc uh Etc so right below Set uh maybe at the end of the file I'm going to go to room Ms and then create a new function export function and then this function you're going to call it as I said set exit it zones and then it takes a the context the map game object the exits and the destination the destination name I'm going to call it this way this part all right so here for so where does this exits come from so here in our room two there's another layer we're going to look for is the exit so I'm going to add right above here if the layer name equal equal exits by the way we need to also add this in the room one logic because there are exit exits as well so let me just verify here so we have the exits layer so now we're going to push we're going to create a new array so you could uh also like make this more modular so all this part that we copied and paste from room one you could have a single source of Truth so a big function that does all of this I didn't do it for this project because it's a relatively small scope but in case you you want to push this further I recommend that you start modularizing and abstracting things from here so here uh we're going to have the exits array that I'm going to create and then in the exits array here I'm going to push exit. push do layer doobs just to not have an error later and of course continue because otherwi there's no point in running the last if statement if we arrive to this condition so you could have decided also to have this as an a um switch case statement in hindsight so feel free to refactor so I'm just going to copy that part in room one as well and now we can go back to room utils and then go back to the set exit zones so for set exit zones we're going to iterate through the exit so exit con exit of exits and then we're going to create the exit zone game object which is a child of the map game object we're going to set the position to be exit X exit y because they offer the position so yeah so we have the positional data in inside of the this exit constant and then we're going to have yeah now I'm just going to copy and paste because it's roughly the same thing we've you've been used to with the other ones so the area is specific we ignore call it collisions with colliders and then we pass in the exit name this is important because this tag is unique to the exit name so here for exit one this is going to be the tag for exit two this is going to be the tag and then for here room one uh room two the exit one here exit two and then Final Exit as well okay so now that we have that right below we can set a collider uh on Collide event listener so if the exit Zone on Collide so collides with the player we're going to have the following so we're going to use in the sync function here and uh I'm just going to copy and paste the code just to go a bit faster and then I'll explain it every line what do we do here so we set the background so this to have a a nice transition so we create a rectangle that takes the whole screen that will move via a tween and then if the exit name is the Final Exit we go to the Final Exit scene we haven't created that scene yet so just copy and paste that for now otherwise we go to the destination name uh which is either room one or room room two depending on where you're coming from and we pass in this object uh to that uh to that next scene which is going to tell us the exit name we're coming from that way we can know where to spawn the player either in entrance one or two so we are going going to have to add some some logic to room one and room 2. J to to control the spawning of the player so now that this is done done we are ready to use it so in room let's let's add it to room one and then to room two as well so for room one I have added it here so let's do it last or yeah we can do it last it doesn't matter okay let's do it right after here so right after camera control so set exit zones and then pass in k the map the exits and then the destination name is room two in room one we need to take this same logic in room two but instead of room one uh instead of room two here it's room one and now here in room one let's go here so for the player position actually it's going to be much more a bit more complex than only one if statement so if I go back to the player uh the room one logic so we're here we're going to have two others if statements so if the prev so for the first one we're going to add the condition that if the previous scene data was null does didn't exist actually we need to do the exit name is null so we would spawn the player in the original initial position otherwise if if if the position. name is entrance so yeah so uh we had a pin if I go here if I go to the positions layer in room one so I'm just going to make it visible we have this entrance one and entrance two pins this is where we determine where to spawn the player uh if they're coming back from a scene so for this if statement if if the pin was entrance one so the position was entrance one and we had a previous scene data exit name passed through this uh to go to arrive to room one and it's exit one then we would place the player into the the position of that pin and then continue on and then set the camera position to be the one of the new player position because otherwise the camera would still be up there in the level and then finally exactly the same logic so here again I was at the end of the project so I just wanted to get it done as quickly as possible so there's a bunch of repetition but at least with repeating code that is simple like that it's easy to to abstract it when when you need it into a more reusable version so here is the same logic all right now we do the exact same thing in room two so for room two I'm just going to copy and paste the logic for by the this time around we only access room two from either of those two exits that you have saw initially so we don't need this default if there's no a default spawn spawn point for room two so it's either entrance one or entrance two if you look in tiled room two you can see the player can either spawn here or or there or or there there is no two option uh two options sorry so here the same logic this time around we set the position as the uh never mind so why is this the case map positionx I I don't think we actually need that so if I go back to room one I just set the position normally since we have the player as still a child of the map we can remove this this was a an error on my part because the position is already relative to the to the map anyway so let me just remove that hope it will work and and here we go so hope I was clear if there is anything unclear feel free to comment in the comment section uh ask your questions there so I can see them all right I think we're basically done let's try it out so there's an error already so set background color room two probably missed an import statement uh set background color what's the issue red Declaration of import set background color previously declared at line one okay so it was so it was re red declared at line three or six ah okay I see I copied it twice so I'm just going to remove the first one now if I press enter exit is not defined uh okay line 40 room one so line 40 it's not exits I thought the this layer existed let me look it up exits yes this layer exists uh did I mess something up layer name exits. push ah I forgot to create the original uh the array for all holding all the exits so let's do the same in room two because we're going to have the okay we did it for room two did not do it for room one that's why so if I press enter and then we have our game okay now let's test it out so I'm going to just go to the left and we have previous previous scene data is not defined okay where is this error from um main.js okay main.js previous in data okay we need to pass this here so now it should work let's test it out pressing enter here we go now let's go here and then K is undefined okay so what's the error now K is not defined in room two line 12 room two line 12 so room two line 12 okay we didn't pass in the K here and we didn't pass in the room two data as well and we didn't pass the room data sorry the room data as well and we didn't pass in the previous scene data so forgot to add all of these params that we did for room one now it should work hopefully so I'm going to make it this full screen ah set exit zone is not defined again forgot this in room two set let's add it to set exit zones here did we add it for here as well okay for room one and room two we have them so now let's test it out again and now it should hopefully work and it does and then if I exit back in we're back at the correct position so now I'm just going to go to the other one so actually I have to beat the boss first to get unlock the double jump ability okay let me just hit the let me just beat it and then we'll all right now we should have the double jump unlocked and now I can go to the other side here and we spawn in the correct place and now here should it it's normal if it bugs here because the scene doesn't exist or did we actually create that scene yeah Final Exit we didn't create it so the game is mostly done now the only thing left is really to create those last scenes so the intro scene with a message that tells you like how to play and the final uh Final Exit scene so we're going to do this in main.js uh for the final scene I'm just going to create it here right below the intro scene and then I'm just going to make a call to the notification box with this message going to do the same thing for the entro scene and the project is done so here I'm going to import make notification box and then for the intro scene I'm just going to add the following as well so right below here and then one thing I also want to add is I'm not sure if it does anything but the audio on the web page unless you do a gesture the audio will not activate so if the first sound of your game is the sound effect from getting hit and before that there were no sounds played then it's going to have a lag between the the time the sounds actually play and what happens on the screen for the first sound that is uh that is heard on a web page so I thought this would fix the issue but I'm not sure if it does anything so I'm I'm gonna keep it here so so it's about creating a new audio context but I'm not sure if that it works because we should actually resume the the already existing audio context but I'm not sure how to get access to that so this is something with Kaboom I I don't know if there is a fix except that you start immediately playing some background sound when or in the menu playing some sounds that that way you wouldn't have this issue all right let's test it out and okay set back color is not defined import set background color all right we we the game should be done let's let's play it so escape the factory use the arrow keys to move X to jump and Z to attack and then press start so let's play Let's see if everything works all right so I hit the enemy all right ah I took some damage can I go to the left yep by the way this is intentional that the enemies respawn when you you go to to another room uh that's a bit like uh in Souls games the the enemies respawn like that but so I'm just going to beat the boss and once the boss is beaten okay that's I have unlocked the ability by the way you can make the boss more complex I made it simple on purpose so it's easy for me to play test so now I'm just going to complete the game so here go here here and then I took some damage and then I go to the left side and then I jump here and I jump here and uh by the way I'm just going to drop off here to test that the respawn logic Works yep and I'm just going to also go back here to make sure that the logic works all right it does and then I'm just going to finish the game you escape the factory the end thanks for playing and that's it that's the game hope you enjoyed this tutorial and uh by the way if you want you can subscribe to the channel so that you don't miss out on future tutorials I don't upload that often so it it would be a good idea but yeah so I hope you enjoyed the tutorial and you can go on my channel see other gamedev JavaScript related tutorials thanks for watching bye one last thing uh if you ever want to upload this game online what you do is you just zip the the whole code base and then drop drag and drop it on h. and it should be able to deploy that was one thing I forgot to tell you so same thing for GitHub Pages you just activate GitHub pages on the repo for this project and it should be up and running so that's the advantage of not using a A bundler or npm is that the deployment is very easy all right thanks for watching again bye