GameMaker Studio 2: Melee Attacks Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody thanks to evoke by my patreon supporters I'm going to be showing you a comprehensive approach to Mellie attacks in games okay I've got this from the perspective of a simple platform game but it will also work for top-down games and pretty much anything so I've got my little hero here and what I'm gonna be showing you how to do with them is make it so when I press the correct button I do this little sword swing and that sword swing is going to detect using a hitbox sprite it's going to detect whether or not it hits an enemy or any number of enemies for that matter so you can see the flash that's going on when I'm hitting this guy here and eventually falls apart like a goofy skeleton and if I run over here and I position myself just right you can see I can actually hear multiple skeletons at the same time in part two of this two-part special I'm Elliot axe and then we showing you how to do combo chains as well so that instead of just doing the same like one static swing over and over if we press attack again within a certain window we do a different animation that can also have a different hitbox different amount of damage different qualities whatever you want okay so first of all let's go through the process by which this is going to happen because I think if you understand the process and you know enough about GML you might not even need to watch the rest of the video so the first thing we want to happen is have the player press a button and then the character play his sword swing animation we're going to use a state machine to accomplish this second of all we're going to empty or create I guess a DS list this list is gonna store everything that has already been hit by this particular animation every game step that we're in this attacking state we're going to check to see if we've hit an enemy we do this by temporarily swapping out our player characters collision mask from his usual walking around Rask to a mask that mirrors his attack there are lots of different approaches to storing and using hit boxes from creating other objects to manage them and so on and so forth but I think just swapping the masks out like this is a really elegant solution it doesn't mean you have to use precise collision checks for these swings because unfortunately in game make a precise collision checks that the only wants to support a per frame collision check and that's exactly what we need to make each frame have a different hitbox from the last the alternative is to store your hit boxes as relative coordinates via some sort of DS map json strategy json which is ultimately the most flexible and probably best all-round solution but it is a really big pain and takes a long time a lot of your own know how to setup and manage often requiring you to build some sort of UI or tool to be able to manage your hip boxes visually whereas this method is super elegant super simple and a couple of precise collision checks is not going to ruin your game in 2018 so after swapping to this mask what we're gonna do is use the new collision list functions to check to see which enemies we've hit which returns them into a TS list we check each instance ID in that das list to see if it already exists in our list of things that have been hit so far by this individual attack for each one that has not yet been hit by this individual attack we add its ID to the list of things that have been hit by this attack and then we cause the effects of the attack on that instance and that's pretty much all there is to it so let's get started so this is our players code I assume you were able to set up a game to the point where you have a simple platform away you can move around or a simple top down game and your step events gonna look something like this where you get your inputs you work out the speed you want to move you saw out any collisions and you do that stuff that's what Absalon here okay and some basic like these pH speed walks being we're a bit yourself in the create event okay I'm gonna keep press R just to restart the games all right that's really all we've got set up here so the first thing we're gonna do is set up a state machine for our player character okay all that really means I mean I have a whole video on this if you want a lot more information it'll be linked in the description but all it really means for the sake of this video is all of this stuff in the step event after we've got our inputs and we work out like where we're moving on our collision and that sort of stuff I'm going to siphon that off into a script okay that we're only gonna run while we are in a free state or an idle state where we're allowed to just sort of move around and act when we press attack we're going to move to an attack state where we're doing our a tank and we're checking to see if we've hit an enemy and so on alright so to set up our state machine the first thing I want to do and the players create event is I'm going to establish an enumerator for our players different states now on earth there's an enumerator mean or entail okay well you can create one by typing enon I'm gonna do that see the text goes yellow I'm gonna call it player state in all caps okay all an enumerator is think of it like a labeling system for numbers okay they're constants so like a global variable for example they can be used absolutely anywhere in your game referenced in any script any event anything once they've been declared and also because they are constant they can never be changed once they're established okay so it's good for establishing them as you never ever want to change we're going to have a variable called state and that's going to store whether or not we're in Free State walking around or whether in the attacking state and so on and rather than store that as state equals zero or state equals one it's better for us if we could store that as player state free or play a State attack and so on okay just because it's more English readable so literally think of them as that they're just a labeling system of four numbers in your game okay we're gonna have three of these we're gonna have player state free comma player's state attack underscore slash that's gonna be your chopping attack and then for part two we're also gonna have a tank underscore combo all right I make I like to take its time with this but eventually those will turn red there we go to establish that they're part of the numerator and that they are constant so there's a couple of other things we need to set up in here I'm just gonna leave some space between those variables an arena and I'm gonna first of all establish that state variable we were talking about so it's like state equals and then this is how you reference the enum player state dots free okay or dot two tanks slash and so on okay now you might be wondering hey we've we've declared that before actually defining our ena in the code how is that going to work well a funny thing about enums and all constants in general so enums and crows in the case of game maker is that you can establish them absolutely anywhere and your code in fact you can even define an enum in a script that you literally never call once in your game okay you could just make a script called macros and enums and you could use that and I often do when working on projects is a way to collect all of my enums and macros because that stuff all gets sorted out when your game is compiled and all the sort of text gets replaced in your code and you never have to worry about it okay the other thing we want to do in here is add hit by attack okay and this is where we're gonna keep our DS list okay of things that have been hit by the player so far by a given a tank and we just wiped that at the start of any given attacks IDs on a list and let's go off create very important when you create a DS list or DS structure in general it's pretty good practice to already go ahead and work out where you're gonna get rid of it okay because it takes up a space in memory and you don't want to create a memory leak or anything like that if you kept creating new players for example and getting rid of players without getting rid of that DS lists you might create a memory leak so let's add an event quickly at the cleanup event it's a handy new event in gaming studio - that happens when this object is destroyed or when the room ends and the object is destroyed and so on okay very handy for getting rid of stuff like DS lists and things that you might have lying around so I'm gonna right yes let's destroy Open bracket hit by a tank that's the only line we need it in there okay so with that sword out let's come back to the step event for our player which is this huge chunk of code let's zoom out a bit on this fine let's just maximize this so how do we turn this huge chunk of code into a state machine at the moment we're just you know processing everything all in one big step event well what I'm going to do is I'm gonna leave the keyboard inputs behind okay cuz those are important and I'm gonna chop everything else out okay so there's everything with speed calculations based on our inputs our collisions our animations is at the bottom here I'm gonna cut all of that out by pressing ctrl X okay just to place it all on the clipboard because we're gonna paste it into another script so I'm gonna right click in scripts hit create and I'm gonna call this script player state underscore three okay capital P capital s capital F and then I'm gonna paste that code straight into there then I'm gonna make two more scripts okay I'm gonna create a script called player state underscore attack underscore slash and I'm gonna make one more script called player state underscore attack underscore combo so now with the self out of the way we can go ahead and actually create our state machine so come to the players step event which is now mostly empty and just has our keyboard inputs then I'm gonna create a switch statement for our state variables when I type switch open bracket state closed bracket now all we want to do to make our state machine work is check to see what is currently in our state variable in the create event we already set it to be player state dot free okay so when it is player state dot free we run a run the player state underscore free script when we're in the attack state one or in the attack /script and when we're in attack combo we want to run that script okay so a switch that a switch statement is perfect for this it lets us check what's in this variable and lets us perform different cases based on what's in it so our first case is going to be case player state dot not a little dot free event and then a colon that's a proper colon not a semicolon as hopefully you're used to writing at the end of lines of code now and then anything we write after that colon is what's going to happen if a state equals player state dot free all right so all we want that to be is player state underscore free bracket close bracket semicolon then break at the end of here okay typing that break statement tells the switch statement that this is where this particular case ends our next case and next line of code is you might as well have already guessed is gonna be case player state dot attack I'll just go / : lair state underscore a tank and the school is / / break close bracket semicolon break semicolon and then the third line exactly the same I just go type it out so case 1 SD tank combo : player stay in the school combo a break please bracket semicolon break okay and that we're not even gonna use in this part but it's good to have a set up here doesn't really hurt us to have it so because there's no way if is actually getting to that state ok so I'm gonna come to the play of state underscore free script okay so after running all this stuff with all the collisions and stuff right at the bottom in a single line of code if he attack it's true state equals player state dot attack underscore / it's only press D thankee our state changes to this and therefore on the next step when we check to see what's in our state it's gonna be this and we're gonna run this script instead of this script okay alright so we've got ourselves into the attack state if we would run that and press the tank we'd finally we just find ourselves standing around doing nothing because we're no longer running any of the code for moving around so I character we just sort of stand there forever okay so let's come to now our play of state on the score attack underscore / script I'm just gonna middle click it here to quickly open it a new tab yeah and it's completely empty so what are we put in here first of all I'm gonna neutralize whatever our current speeds are okay even though we're not using the move yet just for when we come back to the free state later I want to just completely cut any momentum we previously had in favor of this attack all right so start of the attack so what I'm gonna do is check to see if we are just this frame beginning our attack and we can do that very very easily because this is the only time we would ever be in our attacking animations from their time if sprite underscore index does not equal s attack underscore slash that's okay so I've got a whole bunch of sprites in here the tank slash is the name of our slashing tank all right so if that's true then we want to set sprite index to be as a tank on let's go on slash we want to set image index that equals zero so that we're doing from the start of the tank that's very important and then we want to do D s underscore list underscore clear hit by a tank next up we are going to use attack hitbox and check or hits okay and we're going to do this by setting our mask index to equal s attack and just go / H B now let's talk a little bit about how I set these hitboxes up okay so I have s a tank a slash over here and I have s attack and it's got slash HB which you can see has this big red square now if I edit this a handy very handy thing for this in game X to do too is we have layers so if I turn on this bottom layer you can see I actually just duplicated the attack the slashing attack and then why did as I create a new layer on top which I called hitbox and I just drew a half transparent just so I could see what was underneath a box over the top have of our sprite and then once I was happy that I'd covered everywhere that I want the attack to be able to hit I simply turned the default at the bottom layer off invisibility okay leaving that as our final sprite very very useful because it means we've got the exact same number of frames it's lined up perfectly the origin is in exactly the same spot okay so if you want to create your hitbox that's how I recommend you do it just right click duplicate your original spray draw the hitboxes over the top and then mark that layer the original layer invisible okay absolutely perfect one other thing about the attack hitbox okay so make sure you go to collision mask select automatic and type is precise per frame okay that's very important that's what makes this whole thing work unfortunately does have to be precise per flame there is trade pro flame per frame there is no rectangle per frame unfortunately there's no ellipse per frame or any of these other things precise per frame is the only one that allows us to have per frame collision boxes which is what we need for this method it's unfortunate but it doesn't as I've said before it's it's not gonna matter in term of your game unless you have loads and loads and loads of entities all doing these kinds of attacks all the time it's not going to matter that much and I have an even better more elegant solution than this would require a much longer video and this video is already kind of long so it's a good method it's a good elegant method don't be too put off by this okay but do make sure you said it it is essential for this to work the other thing that's important to know as you can see an ass idle here I have occlusion marks already marked out for the general like collision box or player walking around and stuff okay that's not going to be affected by any of this so if I come to the player object NC collision mass and this is important is not set as it is by default - same as sprite it is set to s idle okay that means it's fixed in s idle and will always be s idle unless we specifically and manually change it which is what we are doing here in the code we're changing it to slash HB and then when after we're done once we're done checking for hits we change it back to s idle okay that's what we're gonna do right at the end of here it's very important that you do that because obviously we still want to have our regular idle collision box for checking to see like car collisions with walls where their enemies have hitters and so on okay so now that we've set our masks to be our hitbox I'm gonna write bar hit by a tank now to equal vs list we ate okay so I'm going to create a new DF list and this list is gonna store the IDS of every instance that we hit on this frame okay and that's what we're gonna then check against our list of things we've attacked with this entire attack all of its frames so far okay bar hits is gonna equal instance underscore place underscore list okay this is a new function GMs to x and y as the position the object we're looking for a collision with is Oh enemy the list that we're gonna store the hits in is hit by a tank now okay you need to have created that this list beforehand which we've just done that and ordered at the end will if you mark it as true we're not going to we're gonna mark it as false but if you do marketer just true it can be very useful it will return the IDS in the order of closest to furthest okay which can be really really helpful in specific circumstances to get a bunch of collisions and work out something that should happen to them in order of distance okay that's really really cool I cover that more and another video I've done on multiple collisions which you can go check out I might put that in the description as well why not okay what this will actually return though other than filling this list with all those IDs which it will do is it will fill hits with just the broad number of hits okay so if we collide with three things that will contain three so if it's greater than zero so if we've hit something on this particular frame for bar I equals zero semicolon I less than hits semicolon I plus plus so this is gonna do three like if we hit three things this is good would do three loops we had two things it would do two loops okay with I incrementing by one each time so we can go through in order each one of the hits and process them accordingly another Caracol e braces if this instance has not yet been hit by this attack okay so next up right before hit ID equals hit by a tank now open a square bracket typed a little a vertical line okay for me this is a holding shift and pressing Bank slash in order to get this character okay and then type I close bracket semicolon okay what this does and what this little weird character does is it's kind of shorthand before dealing with a DS list okay let us find a particular entry of a DS list as a shorthand way of writing it if you can't find that character or you find it too confusing you can also write I believe it's TS underscore list find value hit by attack now comma I okay and that will do exactly the same thing okay it finds that position in the list and gives you back the valley okay but that's a shorter way of writing it and it's very much a habit for me now to do it like that then if es underscore list underscore find underscore index okay open bracket hit by a tank comma hit ID close bracket equals minus one so what that does is we check to see if a particular value actually exists in the DS list at all so we found the whatever the top entry is of our list of things we've hit this frame we check to see if an entry matching that entry exists in our list of things that have already been hit okay if it doesn't if it doesn't exist then we'll get on minus one back okay and that's what will be the result of this X payment so if it doesn't exist in that list so we've hit something this frame that doesn't exist on our list of things we've already hit in that case we want to first of all add it to that list so DF underscore list underscore had it by a tack comma hits ie d close bracket semicolon and then we want to do whatever we want to do with our enemy and so we can simply type with hit ID so with the thing that we've just hit and then do whatever you want in here really I'm gonna write enemy hit open - close bracket what that does is it tells my game through my various other scripts that I want to hit this enemy object for to damage if I go into this script you can see it's just that's the argument I perhaps there is damage I want a deal happens to its hit points we set flash to equal true if hit points are still above zero then we go to the hit state its hit points are not greater than zero we go to a dead state okay it's just very simple whatever you want to happen with your enemies you that this is where you want to do it right you don't even have to do as a script like this you could do it with the enemy and do whatever you want in here but I'm gonna leave that to you because there's a just too many variations on how you might want your enemies to behave and react this is a simple one you know pause the screen now if you look into all this stuff and then then replicate like the mechanics of flash and so on the enemy but we don't have time for that in this particular video okay so whatever you want to happen happen to the enemy when they get hit this is where you want it to happen okay then that's it really for this leap so because I mean if that's this doesn't return minus one and it returns something else it means we've already hit that instance so far with this particular attack okay so we wouldn't want to do anything else so just bring all this up together so that's that complete loop done and then at the end of it we want to destroy the list of things we hit this particular step so this list of destroy hit by a tank now and then we want to set our collision masks as I said before back to normal skin mask underscore index equals s needle okay so back to the original collision mask okay so the very very last thing we need to do in this part is we're gonna make it so when this animation actually ends we start the tank stop the attack okay so the attack only happens once and then we go back to the idle State actually a little trickier than it seems and I'm gonna use a script that was very graciously loaned to me from the game maker subreddit discord called animation underscore and showers too pixelated Pope and many Python for this one this script basically will return true if the animation that you're currently in based on your sprite index in your image index and the current speed of your game and all that stuff is about to loop this step okay the manual is very misleading when it comes to showing you how to do this a lot of people have used this code as well where it tells you that if you were to write um so let's come back to our attacks date if you were to write if image index is greater than image number -1 then you're at the end of your animation and your animation is gonna loop this does not work it doesn't work right at all and the worst part of it is it kind of half works sometimes which just makes the misleading use of this and the manual even more distressing okay the reason this doesn't work is because if your image index say you've got six frames in your animation okay so we're starting from frame 0 and ending on frame 5 your image index is 6 so that's greater than image number minus 1 because it's greater than 5 right so you would think okay so that's when your animation is ended but the thing is your your image in X can never equal 6 cuz if your when your image index is incremented it happens at the end of your frame so after the end step image index is gonna go up by an amount depending on your image speed so if it goes to 6 which is more than the number of frames you have then it gets wrapped back around to 0 okay and then your next frame is rendered so the only time this would work is if your image speeders means that your image index is increasing at a rate of less than 1 per frame which it often is because we were you know if we're doing a 60 FPS game we're not gonna ruin all their animations 60 FPS so you might have image because of your image speed etc you might be going up like half a frame every step or whatever right and so if you got to five point five and yes technically your image index is going to be greater than image number -1 and it's going to check to stand it's going to consider the animation to have ended but the animation might not have ended because you're at five point five you're not at six yet which is where the animation will actually loop okay so you're not actually there this frame so it's still not quiet right it's just close enough that a lot of people haven't noticed that this doesn't actually work correctly also do not use this even though the manual tells you to okay it's very very wrong well I'm gonna use instead is this script called animation end as I say courtesy to the game maker discord I added this at the bottom here just dude credit these guys who helped me out with this and showed me this it's where I go it's where I do a lot of my research for these tutorials and a lot of topics if I don't already know what I'm doing with them and I need to learn stuff I go and ask these guys there's loads of really cool guys on this discord really helpful information highly recommend them as a place yeah so their script what it does you don't even have you can pass in arguments but if you just call animation end open bracket close bracket I'll leave this up a little while you can pause the video just copy all this down I mean you can put paste bin in the description or something like that if you just call this then it will tell you it will return true or false based on whether or not on this exact step the animation is going to loop okay which is very very useful it tells you how's the animation just ended super super useful so with that in mind with this script being in mind for doing that of course the other alternative here is you can also just use the animation end event of the animation end which does the same thing that does work correctly but in order to do that we would then have to check our state so it would be like if animation end and we're in the attack state and it's separate out from our state machine so I don't like doing that I've relied on this in the past and in even from previous tutorials but I don't like leaning on the animation end event so we're not going to use it in this tutorial okay so if the bomb here I'm gonna say if animation underscore Oh market closed bracket okay when I'm gonna pass anything else in because we don't need to really know if it even has parameters for checking stuff like if you were using your own manual system you can pass in the rate of frames per step it's that's quite fancy really but we don't need that so if animation and sprite underscore index equals s Idol that's back to our regular animation and state equals player state dot three and that's it that's the end that's every bit of code you should need for this let's run now and hopefully I haven't forgotten anything because that would be kind of embarrassing so let's run this now we've got Blaire we can move around I mean I can press the attack button my case being said and also believe H I can run around press this and we attack and it does our attack it registers the hair it's finding the hitbox you see if I stand like okay no our hitbox is really wide it's kind of hard to show that the hitbox is working the paper bog is also working on a precise level as well so you could even you don't even have to use a box and the way I've done it um so let's just quickly take a look here so you're like I've doing it like a box um over the sword cuz that's like true how traditional hitbox is look you don't have to do that if we're using flies ones but you'll find you probably want to anyway it sounds weird and and intuitive for bidders design reasons players kind of expect well the players don't expect really precise collision boxes they can sometimes work in certain situations I think this would work if you could it have to be exactly circular with the with sprite like that but for example in things like the idle of sprite and stuff especially if it's to do with you getting here and that kind of thing if I'm players are often actually kind of thrown by super precise collision boxes and sounds I'm tiny to it if that it is true but I'll leave that to you that's your own design decisions to make so if you want to you can make these absolutely precise thank you very much for watching in the next part we're going to be looking at combo make it so we don't have to do this single boring attack every time we can mix it up with multiples I hope you'll check that out thank you very much for watching thank you for my patrons for selecting this topic and for supporting what I do speaking of my patrons here they all are now these are the guys that allow me to do what I do I couldn't do any of this stuff without 'ln thank you ever so much to them thank you ever so much in particular and in no particular order to Andrew Gilbert Arthur Kyle Wanderlei boughs of the dog Bertie T da kodanda go Dan Erik Matthew Hibbs James grimly Jason Macmillan James Cole hammer Kemosabe Lampe Malcolm mark Lintz Michael Ward Mike KB Owen Morgan Patrick Duffy penguin muffins Robert churches Rove and darlin run Steven Hagen to buy a Scholten turtle time Zef e aflame and Zinna a thank you ever so much and thank you for watching I'll catch all of you next time
Info
Channel: Shaun Spalding
Views: 116,729
Rating: undefined out of 5
Keywords: Game Maker (Video Game Engine), Tutorial, GameMaker Tutorial, GameMaker, Game Development, Tutorial Series, Game Maker Studio, Making Games, GameMaker Studio 2, GMS, GMS2, Melee, Melee attack, Melee attacks, attacks, swing sword, combo, chain combo, hitbox, hurtbox, gml, programming
Id: 93Dz2hgsZy0
Channel Id: undefined
Length: 31min 47sec (1907 seconds)
Published: Fri Nov 16 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.