Over the years many people have suggested that this code will cause your player to be "invincible" for a frame because of swapping the collision mask. This is not true. You're not invincible as the code runs sequentially. You swap masks and then you swap back after the check is complete. An enemy will only ever perform its own check before or after this, not during. So it is not in any sense invincible at any point. Even if we forgot to swap it back, you would actually just gain the collision mask of the attack and you still wouldn't be invincible. Though it would be undesirable! Nontheless, as long as you swap your collision mask back after finishing your check, there is no problem at all.
Hey Shaun, I would really appreciate if you would do an "updated" tutorial for this, since scripts have changed and many people including me, on the forums don't know how to set up these types of states with the new changes
@@SaraSpalding ive just seen it. my code: state = walker_patrol(accspd, maxhspd) script_execute(state); i get error „script_execute argument 1 incorrect type (undefined)“ the two arguments are defined in the function walker_patrol so any idea whats wrong?
@@yungefendi6480 by supplying arguments you're calling the script, not assigning it to the variable. You assign a function to a variable by writing its name without the brackets.
If you are receiving an error re: Variable and the location is one of your scripts (such as PlayerState_Free), you may be missing the "function" line in your script (introduced in version 2.3.0). In each script, you need to add "function", then the name of the script [such as PlayerState_Free()], then place the contents of the entire script in curly brackets. Ex. PlayerState_Free script should be: function PlayerState_Free() { **the contents of your script/the script from the video go here** } When you create a new script, GMS will actually present this format automatically, and will have notes that the script assets changed for v2.3.0. Hope this helps!
Great video tutorial Shaun! Clear, simple and that animation_end code is truly a life saver. Just a heads up for everyone: If you want to make your player attack while airborne add image_speed = 1; under image_index = 0; in the attack state script. Somethin like this: //start of attack if (sprite_index != player_attack_animation) { sprite_index = player_attack_animation; image_index = 0; image_speed = 1; } That way your player won't act crazy when you attack in the air and probably you don't want to set your horizontal and vertical speed to 0 for it to work. Also make sure that in every animation the upper right option is set the same. If you don't your player will teleport when you attack. Hope it helps anyone with the same issue!
Thanks for this tip; was wondering how to stop my char from freezing in the air. Now I'm on to trying to figure out how to keep my momentum through the attach animation. I've even put the move code in the attack state, but regardless every time I attack my horizontal speed is zeroed for that fraction of time. If I click attack a lot it's very clear that my character stops current movement to perform the attack. But I want my character to show attack animation while still moving in the current direction. Quite frustrating.
ATTENTION: If you're using the latest version of gms2, there should be one extra line of code at the top of the scripts, and curly braces after said line of code and finish after the entire script.
I NEED HELP! I've been following Shaun's Complete Platformer Tutorial playlist, but I wanted to add melee attacks instead of guns and shooting. So I ended up here, trying to incorporate this into my project. I added the function "script name" with curly braces covering the entire script from my previous tutorial's work's coding for movement, pretty much as Shaun has done in this video. But since I've added this "ATTACK" script and "FREE" script, I can no longer move (or punch). We've called scripts in his platformer tutorial before and I did it the same way. I don't get any errors when running the game, I just can't move or attack with my character, he remains in idle.
@@nathanlawrence656 I´m not sure. Did you move the part of the code where you calculate horizontal and vertical movement to the script with the attack state? Because then you´ll only be able to move while in that state, so you want to keep all that stuff in the normal step event for the player
if anyones getting stuck in the air and only playing the first frame of the attack remember to make your image speed 1, in some tutorials (like shauns platforming one) they have you make your image_speed 0 so when you attack in the air your image_speed stays at 0 so you do no animations nor do you progress to the part where the hitboxes come out in your animation. :)!
Hey there, just wanted to thank you so much for this tutorial! In fact, your platformer tutorial series was a basis and amazing startup for my GML journey, and so far It's been an experience, from just "Hope this works" to "This will work so good" mindset Was looking for a framework for melee attacks and saw your's and implemented it to my game and it works perfectly. Hope you are well and looking foward for more videos in general in the future!
I'm getting a "Compile Scripts...Error : duplicate script name found gml_Script_Playerstate_attack_hit" whenever I try to run my game. Did you get this? and how did you fix it
to anyone getting stuck in the air on the first image when they try to attack: change where it says "image_index = 0; to image_speed = 1; it worked for me
Thanks Shaun again for building a bridge for us new to GMS to learn the ropes and build our ideas into reality. Thanks also for giving credit where its due, it creates a great example to follow.
I was amazed when the code in this tutorial worked after only 1 bug fix. That's a first for any piece of code from any tutorial. Absolutely amazing tutorial.
WOW.. I was just trying to figure out how to code melee attacks in GM Studio (I'm very new to GML) and I have been watching your tutorials, and now you post this video, thanks so much for great tutorials! Wish you the best!!
It's not identical! It's incredibly close because I just really liked that sprite (and I'm a bad artist who relies massively on reference). But I did all the swings myself! ...that counts right?
Same here, I am capable of modyfiing sprite to suit my needs but I always need a template. The most original thing I painted was sprite of Peanut with legs that goes up and down. And I did that on accident. In one of my projects I used sprites from The Escapeists as a template for both Player Character and Zombies, and to call them my own I have added idle animation and improved current walking animation. I probably reuse those sprites as a template since I have lost interest in that project. In my current project I have used Frisk, repainted it black/red/grey added three hand gestures and +- 10 facial expresions. And here is Magican The Great. SkelyHat, autor of said sprite, looks really fine with people using them as long as he/she gets credited.
@SrTreo I believe the correct term is “wooosh”, not “r/wooosh” There’s no reason to include “r/“. Besides, the guy you replied to doesn’t even deserve to be woooshed.
At 15:34 you said that there's a method faster and better than collision precise per frame. Could I ask you a tutorial over that method? I really like your videos, thanks you.
damn, ive been using extensively the image_index > image_number-1 thing for over a week now on a project BECOUSE of the manual and now by chance i see what you just said there, and that explains quite a few things now haha thanks for that
If want to be able to control how your player moves while attacking youll have to put all of your movement code into the player attacking state. The best way to do this is to instead make a new script and paste it there. Then you can take out anything you don't need or want to modify and call that script while in the attacking state. so you would have your player move into the Player_State_Attack and the first line would be PlayerMovementWhileAttacking(); or wtv. Took me a while to figure that out.
This was such a big help, thank you so much! I copied my Collide and move code into a separate script and then called that script at the beginning of the PlayerState_Attack_Slash script. I also copied this into that new script to make sure that the player is facing the right way: if (hsp != 0) image_xscale = sign(hsp);
The new attacking state doesn't have any movement code in it so you'l have put in movement calculation in there. You don't need to declare variables or anything. Best thing to do is copy the movement code from your original o_player code and into a script and then call that script at the beginning of the attack state script. Then you can change wtv you want like gravity or walkspeed and it will only be that way while in the attacking state.
var end_anim = image_index >= (last frame) if(!end_anim){ image_speed = 1; } else{ image_speed = 0; image_index = 0; change state..... } That's how I usually do animation end, but the script you posted is great!
Yeah, the biggest problem with this is that it's no longer accurate for GMS2, since your sprite can be in frames per second or in frames per step. Which is why the script is so much more complicated. That being said, if you know ALL of the sprites that will use the above code are set to frames per step, then yeah, that'll keep working.
By this time tomorrow all comments will be saying the character looks like Kris from Undertale, but you're wrong, the colors are wrong and so is the hairstyle somewhat. This is actually Ahrac from Nutdealer
BabyPinkSnail I have a channel that does speedpaints, animation and coding and animation tutorials, and funny and storytelling animations please consider subscribing
I'm currently stuck on making the enemy take damage. I'm not really sure how to set up an enemy script because you didn't show them too much. I'm trying to figure out how to do it (either with scripts or alternative methods), but I can't find anything online and I don't know how to do any of this. Everything I try with my limited knowledge just does not work.
instead of calling the enemy damage script under "with (hitID)" put instance_destroy(); that should ANIHALATE the instance id of your enemy being effected in your for loop :)
Hello! I followed this tutorial and l am having a slight issue... My character attacks and animates properly, but only while I'm on the ground. If I try to attack while mid-air then it freezes on the first frame of the attack animation and he gets stuck in mid-air. I tried applying the physics code from the free state, but all that does is make him slowly descend while still frozen on the first frame. And then he's still stuck after hitting the ground. Am I doing something wrong? (Probably)
Did you fix the issue already, if so could you provide me with your fix. I'm having the same problem and all I could figure out is that it is probably caused by the animation_end() script.
@@vanthelow haven't got it figured out yet. I will let you know if I do. Although, I get the same effect even if I remove the animation end script from the equation.
@@CrawlingShadow9 yeah I noticed that too, it is weird because any other code i put in the script works fine, except this one. I'm actively working on the project and that bugfix so ill let you know too if we coms up with something.
Thank you so much Shaun Spalding for all of your tutorials you have been a big help for me so much with because of you I too was able to release my first game SA4A and soon another title thanks to you. Thank you for all that you have done. Have been and will be supporting you all the way.
this might seem super simple, but i want to know, if i have more than one enemy, how do i reference it? you just put oEnemy in your hits variable, but what if you have multiple types? the parent enemy does work. i would really appreciate an answer
Well it depends on what you mean "more then one enemy". Asuming you mean multiple enemy _objects_ (oArcher,oKnight,oMage...) creating a parent object oEnemy and making it parent of all enemies, then using oEnemy in colisions should work.
For my current version of gamemaker(lates 2023 version) the animation end wont work because spritespeed_framespersecond dosnt exist and neither the code download nor shaun show whats in there.
At 22:30 EnemyHit doesnt work because we cant see the script for the others. i dont understand the argument0 part. its telling me EnemyHit takes no more then 0 arguments but 1 is provided. :(
Most of the comments are saying the fighter is Kris from Deltarune or the sprite is similar to Kris. I do agree with that. (I’m a huge fan of Deltarune)
PLEASE HELP!!! I copied the stuff from the step-event over to the script like you did (without the keyboard-checks), but when i try to run the game, it shows me an error that i didn‘t set the variables (right, left)… Ples help me 😢
whats in the other scrips like the enemy free and state hit i dont think what youre showing can function without the codes in those scripts unless im getting something worng
Hmm, hard to say without knowing "the exact code" but there is a chance you are useing reffering as an object which affect *all* instances of said object. In situacions as this you should use id of instance/s which got hit.
Hey man i know im a bit late but im doing my first game and your guide is being SO helpfull by now. I was wondering where to find the combo slash tutorial since i cant find in your vids (im blind) Good work and thanks!
22:23 are there any other tutorials that i should watc before this one, because he doesnt show where should i pu tthis exactly, or how does this connects to the enemy and many other things
I haven't tested this, but if you add gravity to the attack scripts, it should work. (The reason your character isn't falling is because horizontal and vertical movement was set to 0 in the attack script) Except the collision mask is now different so you'll probably collide with the ground wrong if you hit it before the animation stops. Again though, I haven't tested, but that would be my first guess.
does this still work for top-down games? I am looking to implement a melee combat mechanic to my top-down shooter game for some variation and was wondering if this would still work
2:35 couldnt you just have an actual sword sprite with a cheap rectangular collision mesh matching the width of the sword, then have the mouse attack button simply rotate the sword in an attack motion, kinda like skeletal animation? So you just have a sword object glued to the players x,y that has a simple "on collision with enemy = " blabla?
When you make the horizontal and vertical speed equal to 0 upon entering the slash player state, is that entirely necessary? It seems like it would allow for people to just spam the attack button and hover in midair, and I don’t see any consequences for not implementing it.
Hey Shaun! Thank you so much for this video it's super informative! I just have one question, Because you are swapping the collision mask from your sprite to your weapon, is it possible that you could run into problems with the wall collision checks? For example walking through walls because your hitbox is not more to the right or something like that? Thanks!!
I copyed everything but for some reason after i click the attack key my character keeps on repeating the animation and never stops which disables my other controls. Can someone help plz :) never mind i fixed it. Just didn't copy 2 extremely important parts thats all XD. Thx for the great tutorials tho.
Can someone help me! For some reason, the function instance_place_list is not turning orange even though it is written the exact way it is shown in the video.
if(hits > 0) seems redundant to me as instance_place_list() would return a value of zero if there are no collisions, meaning the for loop wouldn't do anything in such a case
The hit list is a really good idea than to use “invincibility frames”, as it just merely slows the hit frequency and just acts as a damage cooldown before the enemy becomes vulnerable again.
i followed everything the best i could, when the enemies collided with the hit box, they got hit every frame. i tried everything but i can't seem to get it to work, can someone help me out here?
Seems like the only thing that doesn't work for this now is the ds_list_add on line 24 of the PlayerState_Attack script. Looks like it just never adds the hitID into the hitbyattack DS.
Can someone explain to me what part of the code, makes the enemy just take one instance of dmg? Im trying to use the code mixed with mine, and the only problem im having is that the enemy is taking dmg on every frame of the attack.
soooo i followed everything and checked multiple times but my character if on ground just keeps playing the attack animation on loop, i can't move him nor jump , also if i run the game again and start by jumping then press the attack button he just stops mid air, does the attack animation once then fall and return to FREE state, i tried changing stuff but still didnt work
ichimo I have a channel that does speedpaints, animation and coding and animation tutorials, and funny and storytelling animations please consider subscribing
No it doesn't. You're not invincible as the code runs sequentially. You swap masks and then you swap back after the check is complete. An enemy will only ever perform its own check before or after this, not during. So it is not in any sense invincible at any point.
Everytime I try to run my game I get an error message saying that my player sprite was not set before reading it. The exact message is Variable .sprite_index(25, -2147483648) not set before reading it. at gml_GlobalScript_PlayerState_Attack_Slash (line 5) -if(sprite_index != spr_player_attack)
@@theburgundysweaterman6623 I figured it out. Should have updated this. If you’re running the newer version of gms2, you need to keep the original brackets you get when you create the scripts. It’s very important. Otherwise the script runs all the time, not when it’s supposed to execute.
fixed it but now i get Variable ._keyRight(100021, -2147483648) not set before reading it. at gml_Script_scr_player_normal (line 4) - hsp = (_keyRight - _keyLeft) * hspWalk ############################################################################################ gml_Script_scr_player_normal (line 4) gml_Object_obj_player_Step_0 (line 16) - case Pstate.free: scr_player_normal(); break;
sooo... how hard is it to impolement a state machine in your platformer video if im like 15 episodes in. its just i designed my character for melee and i thought that tutorial would cover it and now im trying to implement state machines and my player keeps getting stuck in mid air and things are just crumbling at my feet when i try to implement it. is it too late?
Not exactly, this simply changes the player's hitbox to match that of the attack hitbox. So this means you can still be hit but you will instead take damage when an enemy attack hits your attack, which doesn't make a lot of sense! So to fix this you would instead create a new invisible object when the player attacks, you would then change this object's collision mask instead of changing the player's collision mask. In code, this would be nearly identical to what is shown in the video with the only difference being that whenever you set `mask_index` you would instead be changing the `mask_index` of the new invisible object which could look something like this: function PlayerState_Attack_Slash() { hSpeed = 0; vSpeed = 0; if (sprite_index != sAttack_Slash) { sprite_index = sAttack_Slash; image_index = 0; ds_list_clear(hitByAttack); } var hitbox = instance_create_depth(x,y,depth,oHitBox); hitbox.mask_index = sAttack_SlashHB; } You would then have the rest of your collision and hit detection code as normal or you could place the attack collision code in the oHitBox object. You would also of course need to destroy the oHitBox object once the attack has finished.
@@mikusama8030 Oh okay, weird. Well thanks for explaining that. I suppose if you're doing melee combat with the need to check things at each different attack sprite this is unavoidable. Thankfully in my case I'm making something that's more like a traditional 16 bit game where attacking either kills the enemy or makes them flash for a moment before you can hit them again, so I can just use the technique from Shaun's other "melee combat" video that creates a hitbox object independent of the player
No. This isn't true at all and neither is MikuSama's reply. You're not invincible as the code runs sequentially. You swap masks and then you swap back after the check is complete. An enemy will only ever perform its own check before or after this, not during. So it is not in any sense invincible at any point nor will enemies (or the ground and walls for that matter) use the attack hitbox of the player for any reason outside of this attack check. If it worked this way you would also presumably fall through the floor. Note that this does not happen in the video.
How do I include various objects? To be more specific how do I make the attack hit not only just one type of object. I thought it would be as simple as adding all the objects into the arguement but it just breaks it. any advice?
Can you do a tutorial on delta time next? I've been searching for tutorials on RUclips but never found any good ones. Delta timing is really important for fixing lag, and other game engines like Unity already have delta time built in. Thanks
GMS has delta_time variable built in, it have amount of microseconds that happened between frames. So movment per frame can be counted as movement per seconds *delta_time/1000.
How do I change what direction the player is attacking in based on which direction they are facing? I can’t figure that part out. When I walk left and the attack animation faces right, it automatically attacks to the right. I duplicated and flipped the animation, now I just need to know how to program it to pick the right animation based on the direction
hey shaun, huge fan of the work you do. i'm just wondering, how would i use the collision checking code for different enemy types? with "var hits = instance_place_list(x,y,obj_enemy,hitbyattacknow,false);", the code seems like itd only work on specifically obj_enemy. I'm currently working on a game that will have about 20 different enemy types plus a few different boss characters, how would i be able to implement this code without repeating it for every unique type? a solution i was thinking of was to just change "obj_enemy" to "all" and just have some sort of switch case determine if the code should run, but surely there's a more elegant solution? I'd rather have, say, hitting walls or scenery not even be considered by the code if possible thanks!
did u manage to do it man? I'm trying to do the same, i have 2 enemies with diff object, idk how to do this, i already tried listing both objects and putting the list in the var hits but the enemy doesnt take damage this way
Has anything changed in the 5 years since this was posted? Do scripts need to be written differently than events? I keep following along, but I'm interrupted with warnings that my code should be written a different way.
So I have two different sprites, one for moving and one forstill with a sword, how do I code it so that those sprites only show up when I hit the button Thanks!
so far i always just used the collision box collision event with enemy to do melee damage , is there any benefit using this method over just collision event ?
hey Shaun! Quick question - I have a gamepad and all the face buttons, and the axis work fine, however the dPad doesn't work at all. I looked around and saw others had the same issue, but there was no solution. If there isn't a way to get them to work, is there a way to have the analog stick act as a 4-directional input? I'm trying to do an old-school style top down movement, and if the dpad doesn't work, that's the next best thing.
You could use an ”or” statement Example (xDir = analog_Left; || xDir = Dpad_Left); Disclaimer, not sure if this actually works or not, and the code for the inputs are different from what they’re called in gamemaker. (Like wtf is dpad_left lmao)
Ive got a question, Ive followed the code correctly, but somehow, it does everything except for interacting with the object its supposed to be interacting with. it actually doesnt do anything. no hits, no destroying, not calling up the script, nothing at all. any ideas on how i can solve this??
Awesome tutorial! Looking forward to seeing more videos like these. By the way, I would really love it if you made a tutorial on a dash mechanic, I really need help on that and there really isn't any new tutorials about this, at least I couldn't find any GMS2 dash tutorials, so that would be pretty cool.
after that, it needs to set hsp to the previous value , but out of the if statement, because if you don't, the hsp will always be equal to the value it returns if you press the key
I doubt anyone will see this before I figure it out myself but: I'm having trouble with getting it to reduce enemy HP properly. I'm trying to have it be every hit reduces the HP by 1. But I think the game is calculating this as every frame they're getting hit by = -1 hp. so one hit does like 5-6+ hp (or however many frames the hitbox is colliding with an enemy) instead of a flat amount
how can i create a new enemy ? did i really have to create each time 3 new scripts for each enemy ?! like EnemyBlobState_Free / EnemyBlobState_Hit / EnemyBlobState_Dead and if i want to add some movement and attacks to my enemy i have to create EnemyBlobState_Move / EnemyBlobState_Attack ??
Helpful tutorial. The only thing is the player will freeze if attacking in midair. I followed the code closely, but have to restrict the player to only being able to attack while on the ground (which works fine for the game I'm working on, but just saying)
Over the years many people have suggested that this code will cause your player to be "invincible" for a frame because of swapping the collision mask. This is not true.
You're not invincible as the code runs sequentially. You swap masks and then you swap back after the check is complete. An enemy will only ever perform its own check before or after this, not during. So it is not in any sense invincible at any point.
Even if we forgot to swap it back, you would actually just gain the collision mask of the attack and you still wouldn't be invincible. Though it would be undesirable! Nontheless, as long as you swap your collision mask back after finishing your check, there is no problem at all.
Hey Shaun,
I would really appreciate if you would do an "updated" tutorial for this, since scripts have changed and many people including me, on the forums don't know how to set up these types of states with the new changes
@@yungefendi6480 you do exactly the same thing just put each script into a function. I made a video on these changes a little while back.
(I do however, plan to update most of these videos eventually)
@@SaraSpalding ive just seen it.
my code:
state = walker_patrol(accspd, maxhspd)
script_execute(state);
i get error „script_execute argument 1 incorrect type (undefined)“
the two arguments are defined in the function walker_patrol so
any idea whats wrong?
@@yungefendi6480 by supplying arguments you're calling the script, not assigning it to the variable. You assign a function to a variable by writing its name without the brackets.
Because of you I have released my first game and it got 200 downloads on the first day. I owe all I know in GM to you, thanks so much
Aljon D. Do you mind if I get a link to the game I'd love to check it out!
Seconded, I'm really curious how it is!
Yeah. Link? Please
If its the one on your youtube page i gotta say it looks pretty nice, well done!
@@Tneeder that's the one. soul chase is the name. thanks! glad you liked the trailer!
If you are receiving an error re: Variable and the location is one of your scripts (such as PlayerState_Free), you may be missing the "function" line in your script (introduced in version 2.3.0).
In each script, you need to add "function", then the name of the script [such as PlayerState_Free()], then place the contents of the entire script in curly brackets.
Ex. PlayerState_Free script should be:
function PlayerState_Free()
{
**the contents of your script/the script from the video go here**
}
When you create a new script, GMS will actually present this format automatically, and will have notes that the script assets changed for v2.3.0. Hope this helps!
my brother... thank you so much!
you saved my fuckin sanity dude, THANK YOU!!!!!!!!
Part 2 out next Friday! (or now for $5 patrons!)
Here is the animation_end() script that was used:
pastebin.com/0AsJn1WB
not working plz update
Great video tutorial Shaun! Clear, simple and that animation_end code is truly a life saver. Just a heads up for everyone: If you want to make your player attack while airborne add image_speed = 1; under image_index = 0; in the attack state script. Somethin like this:
//start of attack
if (sprite_index != player_attack_animation) {
sprite_index = player_attack_animation;
image_index = 0;
image_speed = 1;
}
That way your player won't act crazy when you attack in the air and probably you don't want to set your horizontal and vertical speed to 0 for it to work. Also make sure that in every animation the upper right option is set the same. If you don't your player will teleport when you attack. Hope it helps anyone with the same issue!
Thanks for this tip; was wondering how to stop my char from freezing in the air.
Now I'm on to trying to figure out how to keep my momentum through the attach animation. I've even put the move code in the attack state, but regardless every time I attack my horizontal speed is zeroed for that fraction of time. If I click attack a lot it's very clear that my character stops current movement to perform the attack. But I want my character to show attack animation while still moving in the current direction. Quite frustrating.
This is literally exactly what I needed, and I wasn't even looking for this! Thank you!
6 yrs later... Thank you Shaun. I hope you keep up with the videos, you are too important for the Game Maker Community
ATTENTION: If you're using the latest version of gms2, there should be one extra line of code at the top of the scripts, and curly braces after said line of code and finish after the entire script.
What is the line of code
@@maitreyiramkumar7219 function i think
something like function name { the script } i think
I NEED HELP!
I've been following Shaun's Complete Platformer Tutorial playlist, but I wanted to add melee attacks instead of guns and shooting. So I ended up here, trying to incorporate this into my project.
I added the function "script name" with curly braces covering the entire script from my previous tutorial's work's coding for movement, pretty much as Shaun has done in this video.
But since I've added this "ATTACK" script and "FREE" script, I can no longer move (or punch).
We've called scripts in his platformer tutorial before and I did it the same way.
I don't get any errors when running the game, I just can't move or attack with my character, he remains in idle.
@@nathanlawrence656 I´m not sure. Did you move the part of the code where you calculate horizontal and vertical movement to the script with the attack state? Because then you´ll only be able to move while in that state, so you want to keep all that stuff in the normal step event for the player
if anyones getting stuck in the air and only playing the first frame of the attack remember to make your image speed 1, in some tutorials (like shauns platforming one) they have you make your image_speed 0 so when you attack in the air your image_speed stays at 0 so you do no animations nor do you progress to the part where the hitboxes come out in your animation. :)!
Buy yourself a cape, because you a hero
Hey there, just wanted to thank you so much for this tutorial! In fact, your platformer tutorial series was a basis and amazing startup for my GML journey, and so far It's been an experience, from just "Hope this works" to "This will work so good" mindset
Was looking for a framework for melee attacks and saw your's and implemented it to my game and it works perfectly. Hope you are well and looking foward for more videos in general in the future!
I'm getting a "Compile Scripts...Error : duplicate script name found gml_Script_Playerstate_attack_hit" whenever I try to run my game. Did you get this? and how did you fix it
I'm very skeptical because this video is old and it will not work, so I'm just watching for the theory
to anyone getting stuck in the air on the first image when they try to attack: change where it says "image_index = 0;
to image_speed = 1; it worked for me
thanks a lot that really helped me out lol :)
WAS NEEDING THIS TUTORIAL SO BAD! Thanks Shaun!
Thanks Shaun again for building a bridge for us new to GMS to learn the ropes and build our ideas into reality. Thanks also for giving credit where its due, it creates a great example to follow.
I was amazed when the code in this tutorial worked after only 1 bug fix. That's a first for any piece of code from any tutorial. Absolutely amazing tutorial.
WOW.. I was just trying to figure out how to code melee attacks in GM Studio (I'm very new to GML) and I have been watching your tutorials, and now you post this video, thanks so much for great tutorials! Wish you the best!!
strange, he chose an identical deltarune sprite this time
It's not identical! It's incredibly close because I just really liked that sprite (and I'm a bad artist who relies massively on reference). But I did all the swings myself! ...that counts right?
@@SaraSpalding what really counts is having fun at your work
Same here, I am capable of modyfiing sprite to suit my needs but I always need a template. The most original thing I painted was sprite of Peanut with legs that goes up and down. And I did that on accident.
In one of my projects I used sprites from The Escapeists as a template for both Player Character and Zombies, and to call them my own I have added idle animation and improved current walking animation. I probably reuse those sprites as a template since I have lost interest in that project.
In my current project I have used Frisk, repainted it black/red/grey added three hand gestures and +- 10 facial expresions. And here is Magican The Great. SkelyHat, autor of said sprite, looks really fine with people using them as long as he/she gets credited.
@SrTreo I believe the correct term is “wooosh”, not “r/wooosh” There’s no reason to include “r/“. Besides, the guy you replied to doesn’t even deserve to be woooshed.
@SrTreo that wasn't very wholesome 100 from you.
in which video do you configure the scripts of the enemies? :/
That "|" symbol used at 19:32 is ALT+124.
In case you can´t find it in your keyboard.
| you're a legend. also protip for laptop users.
> = alt+62
< = alt+60
can you please make a video showing the enemystate code? i cant figure it out and im having major issues with it
solved it?
I have the same question my friend
@@maul8456 His Gamemaker 1.4 tutorial on melee attacks has the code you're looking for.
At 15:34 you said that there's a method faster and better than collision precise per frame. Could I ask you a tutorial over that method? I really like your videos, thanks you.
damn, ive been using extensively the image_index > image_number-1 thing for over a week now on a project BECOUSE of the manual and now by chance i see what you just said there, and that explains quite a few things now haha thanks for that
If want to be able to control how your player moves while attacking youll have to put all of your movement code into the player attacking state. The best way to do this is to instead make a new script and paste it there. Then you can take out anything you don't need or want to modify and call that script while in the attacking state. so you would have your player move into the Player_State_Attack and the first line would be PlayerMovementWhileAttacking(); or wtv. Took me a while to figure that out.
THANK YOU! I’ve spent a few days trying to figure out how to get attacking to work the way I want it to. Your comment totally helped!
This was such a big help, thank you so much! I copied my Collide and move code into a separate script and then called that script at the beginning of the PlayerState_Attack_Slash script. I also copied this into that new script to make sure that the player is facing the right way: if (hsp != 0) image_xscale = sign(hsp);
@@Grimsikk no problem. I forgot I posted this and have since forgotten everything I learned lool. But it was fun for a while!
so when i jump in the air and attack, my charatcer stays in the attack animation and is stuck in the air and i cant do anything. why?
same here, if you resolve this please post the solution
Ivan Rowlands de Macedo will do
The new attacking state doesn't have any movement code in it so you'l have put in movement calculation in there. You don't need to declare variables or anything. Best thing to do is copy the movement code from your original o_player code and into a script and then call that script at the beginning of the attack state script. Then you can change wtv you want like gravity or walkspeed and it will only be that way while in the attacking state.
@@wtflol6969 can you put the code??
Thanks for all you do. A video showing the set up process and everything start to finish would be helpful. I say this because your tuts matter.
When I added this to my game the attack keeps triggering every frame, playing my attack sound multiple times and killing the enemies instantly.
var end_anim = image_index >= (last frame)
if(!end_anim){
image_speed = 1;
}
else{
image_speed = 0;
image_index = 0;
change state.....
}
That's how I usually do animation end, but the script you posted is great!
You can use image_number-1 instead of writing the last frame manually.
Yeah, the biggest problem with this is that it's no longer accurate for GMS2, since your sprite can be in frames per second or in frames per step. Which is why the script is so much more complicated. That being said, if you know ALL of the sprites that will use the above code are set to frames per step, then yeah, that'll keep working.
By this time tomorrow all comments will be saying the character looks like Kris from Undertale, but you're wrong, the colors are wrong and so is the hairstyle somewhat. This is actually Ahrac from Nutdealer
BabyPinkSnail I have a channel that does speedpaints, animation and coding and animation tutorials, and funny and storytelling animations please consider subscribing
@@Codamations No thanks I dont particularly like people I dont know coming to me and asking me if I wanna sub to them, but I appreciate the offer.
I'm currently stuck on making the enemy take damage. I'm not really sure how to set up an enemy script because you didn't show them too much. I'm trying to figure out how to do it (either with scripts or alternative methods), but I can't find anything online and I don't know how to do any of this. Everything I try with my limited knowledge just does not work.
instead of calling the enemy damage script under "with (hitID)" put instance_destroy(); that should ANIHALATE the instance id of your enemy being effected in your for loop :)
Go back to earlier platforming tutorial video where he deals with creating and damaging/killing enemies.
This tutorial works perfectly! It helped me a TON. Thank you!
Hello! I followed this tutorial and l am having a slight issue...
My character attacks and animates properly, but only while I'm on the ground. If I try to attack while mid-air then it freezes on the first frame of the attack animation and he gets stuck in mid-air. I tried applying the physics code from the free state, but all that does is make him slowly descend while still frozen on the first frame. And then he's still stuck after hitting the ground.
Am I doing something wrong? (Probably)
Did you fix the issue already, if so could you provide me with your fix. I'm having the same problem and all I could figure out is that it is probably caused by the animation_end() script.
@@vanthelow haven't got it figured out yet. I will let you know if I do. Although, I get the same effect even if I remove the animation end script from the equation.
@@CrawlingShadow9 yeah I noticed that too, it is weird because any other code i put in the script works fine, except this one. I'm actively working on the project and that bugfix so ill let you know too if we coms up with something.
@@CrawlingShadow9 Hey, I dont know if you have a solution yet, but changing image_index = 0; to image_speed = 1; worked for me.
Thank you much! I've been at work so much I haven't had time to work on my project. You are a life saver!
Thank you so much Shaun Spalding for all of your tutorials you have been a big help for me so much with because of you I too was able to release my first game SA4A and soon another title thanks to you. Thank you for all that you have done. Have been and will be supporting you all the way.
im getting an error Script: PlayerState_Attack_Slash at line 13 : unknown function or script instance_place_list
this might seem super simple, but i want to know, if i have more than one enemy, how do i reference it? you just put oEnemy in your hits variable, but what if you have multiple types? the parent enemy does work. i would really appreciate an answer
Well it depends on what you mean "more then one enemy".
Asuming you mean multiple enemy _objects_ (oArcher,oKnight,oMage...) creating a parent object oEnemy and making it parent of all enemies, then using oEnemy in colisions should work.
@@gphi6053 It don't have to. It can be an "empty" object whose only purpose is to be a parrent.
For my current version of gamemaker(lates 2023 version) the animation end wont work because spritespeed_framespersecond dosnt exist and neither the code download nor shaun show whats in there.
At 22:30 EnemyHit doesnt work because we cant see the script for the others. i dont understand the argument0 part. its telling me EnemyHit takes no more then 0 arguments but 1 is provided. :(
Most of the comments are saying the fighter is Kris from Deltarune or the sprite is similar to Kris. I do agree with that.
(I’m a huge fan of Deltarune)
PLEASE HELP!!!
I copied the stuff from the step-event over to the script like you did (without the keyboard-checks), but when i try to run the game, it shows me an error that i didn‘t set the variables (right, left)…
Ples help me 😢
Came here to figure out a collision problem I had and learned about scripts instead. Well dang. xD
whats in the other scrips like the enemy free and state hit i dont think what youre showing can function without the codes in those scripts unless im getting something worng
I have this problem that all of my enemies is getting attacked when one is damaged is there another tutorial for the enemy scrips or?
Hmm, hard to say without knowing "the exact code" but there is a chance you are useing reffering as an object which affect *all* instances of said object.
In situacions as this you should use id of instance/s which got hit.
@@Karak-_- Please help i actually cant find the solution its the same code as his and it damages all of them
Thank you very much! Think I got a good understanding of how states work thanks to this.
Hey man i know im a bit late but im doing my first game and your guide is being SO helpfull by now. I was wondering where to find the combo slash tutorial since i cant find in your vids (im blind) Good work and thanks!
To check if you are on the last frame of the animation have you tried this? if image_index >= image_number - sprite_get_speed(sprite_index)/room_speed
What to use instead of instance_place_list? 18:12
Thanks again, Shaun. You are the best!
22:23 are there any other tutorials that i should watc before this one, because he doesnt show where should i pu tthis exactly, or how does this connects to the enemy and many other things
How do you make it so you can hit multiple enemy types?
You make oEnemy a parent object of those objects
AWESOME ! I was waiting for this.
I followed the tutorial and I got that when the character is jumping and I do the slash it stops the character:'/ any solution please?
I haven't tested this, but if you add gravity to the attack scripts, it should work. (The reason your character isn't falling is because horizontal and vertical movement was set to 0 in the attack script)
Except the collision mask is now different so you'll probably collide with the ground wrong if you hit it before the animation stops.
Again though, I haven't tested, but that would be my first guess.
does this still work for top-down games? I am looking to implement a melee combat mechanic to my top-down shooter game for some variation and was wondering if this would still work
2:35 couldnt you just have an actual sword sprite with a cheap rectangular collision mesh matching the width of the sword, then have the mouse attack button simply rotate the sword in an attack motion, kinda like skeletal animation? So you just have a sword object glued to the players x,y that has a simple "on collision with enemy = " blabla?
When you make the horizontal and vertical speed equal to 0 upon entering the slash player state, is that entirely necessary? It seems like it would allow for people to just spam the attack button and hover in midair, and I don’t see any consequences for not implementing it.
Hey Shaun!
Thank you so much for this video it's super informative! I just have one question, Because you are swapping the collision mask from your sprite to your weapon, is it possible that you could run into problems with the wall collision checks? For example walking through walls because your hitbox is not more to the right or something like that? Thanks!!
No. Because it is swapped back after the check is done.
I swear, officer, I didn’t see “Fuck you, Shaun.”
I copyed everything but for some reason after i click the attack key my character keeps on repeating the animation and never stops which disables my other controls. Can someone help plz :)
never mind i fixed it. Just didn't copy 2 extremely important parts thats all XD. Thx for the great tutorials tho.
what were those impotrtant parts,having same problem
TheBulbaMachine If I had to guess, it most likely has do with the animation end event which is supposed to set the character back to their free state
When i press the button the slash animation never ends, even though i'm using the "animation_end" script.
Btw im using the sprite for your new action rpg if that helps
Can someone help me! For some reason, the function instance_place_list is not turning orange even though it is written the exact way it is shown in the video.
I was searching this today,looking at your other melee tutorial
if(hits > 0) seems redundant to me as instance_place_list() would return a value of zero if there are no collisions, meaning the for loop wouldn't do anything in such a case
The hit list is a really good idea than to use “invincibility frames”, as it just merely slows the hit frequency and just acts as a damage cooldown before the enemy becomes vulnerable again.
i followed everything the best i could, when the enemies collided with the hit box, they got hit every frame.
i tried everything but i can't seem to get it to work, can someone help me out here?
When I move the basic step code to the script I am getting a compile error:
Variable .y(1, -2147483648) not set before reading it.
Any suggestions?
do you have function whatever the name of the script is() { every line of code}
im having the same problem
Was able to get the melee attack working while in the air, but now player object descends verrrrry slowly and wont jump, any ideas how to fix?
how did you make the player attack in the air
tell me
great video! but in which video did you write the scripts for the enemy?
2 years later and I'm wondering the same thing right now...
How would one be able to do the attack animation but still continue to move along the path if attacking in the air?
yo how do i keep my character affected by gravity/momentum during the attacks?
Can you put in the collision/gravity check into the script?
Seems like the only thing that doesn't work for this now is the ds_list_add on line 24 of the PlayerState_Attack script. Looks like it just never adds the hitID into the hitbyattack DS.
That took more time than i expected it.
Could you just add a duplicate of the last frame for (image_index > image_number-1) ?
Can someone explain to me what part of the code, makes the enemy just take one instance of dmg? Im trying to use the code mixed with mine, and the only problem im having is that the enemy is taking dmg on every frame of the attack.
soooo i followed everything and checked multiple times but my character if on ground just keeps playing the attack animation on loop, i can't move him nor jump , also if i run the game again and start by jumping then press the attack button he just stops mid air, does the attack animation once then fall and return to FREE state, i tried changing stuff but still didnt work
Listened to the opening and found out I already did this type of thing in the game I'm making, now gonna finish watching to compare the two. :3
ichimo I have a channel that does speedpaints, animation and coding and animation tutorials, and funny and storytelling animations please consider subscribing
@@Codamations No. :D
can someone explain to me what the "hit by attack" list does?
Doesn't this method make the player invulnerable for multiple frames while attacking tho? maybe fine for some games but
No it doesn't. You're not invincible as the code runs sequentially. You swap masks and then you swap back after the check is complete. An enemy will only ever perform its own check before or after this, not during. So it is not in any sense invincible at any point.
Shaun! Can you tell me, you didn't show the codes in the folders: AnemyStage_free,dead,hit! in which video did you write it? Thanks!
hey there im facing problems with gms 2 it's whenever i press the Q button to attack i turn into a wall and i dont know what to do please help me
Everytime I try to run my game I get an error message saying that my player sprite was not set before reading it. The exact message is
Variable .sprite_index(25, -2147483648) not set before reading it. at gml_GlobalScript_PlayerState_Attack_Slash (line 5) -if(sprite_index != spr_player_attack)
Me too!!
@@theburgundysweaterman6623 I figured it out. Should have updated this. If you’re running the newer version of gms2, you need to keep the original brackets you get when you create the scripts. It’s very important. Otherwise the script runs all the time, not when it’s supposed to execute.
@@CarGuyCole360 Can you explain what you mean? Like I have to keep the function name and brackets when you first generate a script?
@@CarGuyCole360 i get this in the step event
it sucks
fixed it but now i get
Variable ._keyRight(100021, -2147483648) not set before reading it.
at gml_Script_scr_player_normal (line 4) - hsp = (_keyRight - _keyLeft) * hspWalk
############################################################################################
gml_Script_scr_player_normal (line 4)
gml_Object_obj_player_Step_0 (line 16) - case Pstate.free: scr_player_normal(); break;
sooo... how hard is it to impolement a state machine in your platformer video if im like 15 episodes in. its just i designed my character for melee and i thought that tutorial would cover it and now im trying to implement state machines and my player keeps getting stuck in mid air and things are just crumbling at my feet when i try to implement it. is it too late?
So wouldn't this make the player invincible while attacking as you've effectively turned off his collision mask during the attack state?
Not exactly, this simply changes the player's hitbox to match that of the attack hitbox. So this means you can still be hit but you will instead take damage when an enemy attack hits your attack, which doesn't make a lot of sense! So to fix this you would instead create a new invisible object when the player attacks, you would then change this object's collision mask instead of changing the player's collision mask. In code, this would be nearly identical to what is shown in the video with the only difference being that whenever you set `mask_index` you would instead be changing the `mask_index` of the new invisible object which could look something like this:
function PlayerState_Attack_Slash() {
hSpeed = 0;
vSpeed = 0;
if (sprite_index != sAttack_Slash) {
sprite_index = sAttack_Slash;
image_index = 0;
ds_list_clear(hitByAttack);
}
var hitbox = instance_create_depth(x,y,depth,oHitBox);
hitbox.mask_index = sAttack_SlashHB;
}
You would then have the rest of your collision and hit detection code as normal or you could place the attack collision code in the oHitBox object. You would also of course need to destroy the oHitBox object once the attack has finished.
@@mikusama8030 Oh okay, weird. Well thanks for explaining that. I suppose if you're doing melee combat with the need to check things at each different attack sprite this is unavoidable. Thankfully in my case I'm making something that's more like a traditional 16 bit game where attacking either kills the enemy or makes them flash for a moment before you can hit them again, so I can just use the technique from Shaun's other "melee combat" video that creates a hitbox object independent of the player
No. This isn't true at all and neither is MikuSama's reply. You're not invincible as the code runs sequentially. You swap masks and then you swap back after the check is complete. An enemy will only ever perform its own check before or after this, not during. So it is not in any sense invincible at any point nor will enemies (or the ground and walls for that matter) use the attack hitbox of the player for any reason outside of this attack check.
If it worked this way you would also presumably fall through the floor. Note that this does not happen in the video.
How do I include various objects? To be more specific how do I make the attack hit not only just one type of object. I thought it would be as simple as adding all the objects into the arguement but it just breaks it. any advice?
make all the objects as children of one parent enemy object, thats probably the simplest way
Can you do a tutorial on delta time next? I've been searching for tutorials on RUclips but never found any good ones. Delta timing is really important for fixing lag, and other game engines like Unity already have delta time built in. Thanks
GMS has delta_time variable built in, it have amount of microseconds that happened between frames. So movment per frame can be counted as movement per seconds *delta_time/1000.
ugh. So much of this went over my head.
How do I change what direction the player is attacking in based on which direction they are facing? I can’t figure that part out. When I walk left and the attack animation faces right, it automatically attacks to the right. I duplicated and flipped the animation, now I just need to know how to program it to pick the right animation based on the direction
did u solve this issue
hey shaun, huge fan of the work you do. i'm just wondering, how would i use the collision checking code for different enemy types? with "var hits = instance_place_list(x,y,obj_enemy,hitbyattacknow,false);", the code seems like itd only work on specifically obj_enemy. I'm currently working on a game that will have about 20 different enemy types plus a few different boss characters, how would i be able to implement this code without repeating it for every unique type?
a solution i was thinking of was to just change "obj_enemy" to "all" and just have some sort of switch case determine if the code should run, but surely there's a more elegant solution? I'd rather have, say, hitting walls or scenery not even be considered by the code if possible
thanks!
make a parent for all the enemies and do the instance_place_list check with the parent
did u manage to do it man? I'm trying to do the same, i have 2 enemies with diff object, idk how to do this, i already tried listing both objects and putting the list in the var hits but the enemy doesnt take damage this way
What manual is he talking about @24:30?
Has anything changed in the 5 years since this was posted?
Do scripts need to be written differently than events?
I keep following along, but I'm interrupted with warnings that my code should be written a different way.
yeah put the script stuff insdie the function
Can you do a Part 2 on how to do this with movement. Like, slashing while moving.
This method will work even while moving. Since you are changing the player's mask to the melee mask it will move with your character.
@@PixelatedPope i think he means keeping momentum during the slash
So I have two different sprites, one for moving and one forstill with a sword, how do I code it so that those sprites only show up when I hit the button
Thanks!
If I have multiple types of enemies, how should I do all the hit count part?
Thanks for the tutorial
Did you ever figure this out? , having the same problem.
3 enemy type - hit box only works for one of them.
What is the difference between using lists and just checking collision and adding events to the enemy object?
so far i always just used the collision box collision event with enemy to do melee damage , is there any benefit using this method over just collision event ?
In reference to my script " EnemyHit(2) " I am getting an error saying "expected 0 got 1" What does this 2 do?
hey Shaun! Quick question - I have a gamepad and all the face buttons, and the axis work fine, however the dPad doesn't work at all. I looked around and saw others had the same issue, but there was no solution. If there isn't a way to get them to work, is there a way to have the analog stick act as a 4-directional input? I'm trying to do an old-school style top down movement, and if the dpad doesn't work, that's the next best thing.
You could use an ”or” statement
Example (xDir = analog_Left; || xDir = Dpad_Left);
Disclaimer, not sure if this actually works or not, and the code for the inputs are different from what they’re called in gamemaker. (Like wtf is dpad_left lmao)
I’ve just noticed this was 9 months ago
Ive got a question, Ive followed the code correctly, but somehow, it does everything except for interacting with the object its supposed to be interacting with. it actually doesnt do anything. no hits, no destroying, not calling up the script, nothing at all. any ideas on how i can solve this??
What if a want a melee attack while running? should I just not use the Playerstate free script?
so if im on GM studio 1 and i dont have the clean up event how would i handle destroying the list?
Awesome tutorial! Looking forward to seeing more videos like these.
By the way, I would really love it if you made a tutorial on a dash mechanic, I really need help on that and there really isn't any new tutorials about this, at least I couldn't find any GMS2 dash tutorials, so that would be pretty cool.
its easy. get the sign from hsp and then if ur pressing a key just increase the hsp
after that, it needs to set hsp to the previous value , but out of the if statement, because if you don't, the hsp will always be equal to the value it returns if you press the key
I doubt anyone will see this before I figure it out myself but:
I'm having trouble with getting it to reduce enemy HP properly. I'm trying to have it be every hit reduces the HP by 1. But I think the game is calculating this as every frame they're getting hit by = -1 hp. so one hit does like 5-6+ hp (or however many frames the hitbox is colliding with an enemy) instead of a flat amount
how can i create a new enemy ? did i really have to create each time 3 new scripts for each enemy ?! like EnemyBlobState_Free / EnemyBlobState_Hit / EnemyBlobState_Dead and if i want to add some movement and attacks to my enemy i have to create EnemyBlobState_Move / EnemyBlobState_Attack ??
Helpful tutorial. The only thing is the player will freeze if attacking in midair. I followed the code closely, but have to restrict the player to only being able to attack while on the ground (which works fine for the game I'm working on, but just saying)
My player just gets stuck in the air if i melle in air i suppose i could just do a check and only allow playerto attack on ground