• Hey! Guest! The 40th (!!!) GMC Jam will take place between February 25th, 12:00 UTC to March 1st 12:00 UTC. Why not join in this very special anniversary jam! Click here to find out more!

GMS 2.3+ Sprite Direction Problem

T2008

Member
My 8 directional enemy's sprite is sometimes off while in wandering state (ie it will walk backwards sometimes while facing forward, etc). I'm sure it's something stupid but I can't figure it out. I have scripts that control the sprite (for idle, walk, attack, etc). The relevant code is below (for walk; the others are the same). I define walk in the create event of the enemy. Any ideas as to why the correct sprite doesn't always show?

Code:
function direction_sprite_walk() {

    switch ((((direction + 22.5) mod 360) + 360) mod 360) div 45 {
        case 0: sprite_index = walk_e; break;
        case 1: sprite_index = walk_ne; break;
        case 2: sprite_index = walk_n; break;
        case 3: sprite_index = walk_nw; break;
        case 4: sprite_index = walk_w; break;
        case 5: sprite_index = walk_sw; break;
        case 6: sprite_index = walk_s; break;
        case 7: sprite_index = walk_se; break;
    }
}
Here's a portion of the wander script (it will run the script direction sprite run if moving etc; I didn't include all for brevity):

Code:
//---Stand Sprite If Enemy Is Alive, Not Moving and Not Hit
        if (hp > 0) && (spd = 0) && (!hit) {
            //Enemy Is Not Touching Object
            if (!place_meeting(x,y,obj_all_solid_parent)) &&
            (!place_meeting(x,y,obj_room_constrainer_parent)) &&
            (!place_meeting(x,y,obj_all_animal_parent)) &&
            (!place_meeting(x,y,obj_npc_parent)) &&
            (!place_meeting(x,y,obj_enemy_ground_parent_not_sp)) &&
            (!place_meeting(x,y,obj_player)) {
                //Direction 
                direction = choose(0,45,90,135,180,225,270,315);
                //Sprite Index
                direction_sprite_stand();
            }
        }
        //---Set Alarm To Change Wander Direction
        alarm[0] = choose(60,90,120,180);
 

ThraxxMedia

Member
switch ((((direction + 22.5) mod 360) + 360) mod 360) div 45 {
Without even looking any further into your code... may I ask where you got this wild piece of formula from? No offense, but it's hurting my head just looking at it. That being said, are you absolutely sure it always returns the desired value? Because not long ago I actually had an error in one of my own scripts, where all of the movement directions were calculated correctly... except for the very last case which sometimes would produce a wrong number, hence setting the wrong sprite index. The reason for this being going over 360 (or below 0) degrees doesn't always seem to wrap around as it should.

Also keep in mind that case-values are precise, meaning that if you type "case 0:" it only ever passes when it's exactly 0 (and not 0.01 or whatever).

An easy way to check this would be to display a debug text that prints out the current value of whatever direction you're walking in.
 
Last edited:

T2008

Member
I got the case statement from an asset at the GM Marketplace and the other code is from tutorial Making Games 101, which has been taken down (I had to modify it some). I have a bite/bullet code added which I didn't post and it seems to work when I delete that part. Here it is below. I don't know why this makes it not work. Any ideas?

Code:
//Enemy Shoots If Enemy Has Attack Sprite and Shoot Cooldown Has Run Down
#region
if (!bullet_created) && (hp > 0) 
&& (shoot_cooldown == 0) {
    //East
    if (sprite_index = attack_e) {
        if (!bullet_created) {
            instance_create_depth(x+12,y-9,0,bullet_object);
            bullet_created = true;
        }
    }
    //North
    if (sprite_index = attack_n) {
        if (!bullet_created) {
            instance_create_depth(x,y-20,0,bullet_object);
            bullet_created = true;
        }
    }
    //South
    if (sprite_index = attack_s) {
        if !(!bullet_created) {
            instance_create_depth(x,y+4,0,bullet_object);
            bullet_created = true;
        }
    }
    //West
    if (sprite_index = attack_w) {
        if (!bullet_created) {
            instance_create_depth(x-12,y-9,0,bullet_object);
            bullet_created = true;
        }
    }
    //Northeast
    if (sprite_index = attack_ne) {
        if (!bullet_created) {
            instance_create_depth(x+9,y-20,0,bullet_object);
            bullet_created = true;
        }
    }
    //Northwest
    if (sprite_index = attack_nw) {
        if (!bullet_created) {
            instance_create_depth(x-9,y-20,0,bullet_object);
            bullet_created = true;
        }
    }
    //Southeast
    if (sprite_index = attack_se) {
        if (!bullet_created) {
            instance_create_depth(x+10,y-5,0,bullet_object);
            bullet_created = true;
        }
    }
    //Southwest
    if (sprite_index = attack_sw) {
        if !(!bullet_created) {
            instance_create_depth(x-10,y-5,0,bullet_object);
            bullet_created = true;
        }
    }
}
         

#endregion
//Stop Shooting Sound and Reset Shoot Cooldown If Have Hit Sprite
#region
if (sprite_index = (hit_e)) 
|| (sprite_index = (hit_ne))
|| (sprite_index = (hit_nw))
|| (sprite_index = (hit_n))
|| (sprite_index = (hit_s)) 
|| (sprite_index = (hit_se)) 
|| (sprite_index = (hit_sw)) 
|| (sprite_index = (hit_w)) {
    //Stop Shooting Sound
    //if (audio_is_playing(snd_elemental_shoot)) {
        //audio_stop_sound(snd_elemental_shoot);    
    //}
    //Reset Shoot Cooldown
    shoot_cooldown = 30;
}
#endregion
//Run Shoot Cooldown  
shoot_cooldown -=1;  
//Reset Shoot Cooldown Clock If It Is Less Than Zero
if (shoot_cooldown < 0) {   
    shoot_cooldown = 30;
    bullet_created = false;
}
 

ThraxxMedia

Member
I'm sorry, I can't quite follow. What part did you delete to make it work?

Edit: ohh! I might have spotted an issue! In the bottom section of the code you just posted, within the 'if' statement with all the 'or' operators, you have single equals. I don't exactly know how lenient GameMaker is with that, but in other programming languages, a single equal sign SETS a variable to a given value. If you want to COMPARE, you need to type '==' (i.e. double equals). Please see if that changes anything.
 

T2008

Member
I assume you are referring to the hit sprites ?? The enemy actually was never hit so it would never get to that part. I think game maker is very lenient also.

Oddly enough the code seems to be working now for no apparent reason. Would it be better for me to say if sprite_index == hit_e, etc? I have no programming experience, but I got some of this from tutorials that did it this way so I just copied them.

And thank you so much for responding!!
 

ThraxxMedia

Member
Yes, I am talking about the part with the hit sprites. But from what you've posted, it's not clear where this piece of code is sitting; if it's within a step event for example, and no other checks are performed beforehand (that would cause the event to skip that part) it's always going to run regardless. I'm not seeing any kind of condition there. Anyways... yes, it's always good practice to use proper syntax. As I said, 99.9% of other programming languages will probably have issues with single '=' as a comparison operator, so please get used to using '==' for that purpose whenever possible, even if it's not necessary in GameMaker.

I'm glad it's somehow working now (?) although it'd be strange if that just happened randomly for no apparent reason.
 
Last edited:

T2008

Member
Yes, it's in step event. I meant that I didn't hit the enemy so the enemy would not have the hit sprite. Thanks again for your advice! Hopefully, there won't be anymore issues.
 

T2008

Member
Quick question, would I use double == for the code in first post as well, eg:
instead of: if (sprite_index = attack_nw)
I should say: if (sprite_index == attack_nw)
 

ThraxxMedia

Member
No. It works as follows:

GML:
if (some_variable == 1) // COMPARING 'some_variable' to a given value
some_variable = 1; // SETTING 'some_variable' to the given value
So, whenever you want your variable to change, you use '=' and whenever you wanna compare it to something else, you make it double.

Edit: I am confused now. In your first post, there weren't any "IF" statements of that sort. What are you talking about? xD Anyways, I hope you get the idea.
 
Top