GameMaker Studio 2: Isometric Game Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody I'm Sean Spaulding and today's tutorial topic was selected by my patreon supporters if you'd like to get involved in deciding what GameMaker topics I cover in these videos as well as getting behind-the-scenes access to the videos early and a bunch of other cool stuff head on over to patreon comm for /oj s where you can get access to loads of cool stuff and just play a part in making sure these videos keep happening today we're going to be looking at how to create control and render an isometric game world the isometric perspective is pretty popular and useful way of using 2d artworks and convey a pseudo 3d space we're going to learn how to use a normal top-down 2d grid to create and render an isometric game world this is pretty much the same technique I used for my Ludum dare game fireball by the end of this episode we're gonna have something like this so it's an isometric game world and you can see we've kind of randomized the height of each one of these just to show you how you can manipulate the height of each individual tile and still be able to render them in the correct order so the tiles further Bank render behind tiles in front and so on so let me just quickly walk you through what I'm starting with because it really isn't much so we've got this sprite here I've called s stack which is our tiles okay I've got one grass tile on one sort of cracked tile these are just literally the tiles I used in fire ball just rip through either each of you really wrote me having to make any new stuff these are our final isometric tiles that were going to be using okay as long as your origin point is centered on the x axis it doesn't matter necessarily too much where it goes but I'm gonna put it just about here so it's sort of right in the middle of that kind of diamond-shaped for the grid that sadly and this is the crux of why you need this video really we can't just place tiles like this into the game room easily we kind of can up we manipulate the GRU in certain ways but the default 2d grid that you get and the room editor doesn't really support placing these kinds of tiles so what I'm going to do instead is I've created a tile stack that's just squares okay so I've got a blank square when you're using a tile set you always need the first tile will be blank and a green square to represent that grass and a brown square to represent my brown one okay and a tile set that maps those maps those tiles accordingly and then in the room editor I've just kind of drawn a map using that tiles okay I've got a tile set layer called map and I've just used that to draw draw a map and what we're going to do is create an object that converts this tile map into that isometric map that we saw the beginning of the video the reason I've just put these corners in here is it just makes it easy for us to make sure things are working correctly with how the game world is actually going to be positioned in the screen one other thing to know in here my tiles are tiny pixel art things they're like 16 16 pixels wide and 8 pixels 8 pixels high and these that's the diamond anyway it stretches a bit down under here just for some extra fun so the 3d and that's underneath but the main crux of the tile is 216 across in a town that's obviously pretty small you can make it whatever size you want but since I've gone for this really small work just to be able to show it off a bit better I zoomed in our room a bit so the room is actually only 512 by 384 but then our viewport I've enabled viewport and my viewport has double that size so it's 102 four seven six eight okay so that when we're in the game it's actually like zoomed in so that's like our actual size but then it'll actually be like like double that and when we actually run the game so before I do anything else I'll talk too much about how this is going to work I'm gonna create a script okay I'm gonna right click on scripts and hit create script I'm just gonna call it macros now this is a very common technique but a lot of people use a knife start using across most my project is for whenever you have constants using the hash macro function or enums or other constant things that are baked into your game at compile time you can actually declare them all in a single script that's not ever called by anything in your game so you don't need an object to run this you don't need to run it in like an initialization room or anything now you just put them in a script separate from everything else you can always find them and because they get baked in at compile time you never actually need to call the script so just having a separate one called macros is really handy and I'm just going to use this to define some constants that we're going to use throughout this tutorial so in this macro script I'm just gonna raise the font size a whole bunch so if we can see what we're doing and their time hash macro map underscore W in all caps okay I'm gonna call that 32 and hash macro map underscore H I'm call that 24 and now this is going to be the width and height of our map in tiles okay I mean that's literally just you can just count how many there are you know work out how many there are next up natural tile underscore w 16 macro tile H 8 and this is the width and height of an individual isometric tile okay but this to easily work you're gonna want this to be a two to one ratio so you're gonna run it to be twice as wide as they are tall okay so I've just gone for 16 by 8 and again we're not really talking about the exact size of the sprite because that's 16 by 24 we're talking about the height of the the isometric diamond okay I'm not gonna get too much into isometric perspective and grids and how it all works but something simple in two to one will work for this okay just a simple this is 16 and 8 a height there okay and then I've made sure that these tiles fit together and in that way alright so back in our macro script I'm gonna add another couple of these macro screen underscore W 512 macro screen underscore H 3 8 or you'll notice I cannot put a semicolon at the end of any of these lines don't you never want to do that when you're defining the macro okay screen w in screen edge is obviously the width of the screen 512 and the height of it I probably shouldn't have used screen here I'm not gonna change it because I scripted all there so probably it to be more specific there's actually room with and room as we've talked about before our screen width would be 184 and 768 the room width and room height is 512 and 3 or 4 but those are still the bays we want I'm not gonna change them just because otherwise it's gonna confuse me for my script that's probably why should have called these ok I don't think it's too big of a deal but I think pretty much everywhere throughout this tutorial anywhere I write screen if you want to be completely technically accurate it might be more beneficial for you to write room as your the name for various variables to involve lead screen because it's gonna be a few of them a few scripts and things involve screen I've just used I've kept it consistent and you know as long as you're consistent it doesn't really matter but I think technically the word room would would be better than screen in that circumstance it doesn't matter my transverse waves just if you want to be really accurate anyway that's that's the width and high of the room the last thing we want to put in here is I'm going to find an enum those are also defined compile-time so we don't have to worry about calling the script still I'm gonna have an email called tile okay in case you forget how enums work what that means is from now on I'm gonna be able to type tile dot and then anything I define in this enum as a way to refer to that value so if I did that for example Thailand ASD 3 and I equal 4 or whatever right I could type tiled ASD and that's 3 or tile dot hi and that would be 4 right just as another way of defining constants okay and what I'm gonna have I'm gonna have a st in PI I'm gonna have sprites 0 and Z equal 1 technically speaking I'm pretty sure that if you define an enum I could just write sprite and Z in fact that's how I usually do it and that would be 0 and that would be 1 but just for the sake of clarity I'm just gonna put equals 0 and equals 1 okay so that we know exactly that they are 0 1 you might see why in a little bit the point of this enum is that we're going to use an array to store information about each individual time right so each tile is gonna have an array associated with it and an order in that array we're gonna store different pieces of information in each piece of that array it's something I have two entries but we're setting up an enum and everything just so that in case it grew more complicated you want to store more things about tile later on you have an easy way to do that so entry zero in the array we're gonna store what sprite the tiles should use okay and so you know whether or not it reviews by the first frame in this or the second frame in this and so on and Z is gonna be like it's its height right it's sort of z-axis so obviously we're gonna have an x position or a wide position but because this is kind of a pseudo like 3d look we're going for we also want to know the tiles height at any point in time so we're gonna store that in the second entry of the array okay okay so back in our blank workspace now the next thing we're gonna build is an object this object is going to be responsible for more or less rendering our entire game and rendering everything in order and in the correct positions okay so I'm gonna right click an object hit create I'm gonna call this Oh simple enough and now as almost always go ahead and add the create event something like four times two even click on that no no I'm doing today so add the curry event and I'll maximize this because we've got a few things to put in here I'm gonna shrink the font down a little bit if you ever wonder how I'm doing that by the way it's f7 and f8 to change the size of your font because on the fly and scripts just in case you were wondering that the description here is gonna be build the map okay cuz that's what what they might do so the first thing I'm going to do we have this layer in the room in the room area our map layer which is just a tile grid that's just containing everything we want so good we don't want to actually draw this in the game so the very first thing I'm gonna do is make that layer invisible so all the day is still there but it's just invisible well Open bracket map in quotation marks that's the the name of the tile layer , false okay so you might be wondering well you know why do we need to do that in code we could just turn it off there but it's easier for us if we can leave it on in the room at a because then we can you know edit the map and we can add stuff to the map right which is what we want to be able to do and having normal mode turn off every single time we compile every time we make changes to the map as a bit of a pain so it's either first we can just leave that on all the time and then just in Oh render we can just turn it off when we want to actually draw the map okay so our next step is we're gonna make a DS grid okay it's a grid data structure easy way to think of it as just think of it as like an Excel table right so and so we can keep different kinds of data and it has rows and columns and it's very handy for is essentially we're gonna create a grid based on our tile map okay and we're gonna use that to draw how isometric world okay so I'm gonna establish it as a global that goes through our game it's probably gonna be a very popular piece of data to refer to you from our various of the Rob game type players or whatever else we've got going on in my game like global dot the map okay Council M equals DS and the score grid underscore create Open bracket and then we have to provide the width and height of the grid that we're gonna create but map W and map H okay that's why we created those macros area so when you just refer to the width of the height of the map in tiles as defined in our macros next up we're gonna get the info that we already have in the tile map and we're going to put it into this D s grid okay so the first thing we want is to get the ID of the tile map okay that's not the same as the name of the layer okay so that's the layer on which the tile map exists the tile map is on that layer so we have to get the tile map ID from that layer we can do that just by having bar to declare a variable I'll map equals lair underscore tile map underscore jet underscore ID open bracket and then the name of our lamb which is quotation mark map quotation mark close bracket semicolon okay now I want we've got that we can loop through the tile map and get all the data we need so I'm going to do a couple of four loops for this okay very common way to loop through a grid or a tile map or just grid based structures in general let's just do sort of two for loops only for open market and bar T x equals zero T X less than W so the width of map in tiles TX plus plus close bracket and open our braces and then in here I'm gonna do a second for loop for bar T why to represent you know so we're going to go to explain this we're going to go across horizontally so we're gonna have a value called TX that goes up for each column we're looking at and we're gonna have a variable called T Y that goes up for each row we're looking at as we go down each row and by putting the two together we find an individual cell okay and we got on that brings us across all the cells so T y is less than map height t y plus plus so well between 0 and the mat width keep cycling through columns and while we're between sorry equals 0 while we're between 0 and the map height keep cycling through rows okay and so in here we'll eventually get a TX and T y that equals every position in that grid so far I'll map data is gonna equal tile and underscore get tile map which is our home app ID TX t y okay so that gets the information about that cell in that tile map okay and what information does that return well if you've just defined a if you just set up a really simple tile map like we have we've just placed tiles the info you get back is literally the tile index okay so you get like zero for these blank spaces one for these green ones and two for these brown ones right so that makes things really easy for us because that's just going to tell us the exact tile that we want the day it gets more complicated though if you've used things like tile flipping like some of these tools here that like like mirror tiles and things like that as I was a really basic so I'm not doing any like rotate your tiles or like flipped tiles on mirrored tiles or anything like that but if you are doing that then you actually have to there are a couple more steps involved but we're going to skip out but there are a couple more steps involved where you have to then do tile map get index I think is the name of clear command that's tile get index sorry so you'll need to run this function and just return that you can even return it back into the same variable if you want just overwrite it like that because that this is all we want we don't care about any more stuff run in like that but you have to do that too just to get the specific index right and it's good practice to do that and that guarantees that you get the index in case you have done any mirroring on stuff like that but if you haven't you don't need to do it okay because that's just gonna return the index okay which is exactly what we want so the next thing we're gonna do is we're going to define a temporary array okay and this is what I was talking about before so each each tile each cell of this grid is gonna store an array that tells us things about that tile that are important to us and in this case which sprite to use if any and how high to render the sprite okay what was its height what's its depth time for this tile if I can type today equals and then this is a fun new way you can define a and gaming studio - I'm gonna open a square bracket type a minus 1 comma 0 close square bracket that's going to create a 1d array so this tile 0 is gonna equal minus 1 and this tile 1 is going to equal 0 as a result there you could also just write this and to do to do that this is a cool new way of defining a race so you can just define them as comma separated values inside square brackets and I'll create a 1d array with those values in those respective entries okay so you can either do that or you can do this either way entry 0 is going to be minus 1 and entry 1 is gonna be 0 ok and I'm just gonna leave a comment a book it or in mind is what this actually is and the type format yeah open square bracket sprites comma Z just to remind it's that the first value is the sprite that we're saying and the second value is the height each one's going to be default a minus 1 just in case like and if something goes wrong and finding the tiles and we know that minus 1 is some sort of error in theory it's gonna return about between 0 and 2 depending on which one of these tiles it is ok so tau 0 is blank tile one is green and tile 2 is brown but we'll say 2 minus 1 by default because then if we somehow get back a minus 1 we know there's been a problem okay so this tile an open square bracket and this is what we're going to use our enum we could just write 0 but I'm gonna use the enum here tile dot sprite which is we know from our macros is 0 okay tile sprite equals tile map data okay so whatever is in this particular cell is going to go into that entry of this of the grid okay of this array even sorry and then this tile open square bracket tile dot Z so the second entry of the array is going to equal 0 we'll come back and play with this Liam set it to a random value so we can see how the how it works but for now we're just gonna keep everything flat and keep it at zero so now that we have this array we're gonna put it into our DS grid so if I'm global don't move the map which is RDS squared open square bracket press the hash key okay this is what's called the accessor for a DS grid easy to remember because I hash them what kind of looks like a grid right and what this lets us do is type a a set of coordinates for the grid so a call a column and a row and it will return that it's is is accessed that exact cell of the grid and the exact cell of the grid we wanna access is T X and T Y from our for loop I close the square bracket so then we can just press equals to set that particular cell of this D s grid okay really easy just a bit easier than using the DF underscore grid functions which you can also use but this was just a nice shortcut way of doing it and then I'm going to just very simply going to write this time okay so that's our array and we're just sticking it into the DEA's grid all right so that's our create event if I just zoom out a little there this whole section just goes through our tile map and just puts each takes every single one of these tiles and creates a little array and sticks that array into our DS grid so that we have all the information about this tile map now in a global dense grid we're gonna access from anywhere it's pretty handy some of you might be wondering why no I'll just use the tile map that so do that why can't we just use the tile much control rendering well you could do that but doing it this way allows us to actually store more things about given tile as such as a tiles height right and various things like that that you'll find useful in terms of actually controlling and working with your game so it makes a lot more sense in my opinion do set up this D s grid and control it through there now this has been a lot of setup where that was actually showing off anything Google in the game and unfortunately we've got a bit more of that still to go okay we're gonna create a couple more scripts that are going to be very very important to us that are allowed basically once we've got these set up and we've got all this data set up working with our isometric game actually becomes very very easy okay so I'm gonna right click in scripts and hit create script I'm gonna call this a tile to screen X okay now this is what's important about this whole thing really this is the crux of the tutorial is being able to take a given cell of our D s grid so a given row and a given column given column in a given row find a specific cell and convert that from a flat normal grid into an isometric space okay because an isometric grid is basically like a weirdly rotated regular grid right so we can actually convert very very easily a given cell to a given screen position okay or room position I guess technically okay so how do we do this Omnitech bar underscore t x equals armyman zero and bar underscore t y equals argument one so we're gonna pass two arguments to the script T X and T Y and they're gonna represent which cell of the grid we're looking at so for example like if I go like five across and ten down we'd be looking at this tile right so our x and y in terms of our grid okay and then we're gonna use those values and return back an x coordinate in our room okay based on our ice an isometric x coordinate so don't worry too much about the mass of this I'm gonna include some links in the description to other articles to explain more in depth why this math works but I'm just gonna show it to you it's part this tutorial okay because this tutorial already gonna be really long I'm not gonna get into the isometric maths and all the background stuff like that so I'm just gonna show you this stuff I'm going to include some cool links that you can follow and understand exactly how and why this works that it works better if you read about it rather than hearing in a video I think but the line of code you want is just one line of code return open bracket open bracket again underscore TX - py underscore t y sorry close bracket so have that - that x tile width x more point five so half of our tire width close bracket close bracket okay it's um come on then never go away that's that's all there is to it in terms of converting cell x and sell wine into a isometric title position okay then we need another script to return so because this is just giving us the exposition we need one for the Y position so go ahead and entry just duplicate that script it's gonna be easier and to call it tile to screen why okay so again passing in the tile position however get the Y well it's actually almost exactly the same but you want to change this minus to a plus and you want to change tile W to tile H okay that's all there is to it so now we've got tile H as well there is something else we want to add to both these scripts but I'm gonna do it a little bit later just so I can show you exactly why so come back into a render and we're finally going to get to the fun part we were actually drawing the stuff to the screen okay because we've just been doing a lot of cell for the data so far now we're actually gonna get to the good stuff so because we've got these two scripts now we can very very easily convert any day or about on-grid into an antisymmetric drawing okay we're just cool you can build some isometric games with just these two scripts alone we're going to do another video that covers how you convert a arbitrary coordinate into a grid position that's kind of the next level it's a little more complicated but then that allows you to do really any isometric game but you can do so much to measure again so just these two scripts okay and now I'm going to show you pretty much how you call the game with those scripts so in the drawer event for home render I'll make it a bit bigger will maximize this I've got a few things to do in here the descriptions gonna be render game and I'm going to find var here one fun thing you can I don't do this often but you can define multiple variables on one line okay you can initialize a bunch of them and that's what I'm gonna do here I'm just going to find all the temporary variables that we're going to need so tile beta is gonna be one of them screen X is another screen Y there's another pile index entire Z again you might want to use room instead of screen for those names and again over here room at center screen whatever you do whatever you want and once again we're gonna use that exact same for structure that we use to cycle through the grid and the pen bar for sorry I'm bracket bar T x equals 0 T X less than map w semicolon T X plus plus and the same thing again underneath for VAR e y equals 0 to y less than map H TV y plus plus exact same thing okay so I coming through every single cell of RDS grid now this time the tile date is gonna represent something slightly different so tile date o is going to equal global dot the map again using RDS grid access over hash key T X P Y so that's gonna get our array that we stored in this position and put it into tile data so now how there is a 1d array with two entries pertaining the sprite and the the height of that particular time okay screen X is going to equal tile or room X if you don't that way tire yeah not time today tile with a capital T to screen X there we go open bracket T X comma T one be cool screen Y is going to equal tile to screen Y open bracket T X T Y and as simple as that so now we've got our screen physicians or room position drug you can think of it really for the isometric tile where to draw and now we just need to know what we're gonna draw that position to tile index equals tile data open square bracket I'll dark sprite close square bracket semicolon and tile a Z is the height we're gonna draw a tile data let's go bracket tile dalton's knee that's all mean them again semicolon okay and now we've got we know what we're gonna draw we know the height we're gonna draw it we know where we're gonna draw it so now all is left to do is draw it so assuming our tile index is not in 0 in which case is nothing for us to draw right we're gonna draw sprite s static is the name of the sprite the reason they call their stack is because obviously will it be in each one being a frame we're not gonna do animation and I suppose it could set up for animation but the way I structured it was the idea was these would be static sprites and if you want to do animated ones they'll probably be in different sprites do you really that's just in case you were wondering why I called that s tank the frame we're gonna draw is tile index minus 1 because obviously 2 doesn't exist in here okay so this would be naught and this would be one but naught would be no tile one would be the grass title and two would be this tile so we after you minus one okay the exhibition is screen X and the y position is screen y plus tile Z so then that will we bring our height into account okay so the higher our tile Z the lower down we're gonna draw our tile you could do - hair if you want z to work for you the way and it's up to you close bracket semicolon that is the lot so now have to remember the most important step which is to go into the room go to an instances layer or make one if you don't have one and drag Orenda somewhere into a more doesn't matter where now there's going to be an immediate problem with this but I'm gonna run this and show you what we have tada we have an isometric EMA but it's drawing off the screen over here to the side why is it doing that well it's just taking our grid and directly converting those directly converting that grid into an isometric grid which were kind of rotates that around that same point so that's still the top-left corner of our room there that is that Brown arrow and it's in the top-left like that drawing on that so if we want to bring this into the room there's a few ways you could do this you could use it views and cameras and stuff and just assume this is gonna be a coordinate 0 which actually might be the better way of doing things because you've got like a clearer understanding of what X&Y in the room means in relation to the tile grid but since we have those scripts to work that out anyway what I'm gonna do is just modify these scripts a little just as a quick way of doing this so if you've come into tile to screen X at the end of here we're gonna remove the semi-colon and open brackets screen underscore W times null point 5 so we're gonna move everything over by half the screen width and then a semicolon and then in Y we're gonna do something similar rather than get rid something going on just write it before plus a screen h x 0.25 so cor the screen height down then if we run that it should find that they're kind of best centers I need to mess around those numbers and do whatever you want as I say the best way of probably is to just leave those functions as is and build a camera system around it you are then obviously gonna have negative room coordinates and things like that I don't imagine that being a big problem but it could be but there's how you generate a nice metric room you see it's drawing all these tiles correctly one thing I'm going to show you before ending this particular part first of all I'm just going to add a few is browned and they're just a mix of how this looks a little bit if I'm also gonna come into a render going to build here and where we set the height of each tile I'm just gonna type I random 3 just to give us a little bit of random height on each one of those tiles and you can see they're all drawing slightly different heights now okay you can modify an individual tile to be a different height or just by running that in code very easily and so on and you could even do things like that like you could have specific tiles that when that tile is processed initially in here set the height to be lower or higher and that kind of thing allow you need to do more with your map editor or even build and then you could even build a tile layer over the top of here that determines the height of each tile like they never have a literal height map before you level okay but I like working with like this I think it's a very very cool way to work on isometric now I was like a top-down thing and then convert it and that's the exact system I use for building fireball okay on my live indoor game as I say there's gonna be a two partner okay I'm gonna do another video where we look at so we've already got these two scripts which is super powerful which is converting any given cell to a position on screen and you can build especially turn-based isometric games you could do with this alone but to do more advanced stuff more fancy things we want to be able to find it take a arbitrary screen position and convert that back into a tile so we've gone from tile to screen position no we want to go from screen vision of room position rather back to tile okay that's a little more complicated we'll do that in our next video thank you very much for watching hope you've enjoyed this one and I'll catch you guys next time as I said before this will be part of a two-part special on isometric stuff and second part coming early in the new year until then happy Holidays to everybody thank you to all of my patreon supporters throw all the best support throughout 2018 they're the only reason you've seen pretty much any tutorial videos from me throughout 2018 and then the only reason I can keep making them a shout out in particular and in no particular order to the following Arthur Kyle Wanderlei bounces the dog Bertie T daca Donder go Dan Erik Matthew Hibbs Jason Macmillan Kim massive alampi Marcus and dhwaja arias mark Lintz Matt coat Michael Ward Mike KB Owen Morgan Patrick Duffy Robert churches Rove and Alan run Stephen Hagen thornado Tobias Scholten Sathya flame and Zen an may thank you all ever so much I'll catch you all in 2019
Info
Channel: Shaun Spalding
Views: 81,415
Rating: undefined out of 5
Keywords: Game Maker (Video Game Engine), Tutorial, GameMaker Tutorial, GameMaker, Game Development, Indie Games, Tutorial Series, Game Maker Studio, Making Games, How to make games, GameMaker Studio 2, GMS, GMS2, Isometric
Id: BIq2pw6IZ14
Channel Id: undefined
Length: 35min 44sec (2144 seconds)
Published: Sat Dec 22 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.