• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Collision event not changing state.

Within my step event of obj_Enemy_1 I have three states. Currently, in the "Attacking" state I have the following:

Code:
    case "Attacking":
    var attack_angle = point_direction(x, y, obj_Player1.x, obj_Player1.y);

            var shot = instance_create_layer(x, y, layer, obj_Enemy_laser);
            shot.direction = attack_angle;
            shot.speed = 8;
               
       if instance_exists(shot){
           if place_meeting(shot.x, shot.y, obj_Player1){
               Enemy_1_State = "Aggressive";
           }
       }

   break;

    case "Aggressive":
       y+=10;
   break;
I want the enemy state to change when it's weapon hits obj_Player1.
For now I've been testing enemy behavior change and just want whatever enemy that fired and hit player1 to move down the screen at y+=10, so I know its state changed.

However, nothing is happening. Not sure what else to try and I welcome any guidance.
 

Simon Gust

Member
The problem is that you are creating an enemy laser every frame and you end up tracking every attack the enemy fires also for the only frame before getting overwritten by another one. Technically this should work if you only 1 instance of obj_Enemy_laser was created. In addition to that, the shot variable is local and won't be remembered after the frame has ended.

The approach isn't very save, if the shot misses, the enemy wouldn't be able to create another shot and be stuck in the attacking state but not actually doing anything.
CREATE
Code:
shot = noone;
STEP
Code:
case "Attacking":
    var attack_angle = point_direction(x, y, obj_Player1.x, obj_Player1.y);
    if (shot != noone) {
        with (shot) {
            if (place_meeting(x, y, obj_Player1)) {
                other.Enemy_1_State = "Aggressive";
                other.shot = noone;
                instance_destroy();
            }
        }
    }
    else
    {
        shot = instance_create_layer(x, y, layer, obj_Enemy_laser);
        shot.direction = attack_angle;
        shot.speed = 8;
    }
break;

case "Aggressive":
    y += 10;
break;
 
I've been trying to tweak it, but no luck. My understanding is as follows:

Code:
case "Attacking":
   var attack_angle = point_direction(x, y, obj_Player1.x, obj_Player1.y);
   if (shot != noone) { // in the create event "shot = noone", so this part of the code will not run until AFTER the else code.
       with (shot) { //with specific instance of obj_Enemy_laser
           if (place_meeting(x, y, obj_Player1)) { //if shot instance collides with player
               other.Enemy_1_State = "Aggressive";
               other.shot = noone;
               instance_destroy();
           }
       }
   }
   else // "shot = noone", so this part executes and on the next pass "shot != noone", so the first part will execute.
   {
       shot = instance_create_layer(x, y, layer, obj_Enemy_laser); // laser shoots from enemy
       shot.direction = attack_angle; // point_direction is at player
       shot.speed = 8;
   }
break;
I think because under the else code "var" is not used before "shot" (as in var shot = ...) so it is not unique and constantly becomes the NEXT obj_Enemy_laser. I tried adding var, but it threw an error. Please let me know if var is not needed and why.

Any ideas on what to try next?
 
I removed it, but then it threw an error. I tried a few things to resolve it, but none worked. I think the code is really close to working, but something is a little off. I added enum in the enemy create code. This is what I have now:

Code:
case Enemy_1_State.Attacking:

   var attack_angle = point_direction(x, y, obj_Player1.x, obj_Player1.y+25); //so it aims for the center of Player1.

    if shot != noone{
         with (shot) {
            if (place_meeting(x, y+25, obj_Player1)) {
                Enemy_1_State = Enemy_1_State.Aggressive;
                shot = noone;
                instance_destroy();
               show_message("Hit");
           }
       }
    }
    else
    {
    shot = instance_create_layer(x, y, layer, obj_Enemy_1_Sonic_Wave_1);
    shot.direction = attack_angle;
    shot.speed = 8;
    }
  
break;
The message "Hit" does display when Player1 is hit. However, the state won't change.
 
Last edited:

TheouAegis

Member
Code:
   if shot != noone{
        with (shot) {
           if (place_meeting(x, y+25, obj_Player1)) {
               Enemy_1_State = Enemy_1_State.Aggressive;
               shot = noone;
               instance_destroy();
              show_message("Hit");
          }
      }
   }
Oh, yeah because you're using with(). All your variable references are now pointing to the projectile, not to the enemy.

And yeah, I see now that i'm not at work that you wanted the "if shot!=noone" condition cuz of the second half. Personally, I'd have included that second half in the code that changes the state to Attacking, not inside the Attacking state itself. But I won't go into that here.

Code:
case Enemy_1_State.Attacking:

   var attack_angle = point_direction(x, y, obj_Player1.x, obj_Player1.y+25); //so it aims for the center of Player1.

   if shot != noone{
        with (shot) {
           if (place_meeting(x, y+25, obj_Player1)) {
               other.Enemy_1_State = Enemy_1_State.Aggressive;
               other.shot = noone;
               instance_destroy();
              show_message("Hit");
          }
      }
   }
   else
   {
   shot = instance_create_layer(x, y, layer, obj_Enemy_1_Sonic_Wave_1);
   shot.direction = attack_angle;
   shot.speed = 8;
   }
 
break;
 
I made the aggressive state simple just so I know it's working. That was tricky and you made it simple! It's working!

Now I'm going to work on my aggressive state and change it up a bit.

Thank you!

UPDATE: The enemies whose shots hit the player successfully change states. However, the other enemies that miss the player do not continue to shoot.
 
Last edited:

Joe Ellis

Member
Well if they miss, the shot isnt getting reset back to noone so it won't fire a new bullet, you need to do this in the bullet's destroy event or the moment it goes off the screen.
Maybe doing:
shot.parent = id

then in the shot's destroy event:

parent.shot = noone
 
Bam! Solved.

I added "shot.parent = id" in the else code as follows below:

Code:
           else
           {
           shot = instance_create_layer(x, y, layer, obj_Enemy_1_Sonic_Wave_1);
           shot.direction = attack_angle;
           shot.speed = 10;
           shot.parent = id
           }
Then as you said: "in the shot's destroy event: parent.shot = noone".

Thanks Joe!
 
Top