Animation Not Fully Showing

K

Kid Mescudi

Guest
Hello all!

First off, I'm fresh to GML (after doing nothing but D&D) so excuse my lack of understanding of particular terminology.

Basically, my problem is that I have a top-down game where the character swings his sword. Once the animation stops, it returns back to a default still sprite. Right now, I can get it to work if the player is not moving. But if I'm moving AND want to attack, the sprite just shows as the second sub-image (it's only a 4-frame animation for the sword swing).

Here is what I have in the STEP script:

///Attacks
if keyboard_check_pressed(vk_space){
sprite_index = spr_player_attack_right;
image_speed = 0.5;
image_index = 0;
}

And here is what I have in my character's ANIMATION END script:

///Sprite Changes

//Attack with sword
if sprite_index = spr_player_attack_right {
image_speed = .5;
image_index = 0;
sprite_index = spr_player_right;
}

--------------------------------------------

Now I based these scripts off a topic I searched from this year, and it works up until if I wanted to, say, move my character to the right AND press the SPACE bar at the same time to perform a fully animated swing.

Does anyone know where I'm going wrong? Any help is appreciated! :)
 
D

Dramier

Guest
My first guess is that the movement keys are overriding the attack keys animations. In other words, when you press both, the direction key takes precedent over the attack key. You can't actually play both animations at the same time with that setup if I understand what you're doing correctly.
 

Roderick

Member
Does your movement code have anything which would be altering the animation, like putting you into a walk animation? If so, it will override the attack animation as soon as it runs, unless you add code which prevents it from happening while the attack animation is running.
 
K

Kid Mescudi

Guest
My first guess is that the movement keys are overriding the attack keys animations. In other words, when you press both, the direction key takes precedent over the attack key. You can't actually play both animations at the same time with that setup if I understand what you're doing correctly.
Yeah, I just changed my movement key from "keyboard_check(vk_right)" for example, to "keyboard_check_pressed(vk_right)" and now the animation plays while moving. So that somehow fixed it up! But it created yet another problem as a result in what I'm about to say next.

Does your movement code have anything which would be altering the animation, like putting you into a walk animation? If so, it will override the attack animation as soon as it runs, unless you add code which prevents it from happening while the attack animation is running.
Yes, it does. As stated to the other gentlefolk's comment, I've changed my movement key to _pressed and it does the following script setup:

if keyboard_check_pressed(vk_left){
sprite_index = spr_player_left_walk;
}
if keyboard_check_released(vk_left)
{
sprite_index = spr_player_left;
};

So I have the sprite change into a walking animation, which originally prevented the sword animation from fully continuing until I made my little fix. I'm wondering if it would just make more send to actually halt my character when they attack [as in any traditional top down game]? Because to be quite honest, this tiny edit made my movement sprite changes worse than before.
 

Roderick

Member
When you attack, set a variable.

Code:
attacking = true;
In your Animation End event, set it to false. It doesn't need to be checked; when any animation ends, you aren't attacking any more, even if you weren't in the first place.

Code:
attacking = false;
In your movement code, when you tell it to change the animation, just check the variable first.

Code:
if (attacking == false) {sprite_index = spr_player_left;}
Don't use keyboard_check_pressed for movement, because that will only return true on the step that the key was pressed, so you'd have to mash the key repeatedly to move. Stick with what you had before, just with my changes.

And look up "Finite State Machines". There are a few good tutorials on then, and they might help you a lot with this sort of thing.
 
K

Kid Mescudi

Guest
Okay, so I replicated it with variables but it seems to have went back to the same error as before (removing the _pressed function of course). So here's what I have for my code:

STEP Event > "Movement" Script

Code:
///Movement
var left =  keyboard_check(vk_left);
var right =  keyboard_check(vk_right);
var up =  keyboard_check(vk_up);
var down =  keyboard_check(vk_down);

//Check if attacking
var attacking = false;

//Sprite Change on Movement
//Left
if keyboard_check(vk_left){
    if (attacking == false) {
        sprite_index = spr_player_left_walk;
    }
}
if keyboard_check_released(vk_left) {
    if (attacking == false) {
        sprite_index = spr_player_left;
    }
}
STEP Event > "Attack" Script
Code:
///Attacks
var attacking = true;

if keyboard_check_pressed(vk_space){
    if sprite_index == spr_player_right_walk {
    moveSpeed = 0;
    sprite_index = spr_player_attack_right;
    image_speed = 0.5;
    image_index = 0;
    }
ANIMATION END Event
Code:
///Sprite Changes

attacking = false;

//Attack with sword
if sprite_index == spr_player_attack_right {
   sprite_index = spr_player_right;
   image_speed = .5;
   image_index = 0;
   moveSpeed = 2;
}
I just snippeted out the excess code used for the other arrows keys, but this is the general format I have. Maybe I'm just stupid and don't know how to set up variables correctly..? Haha
 

Roderick

Member
Code:
var attacking = true;
This sets attacking as a local variable, meaning that the variable is released from memory as soon as the event or script that called it ends, which means it will only be true for that one step.

Use the code I posted, without the var declaration.

And don't set attacking = false in the movement code. That overrides the value set when you attacked, and lets the movement animation run again.
 
K

Kid Mescudi

Guest
But wouldn't the variable for attacking needed to be defined? Because if I declare everything as just attacking = true; or attacking = false;, then what exactly IS going on in the attacking command? I'm just asking for clarification, because I would think that we need to attach the variable to some kind of event like a key press or something. Like this example:

Code:
var down =  keyboard_check(vk_down);
I've cleared the word "var" in my code so it looks exactly the same, but now just having attacking instead of "var attacking". So far, so good! Now there's a slight glitch where if my character is performing the action and I press another key during the animation, the player is locked in place and cannot move unless I use the "attack" command again. Does this have to do with the new attacking variable statement showing in your code for MOVEMENT?

Edit: Nvm, got it working now! Still getting a weird little glup in movement, but that has to do with something else. Thank you for your help! :)
 
Last edited by a moderator:

Roderick

Member
But wouldn't the variable for attacking needed to be defined? Because if I declare everything as just attacking = true; or attacking = false;, then what exactly IS going on in the attacking command? I'm just asking for clarification, because I would think that we need to attach the variable to some kind of event like a key press or something.
There are three types of variables:

Global: These are defined or referenced by adding "global." before the variable name. Global variables are stored for the life of the game, and are only released when the game is closed.
Code:
// Example
global.points += 100;
if (global.points >= global.nextlife) {player.lives++; global.nextlife += 50000;} // There's an instanced variable here too. See the next section.
Instanced: Instanced variables belong to a specific instance. They exist until the instance that owns them is destroyed, and then are destroyed as well. Instanced variables can be called by name from the owning instance, or by adding the instance id of their owner.

Local: Local variables are instanced variables, but they only exist until the end of the script or event that created them. They are called the same way as a regular instanced variable, but with "var" added when they are first defined.
Code:
// Example of Local and Instanced
var bullet = instance_create(x, y, obj_bullet); // This creates a bullet and stores its id in a local variable. That variable will be forgotten when this step ends
bullet.damage = 5; // This gives the instance created above a variable called damage, and sets it to 5. That object will temember the variable intil the object itself is destroyed.
Regarding your second issue: I don't see a problem with your code. It might be somewhere else.
 
Top