Let's build an RPG with JavaScript - Part 1: Project Beginnings #pizzalegends

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everybody in this video series we're going to create an rpg in html css and javascript from scratch this game's going to be in the style of a lot of the classic retro rpgs i loved when growing up like pokemon red and old final fantasy and it's going to run entirely in the browser let's take a quick look at the result we're going for so this game is going to be called pizza legends it's about these characters that are competing to become the best pizza chefs in the entire city by battling their lineups of pizza creations against each other you control this hero pizza chef in the middle of the screen here and kind of guide him around you can talk to people there will be cut scenes you can manage your pizzas and a pause menu and unlock new pizza types as you play through the adventure there will be a whole turn-based battle feature where you can battle your pizzas against other rival chefs your pizzas gain experience points and grow stronger as they win battles but yeah pizza legends heads up that this is a really large project this is going to span many videos i'm not sure how many yet um and we're going to get started at the beginning in just a second here but just a reminder to to make sure you catch all the videos if you're interested in this please be sure to subscribe and that way you'll be notified when the new videos come out as soon as they're ready let's go ahead and take a look at the beginnings of our project here what i have is a new directory on my machine called pizza legends it's it's pretty empty but there's a few things in here so first there's this index.html file and that's really bare bones it's just a html file with the doctype html tag an empty head and empty favicon in here this is really just to make the browser not complain and to make the tab look a little nicer and then finally there's this uh directory of pre-created images and assets that i've made for us uh just as we build this game together this is all available to you in the download link below in the description so you can check that out and grab it if you want to follow along here in here we have some sprite sheets and different assets that we'll be using throughout the game so let's pop over to the html here and start filling out what we need first we're going to start with our title tag and the title the page is going to be the name of the game which is pizza legends uh and then i'm going to add a style sheet so i'm just going to paste in a link tag and for now we're just going to call it like slash styles.css and give it the usual stuff it needs so quick warning this project's going to grow really big really fast and so right now i'm just you know having styles kind of in the root like this we're going to eventually refactor it to kind of live in nice directories and that kind of thing but for now we're going to start really simple so now down in the body tag i'm going to add some just basic kind of divs that we're going to be using uh so first there the kind of home of the whole game is going to be in this container called game dash container and so if i do dot game container and hit tab the editor is going to create a you know div with the class on it and then in here we're going to have a canvas tag the canvas is what we're going to draw most of our game to and it's going to have a class as well called game dash canvas and on our canvas tag i'm going to go ahead and supply the aspect ratio that we want our game to run in so this game we're going to kind of emulate like a a little screen if you will a game boy screen and the resolution we're going to use is 352 pixels wide by 198 pixels tall so this is a nice 16 by 9 aspect ratio that's just going to kind of work really well for the art style in this game um you could go ahead and adjust this to whatever kind of art style you're working with it's gonna depend we're doing pixel art here so we can get by with these really small numbers and then we're gonna learn how we scale that upwards in a little bit um if you're doing maybe more of like an illustrated style or something like that you could probably have larger numbers here this is just the size that we're going to use for the rest of this series so moving on here i've created this styles.css file and i'm referencing it but it doesn't actually exist in the directory yet so let's go ahead and create it and click this little button and call it styles.css often just to make sure things are linked up properly i just like to do a little like you know grab the body background orange something obnoxious just to make really clear that the style she's coming through and so to actually run the project now to make sure you know things are working and all that we need to start up a web server and so my favorite way to do that at least one of my favorite ways these days is to open up a terminal cd into the project directory so here's our pizza legends if i do ls you can see it's got all the files that we've been working with here and i run this command called python dash m simple http server just like that and when i fire this it's going to start a local a web server on localhost 8000 by default there's a way to pass a different port in there if 8000 doesn't work for you so now when i visit localhost 8000 on my local machine you'll see our web page running here i can open up the inspector just like this and see it's got all the content ready to go so now we're ready to actually work on the game and i want to quickly add here that python command has nothing to do with anything really for this tutorial we just need to run any web server in this directory if you're already an npm user there's a really great package called serv you install that globally then it's just a matter of running and i think just serve from the directory and that will start a web server on a port whichever one you define that'll work fine too it really doesn't matter we just need to run this directory locally so here we are back in our obnoxious orange land let's go ahead and start actually writing some styles that make this look a little bit more like what we're going for so i'll pop open to styles.css i'm going to instead of this lovely orange color i'm going to go ahead and change this to kind of like a dark gray i'm going to add a reset to the box sizing model i'm also going to add some more just general reset stuff to the body here so like padding zero margin zero just to kind of standardize things across browsers and then we're going to be using our arrow keys a lot to guide the character around in browsers that will naturally kind of trigger some scrolling like thinking that we want to scroll down the page that's not really what we want here so we're going to go ahead and disable that by adding overflow hidden to the body itself and now let's move on to our game container this is going to be kind of the home that houses the entire game all the ui everything inside it we're going to have a lot of positioning going on in here so let's go ahead and start out with position relative to make sure everything is kind of relative to this container next we want to apply that same aspect ratio so that's going to be 352 pixels by 198 pixels and you may be thinking hey that's a little bit duplicated from the index.html file and it is but the two things kind of have different purposes where this is we're going to really just kind of like set up the gameboy screen if you will in the middle of the screen and learn how to scale it upwards in a second this is more for like visual kind of effects you can do with the canvas if you want to like play with the um zooming inside the game or something like that but without messing with the actual game boy screen if you will you can play with those two values independently so that's why we have them separate here we're not actually going to do that in this project but i just wanted to call out that maybe a reason to keep them separate and now just so we can see the game container let's go ahead and add an outline so one pixel solid white so when i go back to the browser here and reload our changes you can see that we've got a canvas tag here um it's wrapped in this container and it's kind of you know it's showing us where it is that's good but let's move it into the center of the screen so game container uh we're gonna say margin zero auto and then um just for now let's go ahead and nudge it kind of away from the top of the screen so we can clearly see all four borders and here's what we have now so this is hilariously small right now and that's okay we're gonna fix that in a little bit um but for now we wanna move on and just start drawing some things to the screen to make this a little bit less boring and so let's let's get some javascript going now where we're going to start actually loading images into the page and drawing their pixel data onto this canvas so at the bottom of the body here i'm just going to add a script tag and i'll do like a comment scripts um and this one we're going to do two so first we're going to start with our overworld i'll get into that in a second and then we want another one that's going to be just like in a general kick off the game file and we're going to call that init.js i want to add real quick that again just like the styles i'm putting everything just in the root directory here as we go this project is going to get real massive there's gonna be way more javascript files than just the few that we have going on so far and we're gonna start moving them into directories that maybe make more sense for a large project but for now we're keeping it real simple so let's go ahead and create these new files so the first one's overworld.js and one more it's going to be init.js in init.js real quick i'm just going to kick us off with a function that executes itself and then here we have console.log it's working and now when i go back to the browser and run this we should see the message that just tells us the scripts are wired up and working that's all good okay so let's pop open to overworld and see what this is going to be all about um most of this project we're going to implement as javascript classes so it's going to look like class overworld and then we'll have things in here i've chosen to do this project in classes because it kind of mirrors a lot of patterns you'll see in game engines like game maker godot unity there's this kind of game object pattern that works really well for things extending off each other and kind of enclosing their own state within each other if you hate javascript classes that's okay you don't have to build your game like this but this is just kind of the pattern that we're going to roll with for this project so the overworld here is going to be kind of our top level parent component it's going to keep track of a lot of state that's going on and then kind of send that state downwards to little sub components and we'll get there in a while but first what we want to do is just have the overworld draw some image data onto that canvas tag that we created already and so what i'm going to do is make a constructor and even though we're only going to have one overworld we're going to code it as if we could have multiple just in case you know if something comes up in the future we don't want to be like totally against a wall so i have the config here what i'm going to say is this dot element is going to be equal to config.element so we're going to pass in an element for the overworld to operate on and then from this element we want to grab the canvas tag and we'll just go ahead and save it to this.canvas there's a few times the overworld is going to want a reference to the canvas and finally we're going to be drawing to the context of this canvas a lot and so we're going to go ahead and save that as a reference inside the class too so that's going to be this.canvas.getcontext and we'll pass in 2d this is going to give us access to a lot of the drawing methods that exist on canvas elements here so now our overworld is created and that's good but it doesn't actually do anything another pattern you're going to see all the time in this project is adding an init method to our classes and so basically this code is going to exist but it's not going to do anything until init is called and so we're going to go ahead and just say like i don't know hello from the overworld and then let's just pass in this so we can kind of dig around in the console so we're set up and ready to go here but we're not actually creating a over world yet um so what we can do is do that in init.js so instead of this log here let's go ahead and say const over world equals a new overworld instance and in that we're going to pass in the stuff that the constructor expects and so again if you remember we basically are just pulling an element out of config and that's going to be the game container and so we'll say element is going to be document.queryselector dot game container and then remember from there it grabs the game container finds the canvas within it the game canvas and then that's what we're going to use to draw on now that we've created the instance let's go ahead and initialize it by saying overworld dot init and that'll call the method that we created right here so when we fire it up in the browser we see our log appear hello from overworld and now this is being logged which is the instance of overworld and so you can kind of get in here and dig through to see all of the instance variables we have going on and then um furthermore you can kind of dive in and look at the constructor and see all the methods we have it's kind of cool if you're just getting into class-based development it's kind of a nice way of just digging through and seeing everything that's around okay so back to the code uh what we want to do now is in our overworld instead of just logging a message when we init we want to start drawing stuff to the screen so what we're going to do is take an asset that i have in that assets directory let me find it for you there's this file called demo lower and this is what we want to draw to the screen this is going to act as the environment for like a test room that we're going to build a lot of the game features into so i'm back in the code here how canvas works in htmls if you want to draw pixel data from an image onto a canvas context you need to first load that image into the browser in memory and so uh to do that we can say image is gonna be a new image and this isn't gonna get injected to the dom or anything like that we're just gonna like create it under the hood sort of and then once the browser creates it and downloads our asset in then it can copy those pixels over to our canvas context so to make that happen let's go ahead and add an onload callback to our image and so basically um we're using an arrow function here because whenever this fires we want to take our this dot ctx and um we're going to draw an image on it we'll do that in a second but this will never fire right now because the image doesn't have a source it's starting empty um it's set up to do something when it's done loading but we haven't actually given it a source yet and so to do that we're going to say image.src equals and this is going to be the path to our image that we want to load in so the path to that asset is uh images maps demolore.png so as soon as this is set the image is going to start to download this asset and then once it's downloaded it's going to fire this callback so from there we want to take our context and run the draw image method on it draw image wants a few different arguments and in this case we can do among like the simplest version of it we'll get more complex in a second but we're going to pass in the image that we want to draw the pixels from so that's just going to be image which is the image we created and downloaded here and then we need an x y coordinate of where we want to draw starting from like the top left corner of the image we just downloaded uh so that is just going to be zero zero and now when i fire up the browser you can see that our image for our map is appearing on the canvas so just a quick recap of what's happening here basically uh when we init we're going to create a new image we're going to assign a source to that image and then whenever that source is downloaded we're going to copy all the pixels over to our actual canvas where the canvas has a context and the context is the thing that allows us to draw to the canvas but as you can see this is tiny super tiny we want to scale it up so that we can actually see the game so these days we can achieve this with just css without needing to mess with any like math or anything like that so i'll come back to our code and go into styles.css we're going to take the entire game container which is that white outlined area and scale it up and so we'll say transform scale we're going to start with three and so what that's going to do is take every pixel that's on the screen there and basically multiply it by three which again we're doing pixel art here so that works really well that might not work so well for like a illustrated game or something like that but pixel art perfectly even squares of color uh scale is perfect for this so when i apply this and pull it up in the browser it's working but but there's like two problems with it one it looks blurry and we'll fix that in a second but two you can see that it's cut off here and that's because scale by default will start scaling from the middle of the thing that you're scaling and so if this is what we're scaling basically we have expanded it to go like this way but the top of the monitor is still right here and so now the top of the game is basically cut off and so we need to push it down this way now to compensate for that scaling so we'll go back to our css and right after we scale we're going to go ahead and translate y just by 50 and translate percentages and translate operate on the size of the actual thing so it's going to take the game container and then move it down 50 of the height of the game container so now when we see that we can see that we can actually see the game again and this will allow us to sort of remove that temporary margin that we added before so i'll go ahead and rip that out now let's take care of that blurriness so just to see it one more time if i zoom in here you can see that there's some fuzziness around the edges uh pixel art should look like perfectly crisp so that's no good again there's a real easy way to fix that in css these days where if we take our game container and grab any canvas inside of it a spoiler we're going to have multiple canvases going on in a few videos from now but we want to apply this effect to any canvas we have so we'll take all the canvases and run a rule on them called image rendering pixelated and what this is going to do is tell the browser to just like evenly multiply all the pixels don't worry about like blur compensation or anything like that and when we see it in effect see the lines on the art just instantly crisp up and we have perfectly even squares of color and because this is all css this kind of like opens the door for some responsive styling we can do so say you have like a really large monitor and you want to scale this thing large like you could scale it by like four or five whatever you can fit in the screen uh seo giant that's a little big for the screen i'm using right now but the idea is that you could continue to scale it however you want or even smaller if if you want to support mobile with your game i guess we wouldn't need scale in that case but how about like two and really just by playing with the css value you can size the viewport to be whatever you need okay setting this back to three real quick this is looking okay so far you know it's a little bit more interesting we see like a little bit of a map uh but these games are all about the characters so let's get a character on screen next so hopping back to the code and what we're gonna do is find our drawing code again and right after we draw this image we're going to draw another image right on top of it so the way that canvas drawing works is is very much just like drawing on a regular piece of paper where if you draw a shape or something like that and then you draw another thing right on top of it it's going to cover up what you drew before and so if we want something in the background like this image that we have going on right now that will be drawn first and then anything on top of that will be drawn next and that's how we get some layering effects that we'll end up doing here so let's go ahead and draw a person to the screen so we're going to use the same pattern that we used before for the image but we're going to call this one hero hero's going to be like our our main hero character we'll say that the hero is also a new image in that you know when hero loads just like before we're gonna draw the hero to the screen and then again to kick off the loading process we need to assign a source and so the hero is going to live in uh the directory images slash characters slash people here that's a little redundant but there's different types of characters in this game about pizzas and now let's just try the same thing that we did before so this dot ctx we're going to draw all the pixels of that hero image so we'll pass in hero and then just zero zero like before see what this looks like and aha we can see that it's working and that's good uh but the hero asset here isn't just one image it's a sprite sheet so within this one image we have like all the different variations of frames that the hero or a person could be showing and so what we need to do is modify our code to not just draw the entire thing at a position but actually to only draw one crop of the hero right now so let's go back to the code and adjust our draw image method here um we are currently using among the most basic flavor of this method which you only pass three arguments into uh but for us to achieve the effect we need to achieve we need to like really beef this up and in fact we're gonna end up passing nine arguments here and so the first one's gonna be the same just hero as it was before that's the image that we're drawing pixels from i'm gonna break out the spacing to make this a little bit easier to read the next two are going to be the starting points of the left and top crop so if we have us a sprite sheet we need to kind of tell the code like where should you start cropping this image from since we only want a subset of the whole image and we're just going to start with like the top left frame the most basic one and so for us that'll just stay zero but i'll leave a comment here to sort of explain what we're doing and so this is going to be like the left cut and then the top cut is next so the next two arguments are going to be the size of the cut that we want to make and so to better visualize this i'm going to open up the asset that we're working with in a you know my favorite pixel art editor it's called a sprite and and you can see the whole image kind of laid on top of this grid and you'll see that the the characters designed in these squares of 32 by 32 pixels so here's a frame you know here's a frame here's a frame you get the idea what we want to do is tell the canvas that you know we're going to start cropping at 0 0 just like we said but we need to stop at 32 wide and then 32 high so here we'll pass in 32 32 and that's going to be the width of cut and the height of cut so moving on the next two arguments are going to be the actual position that we want to draw the character on the map and so we've you know so far we've cut out what we want to draw but now we need to place what we want to draw and so what i'm going to do is instead of i was going to say let's just do 0 0 but instead i'm going to go ahead and utilize a variable here so x y you can imagine that we have a hero and maybe the hero has an x y that can change as the you know character moves around the map so we'll say x is we'll start zero and y is gonna be zero two and so we'll just plop them there at you know x y zero nice and simple for now and finally we need to provide the size of which the character should be drawn on the map so if you wanted to take the character and like scale it up or scale it down a certain way you could do that here but we're just going to keep it really simple and draw it at the natural size that we cut and so for us that's another 32 by 32 cut so here's what it looks like you see that we only have one frame of our character his position's a little funky right now and we'll get to that in a second but just for fun real quick let's see how playing with these last two arguments can kind of uh mess with the display of the hero so he looks nice and crisp right now but if i come back and maybe change this one to like 48 picks you'll now see that the crop is still correct but then the canvas is drawing it in like a skewed aspect ratio and so anyway that can be kind of fun to mess with but i'll go ahead and set it back to what we want which is 3232. so let's go ahead and talk positioning for a second right now you can see that the character is up here in the top left of the screen let's go to our image editor and say i've got the map open right here say we want him to maybe be standing like over here somewhere or let's just keep it simple and how about right here to do that we just need to start counting 16 by 16 cells from the top left corner and so all these maps are going to be designed 16 by 16. the character is 32 by 32 so that he can appear like bigger than the the cell tiles we'll go into that in a little bit but the maps are always 16 by 16. so i'll start counting from the top here for the x coordinate it's going to be 0 1 because we start with 0 and then for the y coordinate we want 0 1 2 3 4. and so if i go back to our code and just say that the character's x is one and um you know his his y is four like we said those values will be used here but we need to go ahead and compensate for that grid and so let's say times 16 here so let's see what this looks like we can see here that the character's position has moved and it looks almost like what we'd expect but something still seems funky about it and that's because the character again is designed in a 32 by 32 pixel uh sprite sheet and so the top left corner is actually going to be kind of like right here and i can kind of visualize that better by just going into the hero right here and at the top left i'm just going to go ahead and add like a marker let's pick this color right here so this will mark the top left corner of where the assets being drawn and if i reload you can see that that's right here it's perfectly aligned with what we expected but the character visually is still kind of not in this cell and so what we need to do is add some nudging to sort of compensate for the character's art size so if i just zoom in here a little bit kind of a good way to do this is just to pull up a little measuring tool and say that we want his feet kind of like right here and so we're going to take his foot and maybe go this way by like 8 pixels or so and then maybe up by like 18 pixels or so so let's pop over the code and try that out in our x where we're applying the grid we can go ahead and just subtract eight and then subtract um what do we say 18 here and pull this up in the browser reload and you see that the character is right smack dab in the cell kind of where we expected them to be now just for cleanliness i'm going to go ahead and go back into a sprite here and remove our little indicator because we don't need it anymore just to make the frame a little bit more interesting we're also going to adjust his position and so instead of being at one four let's make him like in the middle of the room which is like five six you can see that and again these variables are what we're going to play with to actually move the characters around so they're hard-coded right now in future videos we're going to make them dynamic and so one last thing we're going to add here just to make our scene a little bit more complete you see how this character is just laying flat on top of this image it looks a little flat right now and so we want to add some perspective just like the objects here have little shadows underneath them we want to add a little shadow at the character's feet so i'll go back to the code and we're gonna do the exact same pattern that we've done so far and so we're gonna make another image called shadow we're gonna give shadow an unload and kind of see where i'm going with this and then we'll go ahead and add shadow source which is images characters shadow.png we want the shadow in the exact same position that the hero's in so i can actually take all of this code for draw image put it on here and just change it to be shadow and when i reload the scene you can see that the shadow now appears at the hero's feet the shadow image is cut to be the same size as one hero frame so just kind of perfectly aligns now i bet a lot of spidey senses are going off right now being like hey this code has a lot of duplication in it it's not really you know scalable what if we had two characters then do we need another shadow and another you know hero sprite what if we want a different map that's not always this map those are the exact topics that we're going to cover in the next video for now we have the basics of drawing something to the screen scaling it up and putting things in positions according to their state in the next video we're going to tackle refactoring some of this code into a concept called a game object where we can have multiple types of different objects being drawn to the canvas right here each with their own nice little file and their own nice little piece of state and behavior that's going to allow us to add interactivity to the game where the different game objects can talk to each other and be guided around by the human player thank you so much for watching this video if you're getting value out of it i really appreciate it when you hit the like button and subscribe that helps me continue to make these and if you're following along with this code tutorial or you're already working on a game you should join our discord we have this community of people that are making and playing indie games so whatever you're working on hop in there tell us about it we'd love to see you there thanks so much everybody catch you in the next episode you
Info
Channel: Drew Conley
Views: 9,660
Rating: undefined out of 5
Keywords: javascript, tutorial, rpg, html, css
Id: fyi4vfbKEeo
Channel Id: undefined
Length: 30min 51sec (1851 seconds)
Published: Tue Oct 05 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.