Legacy GM 2.5d collisions and slowdown

V

viniciuscsg

Guest
Hello everyone,

The xyz collision code I am using in 2.5d seem to work well despite being still a cuboid collision (rectangular in all dimensions, disregards masks). I have adapted the reasoning from a number of true 3d collision examples, and it worked well in zeldaesque topdown with depth = -y and its variations, so characters can now jump, go under or over flying blocks and moving platforms, climb walls etc. Now, optimization issues:

At first I had the fps drop far below 60 (30-40ish) with as few as 5 or so instances of gravity and collision enabled "active" objects. After transposing all collision and gravity code out of the actual objects onto a single controller_obj (a trick I got from studying bullet hell games), I got it to hold 58-59ish fps with a maximum of 9-11 of those live instances on the room (which will do as baddies and whatnot). Still, I am not comfortable with that, slightly larger rooms would likely need to be populated with more of those active instances, and with more than 12 it goes down to 20-30 fps quite fast.

I need to now if this code is really so intensive as to cause that level of slowdown. The collision code rests on this cube_meeting function which is like collision rectangle in 3d, returning true or false:

Code:
 ///cube_meeting(x, y, z, obj)
    xx  = argument0; yy  = argument1; zz  = argument2; obj = argument3;
  
    with (obj)
    {
    var ww = other.mask_width; var hh = other.mask_height; var zh  = other.zheight;

    if (other.xx > x - ww && other.xx < x + ww &&        //check horizontal overlap
        other.yy > y - hh && other.yy < y + hh &&        //check vertical overlap
        other.zz > z - zh && other.zz < z + zheight) &&  //check z overlap
       (other.id != id)                                  //check for "notme"
            {
            return true;
            }
    }
    return false
Then the cube_meeting function is used to check for pixel perfect collisions in all 3 dimensions (considering the speed, and using the "while" method):

Code:
 ///cube_collision(obj)  
    obj  = argument0;
  
    if (!cube_meeting (x + hspd, y, z, obj)) { x += hspd; } //can move
    else { while (!cube_meeting(x + hspd, y, z, obj)) { x += sign(hspd); } hspd=0 }
  
    if (!cube_meeting (x, y + vspd, z, obj)) { y += vspd; } //can move
    else { while (!cube_meeting (x, y + vspd, z, obj)) { y += sign(vspd); } vspd =0 }

    if (!cube_meeting (x, y, z + zspd, obj)) { z +=zspd } //can move
    else { while (!cube_meeting(x, y, z + zspd , obj)) { z += sign(zspd); } zspd =0 }
As I said, I managed to halve the fps hit by running all the code from a single controller obj, in its step event:

Code:
 /// Handles collisions of all active objects and update their depths (depth=-y+z)
    with parent_active {
    cube_collision(parent_all)
    scr_get_depth() }
The number of passive instances (used as target to check collisions with) seems to be non issue since their objects carry no code at all, even when I am using from 100 to 200 of them as blocks to make up platforms and walls. I know I should probably learn to use tiles or surfaces to make up the level instead of so many object instances, but they carry the z and "z_height" information for multiple levels rooms, and I am planing for some of them to be destructible, have multiple z heights to work as ramps etc. I don't think tiles can do that.

Thank you very much in advance for any help or input you could give me on this.
 

TheouAegis

Member
var ww = other.mask_width; var hh = other.mask_height; var zh = other.zheight;
Why is this inside the with()? Either you don't need other or you need to move it outside the loop.

Make xx, yy, zz and obj temp variables. Right now they are permanent. All those other calls are slowing it down.
 
V

viniciuscsg

Guest
Oh, ok, I'll try to make them temporary, thank you. Regarding other, perhaps that wasn't the best construction indeed. Would the other calls weight it down more the larger is the number of instances in the rooms which meet the criteria for the collision checks? Even if the majority of those passive instances are not actively colliding?. There is a peculiarity to my project, which is the fact that all collisions are geared towards an "parent_all" object, so that even characters and movable objects can serve as platforms themselves (other characters or falling objects can step or rest over their heads for instance), which is the reason I had to put a notme sort of function there. I'll try to revert to logic to put those outside the loop and see what happens, thanks!
 

TheouAegis

Member
If you just use temporary variables, they are much quicker for the code to access. If you use other, the code has to fetch the ID of the instance that other is referring to first. Also your code if it was intended properly, was setting multiple variables multiple times for each object in the room. You should only be saying these variables once before entering the loop.
 
V

viniciuscsg

Guest
hmm, this how I rewrote the cube_meeting without using other, obviously the reference for the overlapping checking needed to be reversed, and I probably messed something up because now it seems to be permanently in state of collision :/ I am also not sure if referring to the variables of the obj (target of the collision script), such as obj.x, obj.z, etc, will be much lighter than using other, since it is still calling variables stored elsewhere.

Code:
//cube_meeting(xx, yy, zz, obj)
xx  = argument0; yy  = argument1; zz  = argument2; obj = argument3;

   var ww = mask_width; var hh = mask_height; var zh  = zheight;

   if (xx > obj.x - ww && xx < obj.x + ww &&
       yy > obj.y - hh && yy < obj.y + hh &&
       zz > obj.z - zh && zz < obj.z + zheight) &&
       (id != obj.id)

           {
           return true;
           }
return false
Interestingly, I still get the z collisions right, and the character can jump, but it cannot move on xy plane as if he is in collision with itself. Weird.

I was later a bit confused by what you meant by making the variables temporary in this context, I thought you were saying I made them into globals and they should be locals, by they are already locals, so should be discarded right way, shouldn't they? Sorry my noobness is showing :/

Anyway, thank you very much for the help you gave me already![/code]
 
Last edited by a moderator:
Top