GameMaker Studio 2: Action RPG Tutorial (Part 2: Animation)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome back everybody to part two if you're enjoying this series please remember it is funded almost entirely by good folks like yourself over on my patreon if you're finding this series useful and want to get early access to new episodes or just want to see this work get bigger and better you can hop over there and make all those things happen right today we're going to be animating the player-character last episode we made a big deal over the structure of our place right being split into four directions and like this and today is we're going to put that structure to work now other than actually getting up later to face the correct direction because our player sprite doesn't actually have anything to animate and okay it's just an idle sprite facing to the right facing left and down so we're going to bring in the run sprite for the player as well so we can show that in action as well so I'm going to press alt s first of all just to make a new sprite or command there so whatever it might be on a Mac I'm not entirely sure it just get a new sprite that I'm going to call s player run capital P capital R and then I'm gonna click import and back in our big a RPG and assets folder I'm gonna find somewhere in here it's one of the longer ones I think s play a run underscore strip 32 and bring that in and because of the strip's a teasing when I bring it in boom it imports all of our frames like that so as you can see similar to how this was set up facing to the right or left and then down this run sprite itself in exactly the same way and so if you want to make your own this is the structure you need to use each animation is eight frames long it doesn't matter how long the animation is as long as each direction has the same number of frames that is very important so it's 32 so each one is eight long so you've got an eight frame running to the right animation an eight frame running up animation left and down okay if I play that you just sort of like runs and sort of spins in a circle similar to how the player sprite just sort of spins in a circle right so once you've either brought that in or or made your own or whatever you can see it's exactly the same sizes as well like the mint oh no okay this one's actually one pixel wider one pixel wider than the original sprite was not very mad as I probably needed to do that in order to fit like some of that yeah I think that's like following looks like it would just I don't know I don't know why it's one pixel wire but it doesn't matter either way it's the same size like roughly anyway ain't hanging on the same space the dimensions don't matter too much as long as we get the origin in the correct place in order to do that you may you have to spend some time if you're making your own making sure that you're a lot of sort of lineup just the same way these these ones do positionally in the frames but the main important thing to get right here is when you bring it in to get the origin in the exact same space relative to the image not necessarily the exact same coordinates if it is a different sized thing I think ours works out the same position but just make sure that the origin lines up so are you using some sort of visual reference on the image itself as handy so as you can see here the origin is like right in between his legs like in the bottom Center down there and on this facing to the right one it's like on the middle of the three pixels here sort of like the the middle bottom takes a lot of the foot and that okay and so just make sure we've got that in the same position here so this is the very first frame of animation here so if I bring that down there on to that exact same pixel there because it's like the exact same frame starting off that's our sort of starting position so I'll make sure I send the same position there and if we go to up we can see that's in the same position there so we can check to make sure that they are lined up correctly if they're not lined up correctly then when you start moving around you're gonna have some weird like jumping like it all here like you blare like little seems to teleport a little bit as is suddenly as origin becomes a little bit offset or whatever when he swaps to this animation but the origin is all we need to do here we don't need to do anything with a collision mask we can leave that on whatever automatic is because we're not using it we're just using whatever the collision mask we set up in our original player sprite was okay this this manual kind of rectangle down here that's the only one we're worried about so this can be left as whatever whatever default that comes that's okay I'm someone closed both of those down now the next thing I'm going to do is open up our place but right not a player sprite I'll play a rob gate sorry and go into the create event where we're going to add a few new variables to control some more stuff to do with the play what I'm gonna do is add a couple of sprites to store the names of these sprites and that might seem a little weird because we can obviously reference the the sprites themselves in code but what I want to do is put those sprites into a into variables so I'm gonna write sprite run equals s player run semicolon and sprite idle equals s player so you might wonder why on earth it's worth doing that because you know if we can refer to this in code anyway why do we need to just stick this in variable and the clue is kind of in the name okay this is a variable it means that we can change this on the fly so if for example later on we wanted to change our running an idle sprites to be something else say I don't know we we changed character that we control or I know he's wearing a hat or you know something along those lines we can easily do it just by later on in our game just being like a sprite run now equals s player run with hats or something like that right and just gives us a bit more flexibility um I actually can't remember at this point in time if or exactly when I might do that throughout the series but it is nice to have that flexibility regardless so it's a good idea to do this either way let's just maximize this briefly just a nice habit to be in really and I'm gonna add one more variable to this which is local frame equals zero now some of you used game maker a little bit you might be aware of image index which is a built-in variable that tells us what frame of a particular sprite we're using but what we're doing is because we have this unique setup here where we've actually got kind of multiple animations within a single sprite well if we were on say this sprite here the third sprite the third frame of our up running animation this would be image index 11 or I think 10 if it counts from yet counts from one there so this would be this would be image index 10 but we want to know what frame were on relative to our current animation so when we want to show this animation we want to know that this is the this would be 0 1 2 right number this would be local frame - so that's what local frame is going to store for us it's going to tell us what frame were on relative to which directional animation we're playing ok so again rather than this one being 16 it would be 0 and this one rather than being 17 would be 1 and so on ok so those three things are all we need to add to the create event for now so I'm gonna right click and here add slash open event go to the step event bringing this back to here where we can see all of our movement code and all of our input code and stuff like that and at the bottom here I'm gonna do a section for updating the sprite so update sprite index this is this should be fairly familiar to you if you follow to my platform a tutorial and it's generally what we do right we've got we gathered our inputs for a frame we've done any movement and stuff like that we know what kind of state are a player is in and based on that and based on whatever current conditions are our object is currently in after deciding what our inputs and stuff they're doing we can set the appropriate sprite okay we know if I'm moving we know in what direction we're moving so now is the appropriate time to set our animation up all right so first thing I want to do in here is we need to store what sprite we're currently on it's gonna be important because it's gonna help us tell later on if we have changed animation this frame so in the time var underscore old striped equals sprite underscore index sprite index obviously storing whatever sprite we're currently on and just sticking that in a variable so we can we can remember later on what sprite we were on and color if you if you're very new to game maker you might be wondering what VAR is so just very quickly I'll go over that that's essentially declaring a temporary variable at the end of this script this script we're running now this bear will basically be discarded okay so stuff we don't we don't need to remember or look after okay very useful I always put this underscore in front of my bars my temporary variables helpful to distinguish them from any variables I might declared elsewhere so things like in my create like I might have I don't know maybe I for some reason have a variable called old sprite in here and you know it's helpful to make sure I don't accidentally conflict with those and and so on alright just my name in convention you can do whatever you want next I'm basically going to work out what it is we're doing and therefore what it is we want to how we want to animate so if input magnitude does not equal 0 wrong type of bracket there Direction is going to equal input direction and sprite underscore index is going to equal sprite run okay that's the variable that we put our s play run into and Direction is a it is a built-in variable that you can use with speed so if you set a direction you set speed or I'll get little move in that direction and so on but otherwise it's just a variable that stores a number and it's called direction so it's useful for us to store our input direction and the reason for that the reason you can't we can't just use input direction to determine what direction we're going to use in our sprite later because if we do you're gonna remember my input Direction is changing every single frame and if we're not pressing any direction then input Direction is going to set us to be like zero right facing to the right so we don't want to have it so that when we run to the left and then stop running to the left we instantly turn around and face to the right okay unless we press to face to the right okay so that's why we're going to set our direction only when we have an input magnitude and we're going to store it in a different variable so that we always have a direction even when we're standing still because Direction might be important when we're standing still right and so our our index is just being set to sprite run because we know we have an input magnitude that means we're trying to move in a particular direction now you could use speed for this so you could like add your speeds together and see if like they are lying add up to more than zero or whatever and to decide to do it that way based on whether or not you're moving I prefer to actually animate based on inputs rather than animate based on the actual end result because if we are colliding with the wall say we're against the wall on the left and we're pressing the left arrow key I prefer in a game when the character still animates and is trying to run rather than I'm pressing left against the wall because I can't move into wall-eyed therefore don't animate I just hide your stand still I prefer to keep trying to run so I'm still getting that input feedback as a player you can do whatever you like you could base this on your speed if you really want to I prefer to base it on the input magnitude and even put on what we're trying to do all right so if this isn't true then an input magnitude is zero then we want to just have a riedel strike playing so else sprite index equals sprite idle and last of all if old sprites does not equal sprite index local frame equals zero okay so here is that these two lines are basically are what's deciding which animation we're going to play okay it's just if we're moving in a direction or we're trying to move in a direction rather we've gone input magnitude then set I thought so the runs bright otherwise set ourselves to the idle sprite and old sprite stores whatever we had at the beginning so if old sprite is still if our sprite index is still the same as old sprite then we know we haven't changed animation but if it's not anymore than we know we have changed animation okay it's either gone from run to idle or from idle to run and if that's the case I'm gonna set a local frame to be zero and if you remember our local frame was our frame relevant relative to the animation within the sprite okay the reasons I do that firstly I like that visually I prefer visually like if we're like running along and our animation is here and then we go back to idle and then we go back to run we start from the beginning of the animation again but also it helps us a little bit later on it makes sure that if we have say say we're on local frame 8 of an animation and we change animation and say our idle sprite add like and you know our Idol spike doesn't match the anime but say our Idol say it did and it had like three or four frames of animation and we went from local frame 8 to suddenly in sprite Idol at local frame 8 that would be in the wrong place and it would be something we would have to account for later on and it just saves us a bit of a headache ok just by cleanly resetting this every time we change animation and we'll be doing this generally throughout throughout the game or whenever we need to change animation just saying local frame back to zero just saves us a headache of having to worry about what to do with it speaking of saving is a headache actually one more thing to mention about this direction variable that we used up here or you know why not use like I'll just objects Direction why not use like our own why not use our own variable for that why are we using the green built-in 100 one is just because it sits there and it doesn't do anything otherwise because we're not using we're not using the the built-in speed variable so it doesn't do anything with that but one thing this does do by it self which is quite handy and saves us hassle is it automatically wraps an angle so if we were to put a number into here bigger than 360 or less than zero it would automatically wrap it around to be the correct value so if we put in like 400 into here that's obviously 40 more than 360 so would wrap around and give us a back an angle at 40 and okay which is very handy just saves us having to worry about that ourselves and what happens when our angles go over 360 and that kind of thing all right so we know we're always gonna have a value between naught and 360 in here which is very useful for us later on when were calculating angles and stuff like that okay so now this sets our animation appropriately it sets us to the right sprite but our animation speed I believe is still 0 and the first frame of each of these is exactly the same still hook it's just that starting standing frame and we've got this complex set up in our sprite um how do we how do we animate any of this like because if we play this animation at any speed it's just gonna it's gonna go in a circle right so how do we combine that with our direction and work out which which air of the animation to play and play our animation manually not using our image speed to do this we're going to actually create a script it is we could just write the code down here like following update sprite index but this is gonna be something we're going to do quite a bit throughout the different states when we come to implementing the play a state machine and so on all our animations are gonna be handled in the exact same way so we're just going to write a script so that we only have to write this chunk of code once and we can just keep putting this script where we need to and we're going to call this script right here but first of all we actually need to make the script so I'm gonna right click on scripts and hit create script and call this player an innate sprite and I'll just leave a comment on the top what we're gonna do in here is update the sprite this first line is a little bit of a doozy so bear with me while I try and explain it I'm just gonna write out first vah underscore cardinal direction equals the floor open bracket open bracket open bracket direction div 45 close bracket plus 1 close bracket x 1/2 close bracket semicolon right you um if you're wondering how on earth did I come up with this it was just the first sequence of I'm sure there's other ways probably better ways of doing it um it was just the first bit of maths I could come up with and the got from 360 degrees down to numbers between noir and three in the vague arrangement that I wanted okay you can do whatever you want there's other things you could do here to get the right one and people have asked as well about if the system would scale up to support on like eight directions and stuff like that absolutely would you just have to find a different a different formula for you cardinal direction and kind of work out yourself um using these various different tools like how to get to the values that you want the rest of this script will pretty much scale for any number of directions to the best of moment I've not tried it I'm not tried it with eight directions or more but the way I've written it it should be moderate it should scale up fish it shouldn't actually matter so the next line is var underscore total frames um this is gonna work out how many frames we have in a particular animation within the sprite okay so for player run 32 frames in this sprite and if we divide that by four we're going to get eight which is the number we have in a particular animation within the sprite okay so at all frames is going to equal sprite and get number weird-looking form trim but it returns the number of frames with our sprite sprite index and divide that by 4 so again yeah if you are scaling this up you'll have to change that number to whatever however many number of directions you've got though that's more or less it okay I think that actually is the very last thing we need to that image index is going to equal local frame so we know that zero at the moment plus cardinal direction in brackets here multiplied by total frames and so this does a lot of heavy lifting whatever local frame we want to be on say well we want to be on a fair dream can't talk today frame number two here so zero one two of our first facing to the right animation between zero and eight so a local frame is to to get our image index we take that local frame two and we add it to whatever our cardinal direction is in this case zero multiplied by the number of animations the number of frames in the animation so each one of those is eight so upbeat zero times eight plus two gives us an image index of two which is this one obviously that's a bit different because it's the very first one but say we want this frame about facing up so we know we're facing to the we're facing up from our direction on our cardinal direction is going to be carnal direction is going to be one okay from 0 up to one and this is going to be local frame zero one two three four so we're gonna have four plus one times 8 so 8 plus 4 gives us 12 if we check that that's current frame 13 so from 0 to 13 that is image index 12 okay so that gives us the correct one and that that's pretty much that that's the magic line okay that's that's the thing that basically does all the heavy lifting of this and works out you know which which actual frame we need to be on and then all we need to do to animate is instead of incrementing image index by our image speed is we basically increment local frame by that instead all right so we do that by doing local frame plus equals sprite get speed open bracket sprite underscore index divided by and whatever our frame rate is in this case it happens to be 60 60 frames a second okay we will replace that with a macro a little bit later on in case we ever want to change our frame rate so we don't have to come into all the scripts and do it in fact let's do that now let's get that out of the way I'm gonna make a new script very quickly and call it macros in all cats okay I'm gonna move it to the very top of our scripts list and I'm going to type macro frame rate I always type macros and constants in all caps okay um just to clearly distinguish them as constants that are fixed and can never be changed and it's gonna be 60 no semicolon on the end of that it's important with macros okay so if you never made a macro before you can it's not really the full story but you can think of them for now as constants and they are baked into your game at compile time okay so you don't have to worry basically what it does is for every macro you have so for frame rate 60 it's gonna go through all of my code and replace anywhere that I've written frame rate with 60 okay that's that is actually how macro works okay it's gonna find everywhere I've written this and replace it with 60 when I compile the game um very very handy because then that means you know I can include this frame rate in a million one places throughout the game and if I ever want to change the frame rate I just come back to this macro script and just just change this number here okay quite useful and I don't have to call this macro script anywhere that I've call this anywhere in the game ago just having it exists in the project this will all get compiled in okay so you don't have to worry about calling it that's why I just have them all in one big script called macros all right we'll get a lot more things added to this as we go throughout the project but may as well kick this off early now so you know how it all works and we don't have to come back and edit it all in layers so I'm going to change that now from 62 frame rates all right okay so there sorry for the quick distraction there but I think it was important to get that okay right and yeah that's that up ahead of time so yeah all we are doing here just to remind you is animating by instead of increasing our image index we're just increasing our local frame and using that local frame along with whatever direction we're facing in how many frames there are per animation to work out what the actual image index should be so we never animate this via image speed ever like it would buy a game makers default system of animating ever we just animate by incrementing a local frame every single frame by whatever image index would have been increased by if we did have an image speed all right which is whatever speed we set in the sprite itself in this case let's play a run I think is 15 frames a second do and then you know dividing that obviously by frames so it's increasing it by the correct amount those seconds of 15 divided by 60 I'm increasing it by you know a quarter of a frame every every core of a frame every step that's what we want in order to therefore increase by yeah 15 frames a second okay so that's animating and that's controlling our image index the only other thing we need to worry about now is what we do when we finish the animation because if we just continue animate like this it's all well and good to start with it all stars in the right place but then what happens when we get to the end of an animation we're just gonna roll on into the next one right and it's still gonna animate in the same way so we need to manually deal with actually looping our animation and ending the animation so I'm just going to leave a comment first of all if animation would loop on next and gain step and if that's the case then we're gonna loop our animation and we can do that just by subtracting this total number of frames you still haven't changed cool yeah that's really weird by subtracting the the total number of frames all that given animation which is eight from local frame so though rappers back around same one week when we're here on local frame zero we get two here we just subtract eight and we're back to here again okay simple as that so if local frame greater than or equal to two all frames animation end equals true that's something we're gonna use a bit later it's handy for us to know generally for lots of different reasons when an animation has finished not in this particular case we're just gonna loop it when we're running it doesn't really matter to us but because as I say this is a script that we're going to use throughout the games to do various different animations when we're doing an animation that we only want to play once it's handy to know when the animation would finish so that is gonna be a variable that we're gonna set we don't have to define it elsewhere for now because we are going to define it here is either true or false in script itself so don't worry about going back to Korea event for now and local frame as I said before it's gonna be - equal total frames okay so that makes us compatible with a sprite with any number as long as I say each direction has the same number of frames in it so it's like it you know this cleanly divides by 4 or divides by however may directions you're using this could be a three frame animation or a 10 frame and it could be any amount okay as long as each direction in one particular sprite is that has the same same number so it scales and spelling modular and work with lots of different situations else animation end equal false alright so we know whether or not animation has finished at the end of this I say not useful now but will be useful a lot later on I'm just gonna close this down and reopen it and see if no I don't no idea why these aren't turning yellow or whatever this one hasn't even changed blue game maker can be weird about and sometimes specifically especially in scripts don't want that's about but don't worry too much as long as you've written it correctly don't worry massively if you can see that you've written it correctly don't worry if like mine it hasn't changed color as it as it should hopefully by the time you're reading this that's been updated and fixed no no maybe that's maybe that's a bit better in your version of game maker now who knows anyway and that's really all there is to it so I'm going to come back to our a player object come back to the step event as physical just click this tab up here but a force of habit down here so I call this update sprite index because that's what we're doing I'm setting the correct sprite and then in order to know what frame we're on we're updating our image index we're doing that by calling this script player animate sprite open bracket close bracket semicolon and that's a lot so assuming I haven't done anything wrong I'm gonna run the game now and we've got our player as before and when I start to move around we animate and when we stop we stop and that's all built from two sprites that allow where we would normally have Oh what for we would only have eight sprites for this right we've accomplished with two sprites or a more basic implementation would accomplish with eight by having all four directions in both our twos brights very very handy because we're going to do lots of different animations for the player throughout this game and if we had to do for four separate sprites for each one as sprites would become very huge and unwieldy very quickly especially if we had to keep mod of making modifications to them and like the size or collision box and things like that there's very helpful so I know this is developing quite slowly this is episode two and we're only just we've just gone to animating the player in a blank space but as you can hopefully see we are starting to set up systems that are gonna make doing stuff later on lots easier okay so it is worth it so it may seem like a slow burn to begin with but I promise you doing all of this flow setup is worth it for the eventual game that we're gonna make thanks guys that's it for this one next time we're going to be taking a look at basic collisions as they were building this up slowly but we are going by bit I am hoping to put these out weekly now in the new year we'll see how it goes I don't expect I'll be able to make that a hundred percent like every single week a new episode but that is that that's kind of my goal that's what I'm aiming for we'll see how it goes thank you as always to all my patreon supporters to the source code for these episodes you can either go down and make a one-time payment below or all of my patrons already have access to all that stuff and so you could go and become one of them you can also get early access to these videos every week see them a week before everybody else does and just enjoy the knowledge that you helped make them happen that's always cool - thank you special thanks in particular and in no particular order as always - army armed Buster arrow Barbarian Bailey raid Bowser the dog Bertie T cabbage pants dacha Donder go dark rider zero three one eight do what doobie Frederick Hobart ler gargoyle drink ha new coochie hair hi youngjun James L Anderson James Higgens Jason Christopher King Leo max and Nathan Wilson Owen Morgan pixel mush Rennie dam Robert churches Rove and arlynn run rependa Schaeffer Scott Matthews semion yo leg aglow Steven Hagen tee lesson Travis Womack Tyler Hubbell Victor Stewart Ville Virtanen Sofia flame and Xin unmei thank you all very much and thank you for watching cheers guys catch you all next time
Info
Channel: Shaun Spalding
Views: 133,932
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
Id: 9KxCE5QbK0s
Channel Id: undefined
Length: 33min 11sec (1991 seconds)
Published: Fri Jan 17 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.