• 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 A Quirk in Precise Sprite / Object Collision with Filled Squares

S

Steneub

Guest
I have discovered a quirk in how precise collision is determined with the collision_line() function.
upload_2019-6-12_6-22-30.png
Using a small sprite (8x8) with one color and several frames as a map* for collision, most of which are angled slopes and one frame as a solid block, I learned that this solid block does not behave as if Precise Collision is enabled.

The documentation clearly states:
...for precise collisions to be enabled, the object or instance that you are checking for must also have precise collisions enabled for their sprite.
Which the sprite does have Precise enabled, which is why the other tiles work the way they should. This quirk has been causing me to pull my hair out.

The engine treats this frame as imprecise, so I must do two checks to be sure the player object is colliding with instances of this collision object.

Code:
    var c = collision_line( x1, y1, x2, y2, obj_collision, true, true );
    if (c == noone) c = collision_line( x1, y1, x2, y2, obj_collision, false, true );
    if (c != noone) {
        collision_direction[i] = true;
    }
I know this is 1.4 and not going to get fixed, but is there a way around this quirk other than doing this the way I'm doing it?

* For a little context, I have an object read the tile data and spawn corresponding objects referencing the appropriate shape.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Do you have "separate collision masks" flagged as well as "precise" in the sprite collision properties?
 
M

Misty

Guest
I dont get it. I have never seen collision code like this before, so it doesnt make sense to me.

Normally, most collision systems check for a bounding box, then if inside bounding box, enable detailed collisions.

Your collisions seem to do it in reverse. The code first checks for precise collisions, if no collision is found, then it goes to imprecise collisions. Is this what you intended?
 
S

Steneub

Guest
My intention was to do pixel-perfect collisions against an arbitrarily rotated rectangle (as I type this, I'm having a bit of a light-bulb moment, so I'll continue here, but then share my realization afterwards).

The game is a top-down driving game, and I want to know if my rotated bounding box is in contact with any of the race track's walls (or will be in the next frame). Relative to the center of the vehicle object, I calculate the locations of the four corners and then use collision_line() to check whether there are any collisions between those points.
Code:
// "fp" stands for footprint, and I have already calculated the x,y positions for each of the four corners of the footprint
// collision_dirs is an enum with D_FRONT, D_LEFT, D_RIGHT, and D_REAR as stand-ins for 0,1,2,3

for (var i = collision_dirs.D_FRONT; i <= collision_dirs.D_REAR; i++) {
    switch (i) {
        case collision_dirs.D_FRONT:
            var x1 = fp_front_left_x;
            var y1 = fp_front_left_y;
            var x2 = fp_front_right_x;
            var y2 = fp_front_right_y;
            break;
    /*snip*/
    }
    var c = collision_line( x1, y1, x2, y2, obj_collision, true, true );
    if (c == noone) c = collision_line( x1, y1, x2, y2, obj_collision, false, true );
    if (c != noone) {
        collision_direction[i] = true;
    }
}
My assumption was that collision_line() with the precision "true" should have been enough to catch anything in between those two line. The solution you're seeing here is a "well, screw it" grasp at straws that says if it fails the desired way, then fall-back to something else that might work. It does work and performance on my potato computer is unhindered so I'm tempted to leave it as is. If optimization is an issue, I can fiddle with things here.

HOWEVER

I can probably skip this precise collision checking that I'm doing and rely on the engine to do pixel-perfect object versus pixel-perfect objects. My current setup is a vehicle that picks its frame from some math
Code:
//draw rotation of sprite, add half a rotation (180/15) so frame-selection is offset a bit
draw_sprite(sprite1, floor(((facing_direction+360 + 180/15) mod 360) / 15), x, y);
This can be skipped because all of this is supposed to be logic before transferring positions and states to the actual rendered product. I can probably update image_angle and do something much simpler to check for collisions.

All of this is beside the point, and it remains that collision_line() is quirky in the scenario where one of the frames of a precise sprite could be defined by an imprecise rectangle and is not detected properly.
 
M

Misty

Guest
Just use Box2d for top-down racing. However, GM doesnt allow you to iterate through Box2d collision groups per frame, so you will not be able to use bridges or ramps in it. Therefore you may have to learn to use collision_line anyway.

Just to make sure, the wall object must also set to precise if I remember correct. You said it did already, which is strange. In that case, make sure the sprite mask is set properly. Also make sure your line points are properly defined. Draw a circle where the each line point is to make sure.
 
Top