• 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!

Legacy GM bouncing object sorta working? HELP

H

Heropants

Guest
I'm creating what's essentially a top-down shooter and I'd like it if some objects bounced of others correctly. I found this code I placed in the step event mostly works, except that it has you input 0 if the object is hitting a vertical surface and 90 if it's hitting a horizontal surface.

Code:
///bounce off full walls
if speed > 0.1 { //it's still moving
    if place_meeting(x + lengthdir_x(speed, direction), y + lengthdir_y(speed, direction), obj_parent_full) { //comes in contact with a full wall
        var v = direction; //angle they are traveling
        var n = 0 for vertical walls, 90 for horizontal; //! I HAVE NO IDEA HOW TO TELL IT IF N should be 0 or 90

        //final calculation
        direction = 2 * n - v - 180;
        }
    }
This code works except that I have no idea how to to detect if it's hitting a vertical surface (where n should be = 0) or a horizontal surface (where n should be = 90). Does anyone have any ideas how I might detect that?

Thank you so much in advance for any help.
 
S

Spencer S

Guest
I'm not really sure how you'd do this either. Maybe you could assign each wall object an "n" value in the Instance Creation Code (not the Create Event, I mean the Creation Code in the room itself, for each wall object).

Then, you simply read the "n" value of whatever wall object you collide with, where each wall object has an "n" value set based on whether they're created vertically or horizontally in the room.
Code:
with (other) {
obj_player.n = n;
}
You might also want to consider using instance_place instead, since instance_place returns the ID of the object found to be colliding with, so you can manipulate the variables more easily with instance_place.

Your code would look something like this.
Code:
///bounce off full walls
if speed > 0.1 { //it's still moving
    var instID = noone; // create the variable being read
    instID = instance_place(x + lengthdir_x(speed, direction), y + lengthdir_y(speed, direction), obj_parent_full); // assign the variable the id of the object being found to collide with next step
    if instID != noone {
        var v = direction; //angle they are traveling
        with (instID) { // Access the ID stored of the colliding object
            var n = n; // Assign var "n" the value that the object found colliding with has assigned for "n"
        }
        instID = noone; // make sure to reset instID, so your code still works afterwords

        //final calculation
        direction = 2 * n - v - 180;
        }
    }
 
Last edited by a moderator:
P

Pyxus

Guest
I'm creating what's essentially a top-down shooter and I'd like it if some objects bounced of others correctly. I found this code I placed in the step event mostly works, except that it has you input 0 if the object is hitting a vertical surface and 90 if it's hitting a horizontal surface.

Code:
///bounce off full walls
if speed > 0.1 { //it's still moving
    if place_meeting(x + lengthdir_x(speed, direction), y + lengthdir_y(speed, direction), obj_parent_full) { //comes in contact with a full wall
        var v = direction; //angle they are traveling
        var n = 0 for vertical walls, 90 for horizontal; //! I HAVE NO IDEA HOW TO TELL IT IF N should be 0 or 90

        //final calculation
        direction = 2 * n - v - 180;
        }
    }
This code works except that I have no idea how to to detect if it's hitting a vertical surface (where n should be = 0) or a horizontal surface (where n should be = 90). Does anyone have any ideas how I might detect that?

Thank you so much in advance for any help.
what @Spencer S said should work assuming you have straight walls and floors, but if you have angled or irregular surfaces you could use this script to find the surface normal aka n value.
 
H

Heropants

Guest
I'm not really sure how you'd do this either. Maybe you could assign each wall object an "n" value in the Instance Creation Code (not the Create Event, I mean the Creation Code in the room itself, for each wall object).

Then, you simply read the "n" value of whatever wall object you collide with, where each wall object has an "n" value set based on whether they're created vertically or horizontally in the room.
Code:
with (other) {
obj_player.n = n;
}
You might also want to consider using instance_place instead, since instance_place returns the ID of the object found to be colliding with, so you can manipulate the variables more easily with instance_place.

Your code would look something like this.
Code:
///bounce off full walls
if speed > 0.1 { //it's still moving
    var instID = noone; // create the variable being read
    instID = instance_place(x + lengthdir_x(speed, direction), y + lengthdir_y(speed, direction), obj_parent_full); // assign the variable the id of the object being found to collide with next step
    if instID != noone {
        var v = direction; //angle they are traveling
        with (instID) { // Access the ID stored of the colliding object
            var n = n; // Assign var "n" the value that the object found colliding with has assigned for "n"
        }
        instID = noone; // make sure to reset instID, so your code still works afterwords

        //final calculation
        direction = 2 * n - v - 180;
        }
    }
Thanks, the issue is that the walls are 32 x 32 pixel squares. So depending on the object's approach (from the side or the bottom/top), it can't know if it's a vertical surface or a horizontal one. I could just have the code check if there's a wall to it's side, then it sets n = 0 and if there's a wall above or below, it sets it n to 90. However, this get's more complicated when it approaches a corner since it'll detect a wall to the side and above/below. Therefore, it'll set n to whichever value I have it check for last meaning that it might pass through one of the walls in a corner.
 
P

Pyxus

Guest
Thanks, the issue is that the walls are 32 x 32 pixel squares. So depending on the object's approach (from the side or the bottom/top), it can't know if it's a vertical surface or a horizontal one. I could just have the code check if there's a wall to it's side, then it sets n = 0 and if there's a wall above or below, it sets it n to 90. However, this get's more complicated when it approaches a corner since it'll detect a wall to the side and above/below. Therefore, it'll set n to whichever value I have it check for last meaning that it might pass through one of the walls in a corner.
You put "bouncing" in the title but are you looking for something more like a ricochet, something like this?
 
H

Heropants

Guest
Yeah, sorry I was thinking more like how a ball would bounce off a wall. Richochet was exactly was I was looking for but based on your feedback, I think I figured out sorta a round about way to do it (it's probably does more checks than necessary but it works). Basically I just have it check if there's a wall above/below or a wall to the side and then it set's n to be whatever it detects. The problem with this is corners, where it's basically hitting a vertical and a horizontal surface. To counter this, I have the code keep track if it hits a horizontal surface and a vertical one or just both. If it realizes it's detect both, then I know it's found a corner and in that case, the direction just does a complete 180.

Code:
///bounce off full walls
if speed > 0.1 { //it's still moving
    if place_meeting(x + lengthdir_x(speed, direction), y + lengthdir_y(speed, direction), obj_parent_full) { //comes in contact with a full wall
        var v = direction; //angle they are traveling
        var checkhit = 0; //how many surfaces it detects
        if place_meeting(x + lengthdir_x(speed, direction), y, obj_parent_full) { //is there a surface right/left?
            n = 0;
            checkhit += 1; //mark that it has detected 1 surface
            }
        if place_meeting(x, y + lengthdir_y(speed, direction), obj_parent_full) { //is there a surface above/below
            n = 90;
            checkhit += 1; //mark that it has detected 1 surface
            }
        //final calculation
        if checkhit < 2 { //if it's only detected 1 surface, then do the normal rickochet code
            direction = 2 * n - v - 180; //normal richochet code
            }
            else //if it has detected something to the top/bottom and the side then it is in a corner
            {
            direction = (direction + 180) mod 360; //just go in a total 180 direction
            }
        }
    }
 
P

Pyxus

Guest
Yeah, sorry I was thinking more like how a ball would bounce off a wall. Richochet was exactly was I was looking for but based on your feedback, I think I figured out sorta a round about way to do it (it's probably does more checks than necessary but it works). Basically I just have it check if there's a wall above/below or a wall to the side and then it set's n to be whatever it detects. The problem with this is corners, where it's basically hitting a vertical and a horizontal surface. To counter this, I have the code keep track if it hits a horizontal surface and a vertical one or just both. If it realizes it's detect both, then I know it's found a corner and in that case, the direction just does a complete 180.

Code:
///bounce off full walls
if speed > 0.1 { //it's still moving
    if place_meeting(x + lengthdir_x(speed, direction), y + lengthdir_y(speed, direction), obj_parent_full) { //comes in contact with a full wall
        var v = direction; //angle they are traveling
        var checkhit = 0; //how many surfaces it detects
        if place_meeting(x + lengthdir_x(speed, direction), y, obj_parent_full) { //is there a surface right/left?
            n = 0;
            checkhit += 1; //mark that it has detected 1 surface
            }
        if place_meeting(x, y + lengthdir_y(speed, direction), obj_parent_full) { //is there a surface above/below
            n = 90;
            checkhit += 1; //mark that it has detected 1 surface
            }
        //final calculation
        if checkhit < 2 { //if it's only detected 1 surface, then do the normal rickochet code
            direction = 2 * n - v - 180; //normal richochet code
            }
            else //if it has detected something to the top/bottom and the side then it is in a corner
            {
            direction = (direction + 180) mod 360; //just go in a total 180 direction
            }
        }
    }
Glad you found a solution that works for you, but if you're interested check out this post. I actually recently helped out someone who was also trying to do a ricochet.
 
H

Heropants

Guest
Glad you found a solution that works for you, but if you're interested check out this post. I actually recently helped out someone who was also trying to do a ricochet.
Oh nice, looks like your script would work even with angles other than straight vertical or horizontal. I definitely might use that instead. Thanks!
 
Top