Make an engine and then remake an engine.
Because I'm [slowly] working on my engine for other people to use, I'm forced to stick with using object-based collisions rather than tile-collisions. I can say this though: tile-based collisions make platforms and shit so much easier to code. With object-based collisions, you have shit like "a=place_meeting(x,y,obj_ground); if a if a.object_index!=obj_platform{ ". Something like that. Then you end up having parents of parents and that's just a plain headache. With tile-based collisions, it's a simple matter of only needing to check for collisions with platforms and not worrying about the ground (which is handled in a separate script).
Then you start coming up with similar methods for use in object-based collisions. With a tile-based collision, you don't need to check every pixel, just a few select pixels within a specific range. So then why not do the same for object-based collisions? If your sprites are 32 pixels tall and your tiles are 16x16, just check for collisions every 16(+1) pixels. So for a sprite 32px tall or shorter, check for collisions at bbox_top, bbox_bottom, and ceil(mean(bbox_top,bbox_bottom)). You went from checking 16x32 pixels to checking just 12 pixels (3 for each direction).
Yes Inccubus, that's one reason it's taking me so long to release v0.4 for you.
Here's an excerpt exemplifying what I was talking about above. It checks if there's a block in front of the player, then checks if it's a trapdoor (which should be passable), then prohibits movement if the check passes.
var plat_T,plat_M,plat_B;
plat_T=instance_position(x+(x-sprite_get_bbox("bbox_left")-1+max(0,sign(hspd)))*sign(hspd),
sprite_get_bbox("bbox_top"),prt_ground);
plat_M=instance_position(x+(x-sprite_get_bbox("bbox_left")-1+max(0,sign(hspd)))*sign(hspd),
ceil(mean(sprite_get_bbox("bbox_top"),sprite_get_bbox("bbox_bottom"))),prt_ground);
plat_B=instance_position(x+(x-sprite_get_bbox("bbox_left")-1+max(0,sign(hspd)))*sign(hspd),
sprite_get_bbox("bbox_bottom"),prt_ground);
if plat_T
if plat_T.object_index==prt_TrapDoor
plat_T=-1;
if plat_M
if plat_M.object_index==prt_TrapDoor
plat_M=-1;
if plat_B
if plat_B.object_index==prt_TrapDoor
plat_B=-1;
if plat_T || plat_M || plat_B
{collide=true; break;}