• 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 with two instances of the same object at once.

W

WimpyLlama

Guest
For collision with walls and such, I use this method.

GML:
//Movement
moveX = (keyD-keyA)*walkSpeed;
moveY = (keyS-keyW)*walkSpeed;

//Collision
//Set sprite bbox variables
var sprite_bbox_top = sprite_get_bbox_top(sprite_index)-sprite_get_yoffset(sprite_index);
var sprite_bbox_bottom = sprite_get_bbox_bottom(sprite_index)-sprite_get_yoffset(sprite_index);
var sprite_bbox_left = sprite_get_bbox_left(sprite_index)-sprite_get_xoffset(sprite_index);
var sprite_bbox_right = sprite_get_bbox_right(sprite_index)-sprite_get_xoffset(sprite_index);

//Move x
x += moveX;

//Horizontal
if (place_meeting(x+sign(moveX),y,oBuilding)) {
    //Get building
    var building = instance_place(x+sign(moveX),y,oBuilding);
  
    //If we can collide with it then do collision
    if (building != noone) {
        if (moveX > 0) x = (building.bbox_left-1)-sprite_bbox_right;
        else if (moveX < 0) x = (building.bbox_right+1)-sprite_bbox_left;
  
        moveX = 0;
    }
}

//Move y
y += moveY;

//Vertical
if (place_meeting(x,y+sign(moveY),oBuilding)) {
    //Get building
    var building = instance_place(x,y+sign(moveY),oBuilding);
  
    //If we can collide with it then do collision
    if (building != noone) {
        if (moveY > 0) y = (building.bbox_top-1)-sprite_bbox_bottom;
        else if (moveY < 0) y = (building.bbox_bottom+1)-sprite_bbox_top;
  
        moveY = 0;
    }
}
I forget who showed me this method, but I've used it ever since. It's much smoother and more reliable than Saun Spaulding's method (which for some reason doesn't even work in my current project. The player often clips into the wall on the y-axis). I showed you my collision code so you can know what type of collision checking I'm doing. Time for the actual problem.

So, I have the object oBuilding. Each of these buildings has different things in them like sprites and stats. Some don't have collision and some do. In order to test if a building the player is colliding with has collision, I created a function call "can_collide(building)". This simply takes the inputted building and looks through things in it to determine if it has collision or not, then returns a boolean. To use this function, I change a little of the collision code.

GML:
if (place_meeting(x+sign(moveX),y,oBuilding)) {
    //Get building
    var building = instance_place(x+sign(moveX),y,oBuilding);
  
    //If we can collide with it then do collision
    if (can_collide(building)) {
        if (moveX > 0) x = (building.bbox_left-1)-sprite_bbox_right;
        else if (moveX < 0) x = (building.bbox_right+1)-sprite_bbox_left;
  
        moveX = 0;
    }
}
In the horizontal and vertical collision checks, I changed "if (building != noone)" to " if (can_collide(building))". This works great! I can collide with buildings that have collision and not collide with ones that don't. But there's a problem. If I have an instance with collision next to one without it, and I go through the one without it, I can easily clip into the one with collision. This is because the collision code has no way to test if the player is colliding with multiple instances, and even if it did know, it wouldn't know what to do about it. I had this same issue in a past project and ended up scraping the whole project BECAUSE of this one issue. I tried to solve it for so long, but I couldn't find a solution. Now I'm having the same issue on my current project, and I'm not turning down this time. I'm gonna figure out how to do this... with your help, lol. I can't seem to figure this out myself, so thanks for any help y'all give me!
 
W

WimpyLlama

Guest
I almost hate how easy that was. Thank you so much.

For anyone who is interested, this is what I did with my code.

GML:
//Movement
moveX = (keyD-keyA)*walkSpeed;
moveY = (keyS-keyW)*walkSpeed;

//Collision
//Set sprite bbox variables
var sprite_bbox_top = sprite_get_bbox_top(sprite_index)-sprite_get_yoffset(sprite_index);
var sprite_bbox_bottom = sprite_get_bbox_bottom(sprite_index)-sprite_get_yoffset(sprite_index);
var sprite_bbox_left = sprite_get_bbox_left(sprite_index)-sprite_get_xoffset(sprite_index);
var sprite_bbox_right = sprite_get_bbox_right(sprite_index)-sprite_get_xoffset(sprite_index);

//Move x
x += moveX;

//Horizontal
if (place_meeting(x+sign(moveX),y,oBuilding)) {
    //Get buildings
    var list = ds_list_create();
    var num = instance_place_list(x+sign(moveX),y,oBuilding,list,false);
    
    //Get if we need to collide
    var blockToCollide = can_collide(list,num);
    
    //If we can collide with it then do collision
    if (blockToCollide != -1) {
        if (moveX > 0) x = (list[| blockToCollide].bbox_left-1)-sprite_bbox_right;
        else if (moveX < 0) x = (list[| blockToCollide].bbox_right+1)-sprite_bbox_left;
    
        moveX = 0;
    }
}

//Move y
y += moveY;

//Vertical
if (place_meeting(x,y+sign(moveY),oBuilding)) {
    //Get buildings
    var list = ds_list_create();
    var num = instance_place_list(x,y+sign(moveY),oBuilding,list,false);
    
    //Get if we need to collide
    var blockToCollide = can_collide(list,num);
    
    //If we can collide with it then do collision
    if (blockToCollide != -1) {
        if (moveY > 0) y = (list[| blockToCollide].bbox_top-1)-sprite_bbox_bottom;
        else if (moveY < 0) y = (list[| blockToCollide].bbox_bottom+1)-sprite_bbox_top;
    
        moveY = 0;
    }
}
can_collide function
GML:
//can_collide(list,num);
//Get arguments
var list = argument0;
var num = argument1;
    
//Loop through the list
for (i = 0; i < num; i++) {
    //Get the ID of the building at the selected slot
    var ID = list[| i].ID;
    
    //Test and see if it has any abilities that have collision
    if (buildings[ID,2] == 0 or buildings[ID,2] == 1) {
        //Return the index of the list
        return i;
    }
}

//Return -1 if there are no buildings with collision in the list
return -1;
 
Top