1. Hey! Guest! The 35th GMC Jam will take place between November 28th, 12:00 UTC - December 2nd, 12:00 UTC. Why not join in! Click here to find out more!
    Dismiss Notice

GM:S 1.4 How do I check what to collide with first? (collision_line)

Discussion in 'Programming' started by Dr_Nomz, Oct 4, 2019.

  1. Dr_Nomz

    Dr_Nomz Member

    Joined:
    Oct 31, 2016
    Posts:
    594
    I have a few moments where an object is supposed to collide with something based on it's positions from where it is now to where it will be in the next step, and then run the correct code. The first moment the bullet is created it can't collide with anything at first, so the first moment it's created it acts a little differently, relying on previousx/y and current x/y, that's why there are 4 collisions here. (2 each for Walls/Enemies)


    Thing is I can't seem to make it work, because sometimes bullets will hit through walls and if you're too close to a wall, the bullet will be destroyed before it hits the enemy. How do I make it so the bullet collides with what it's supposed to collide with? (Whichever object is closer, it'll react to that one instead of the other.)
    Code:
    //Variables for predicting collision in the bullet's next position.
    var x2 = x + lengthdir_x(speed, direction);
    var y2 = y + lengthdir_y(speed, direction);
    
    //Wall Collision.
    if collision_line(xprevious,yprevious,x,y,obj_Wall,false,false) && wall_collision = 0{
      //For colliding at the start of the bullet's creation.
      instance_destroy();
    }
    if collision_line(x,y,x2,y2,obj_Wall,false,false) && wall_collision < 1{
      //For predicting it's next point and colliding before it draws it's position there.
      instance_destroy();
    }
    
    
    //Enemy collision.
    if collision_line(xprevious,yprevious,x,y,par_Enemy,false,false) && wall_collision = 0{
      with(collision_line(xprevious,yprevious,x,y,par_Enemy,false,false)){
        scr_Enemy_Damage(argument0);
      }
      instance_destroy();
    }
    if collision_line(x,y,x2,y2,par_Enemy,false,false) && wall_collision < 1{
      with(collision_line(x,y,x2,y2,par_Enemy,false,false)){
        scr_Enemy_Damage(argument0);
      }
      instance_destroy();
    }
     
  2. Lady Glitch

    Lady Glitch Member

    Joined:
    Feb 10, 2019
    Posts:
    25
    Dr_Nomz likes this.
  3. Dr_Nomz

    Dr_Nomz Member

    Joined:
    Oct 31, 2016
    Posts:
    594
    Wow an entire site dedicated to GML scripts? Thanks! Yeah I forgot to put the GMS 1 tag on this lol, thanks for that, I'll take a look at it later.
     
    Lady Glitch likes this.
  4. Dr_Nomz

    Dr_Nomz Member

    Joined:
    Oct 31, 2016
    Posts:
    594
    Finally got to it, couldn't get it working.

    Code:
    //Close Collision:
    if wall_collision == 0{
    
    var collide_wall_close = collision_line(xprevious,yprevious,x,y,obj_Wall,false,false);
    var collide_enemy_close = collision_line(xprevious,yprevious,x,y,par_Enemy,false,false);
    
    //Wall
    if instance_exists(obj_Wall){
    if scr_Collision_Line_First(xprevious,yprevious,x,y,obj_Wall,false,false){
    if collide_wall_close{
      instance_destroy();
      exit;
    }}}
    
    //Enemy
    if instance_exists(par_Enemy){
    if scr_Collision_Line_First(xprevious,yprevious,x,y,par_Enemy,false,false){
    if collide_enemy_close{
      with(collide_enemy_close){
        scr_Enemy_Damage(argument0);
      }
      instance_destroy();
      exit;
    }}}
    
    }
    So, what am I doing wrong and how do I get it working?

    This is a LOT better than what I had (I think) but it's basically the same as the old one. It collides with walls like it's supposed to, destroying the bullet when fired at a wall at point blank, but if there's an enemy it'll destroy the bullet without damaging the enemy.
     
    Last edited: Nov 10, 2019
  5. Catastrophe

    Catastrophe Member

    Joined:
    Sep 22, 2019
    Posts:
    119
    Basically, there are three cases here:

    collide with wall
    collide with enemy
    collide with wall and enemy.

    And you only have if statements regarding the firsst two cases. for the third (and it should go above the others):

    First, store the results of collision_line_first for each into a variable, this will give you the instance_id to get position values from. Then, check which one is closer, by doing a point_distance against each of those. If the wall is closest, destroy yourself, otherwise do damage.

    Alternatively, you can parent the wall and enemy and do a collision_line_first on that parent (like "o_physical_object") and then check the object_index of the collided object and act appropriately. If you do it this way, you should get rid of your other two checks. But that is a terrible waste of parenting unless they both had no parent to begin with and you think that is a good parenting structure, which it might be *shrug*
     
    Last edited: Nov 10, 2019
  6. Dr_Nomz

    Dr_Nomz Member

    Joined:
    Oct 31, 2016
    Posts:
    594
    I'm sorry I can't figure out how to do the point distance check for this. Can you show me how it's supposed to be done?
     
  7. Catastrophe

    Catastrophe Member

    Joined:
    Sep 22, 2019
    Posts:
    119
    sure

    enemy = scr_Collision_Line_First(xprevious,yprevious,x,y,par_Enemy,false,false)
    wall = scr_Collision_Line_First(xprevious,yprevious,x,y,obj_Wall,false,false)


    if (enemy && wall) {

    distToEnemy = point_distance(x,y,enemy.x,enemy.y)
    distToWall = point_distance(x,y,wall.x,wall.y)

    // do code based on whichever was closer
    } else if (wall) {
    // do wall code
    } else if (enemy) {
    do enemy code
    }

    distance_to_object might actually be more accurate since it accounts for bounding boxes

    Edit; fixed typo where the functions was checking enemies both times
     
    Last edited: Nov 12, 2019

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice