Author Topic: GM 8.1 to Studio: colliding with playerKiller inside solid block  (Read 4879 times)

Pigmess

  • Trial Wannabe
  • Posts: 3
  • OS:
  • Windows 8.1/Server 2013 Windows 8.1/Server 2013
  • Browser:
  • Chrome 42.0.2311.90 Chrome 42.0.2311.90
    • View Profile
  • Playstyle: Keyboard
Hi, first time posting.

I'm in the process of porting my fangame from GM 8.1 to GM Studio. I've noticed a difference in behavior: the player can sometimes collide with a playerKiller that is embedded in a solid block.

My code is built on a version of Lemon engine, which I've made modifications to as I go.

The player object checks whether it's touching a playerKiller in an End Step event, which I believe should come after the player has been moved out of the solid object - at least, that's how it seemed to work in 8.1. I know the order of events is not as transparent in Studio, and am wondering if there's a way to make this check somewhere with 100% certainty that the player will be pushed out of solid objects beforehand (thus keeping the player from exploding when touching a solid block that houses a spike, for example).

Sephalos

  • Spike Dodger
  • Posts: 228
  • OS:
  • Windows Vista/Server 2008 Windows Vista/Server 2008
  • Browser:
  • Chrome 42.0.2311.90 Chrome 42.0.2311.90
    • View Profile
  • Playstyle: Gamepad
Re: GM 8.1 to Studio: colliding with playerKiller inside solid block
« Reply #1 on: April 23, 2015, 01:16:37 AM »
I don't have that much experience with game maker studio yet but I'm pretty sure the order of steps should still be the same or at least quite similar. I'm currently making a engine for studio with the help of Klazen so I will definitly check this out to make sure it works correctly on my end.

Unless the order of steps somehow got messed up during the import or you accidently did something wrong, the only culprit I could see is the fact that gravity pushes the player down into a block very slightly. This is because the gravity in the step event of the player object is badly coded and constantly shifts between 0 and 0.4 while standing on a block. Another theory could be that they changed the way solid objects work in game maker studio and you might have to do some collision checking before landing on a block so you don't clip through it.

I would start the game in debug mode (press the red play button at the top) and check the player coordinates step by step to see what exacly happens to the player object when landing a block and go from there.

Sephalos

  • Spike Dodger
  • Posts: 228
  • OS:
  • Windows Vista/Server 2008 Windows Vista/Server 2008
  • Browser:
  • Chrome 42.0.2311.90 Chrome 42.0.2311.90
    • View Profile
  • Playstyle: Gamepad
Re: GM 8.1 to Studio: colliding with playerKiller inside solid block
« Reply #2 on: April 23, 2015, 02:39:29 AM »
Alright, so I've done a bit of testing and it seems that I have the same problem with my engine. My guess is that GM Studio's collision events happen after end step events. I've come up with a work around, it's not perfect but it works for now.

In end step of the player instead of having...
Code: [Select]
if place_meeting(x,y,playerKiller){
    killPlayer();
}

Replace it with this...
Code: [Select]
if place_meeting(x,y,playerKiller) and !place_meeting(x,y,block) {
    killPlayer();
}

This ensures that the player will not die when clipping inside a block. This code will require more testing to make sure it doesn't break the game in any other way.

I will try to find a better solution later. Since we can assume that the collision events happen after end step events in GM Studio, having the block collision detection inside the player step event would work. Unfortunately, it's not as simple as copy+pasting the collision code.

Sephalos

  • Spike Dodger
  • Posts: 228
  • OS:
  • Windows Vista/Server 2008 Windows Vista/Server 2008
  • Browser:
  • Chrome 42.0.2311.90 Chrome 42.0.2311.90
    • View Profile
  • Playstyle: Gamepad
Re: GM 8.1 to Studio: colliding with playerKiller inside solid block
« Reply #3 on: April 23, 2015, 03:21:31 AM »
Since this is a interesting topic for me I've done even more research on the order of events in both GM8.1 and GMStudio.

This is the event order used in GM8.1
(click to show/hide)

This is the event order used in GMStudio
(click to show/hide)

Pigmess

  • Trial Wannabe
  • Posts: 3
  • OS:
  • Windows 8.1/Server 2013 Windows 8.1/Server 2013
  • Browser:
  • Chrome 42.0.2311.90 Chrome 42.0.2311.90
    • View Profile
  • Playstyle: Keyboard
Re: GM 8.1 to Studio: colliding with playerKiller inside solid block
« Reply #4 on: April 23, 2015, 01:22:29 PM »
Thanks for the response. Sorry I didn't see your reply until now - when I posted this I didn't realize that email notifications are off by default.

According to the docs, the event order is only guaranteed to conform to a few rules:

https://docs.yoyogames.com/source/dadiospice/000_using%20gamemaker/events/index.html

Even if you figure out an order in more detail, subsequent updates to the software can change it, so it shouldn't be relied upon. In any case, the image you posted for Studio's event order does not represent the order of events - it's just a list of the events.

EDIT:

Looking at your work-around:

Quote
This ensures that the player will not die when clipping inside a block.

I needed to additionally check that the block is solid, since platform is a child of block, before preventing death.

UPDATE:

My current understanding of the problem is as follows:

In GM 8.1, playerKiller collision check happened in player's End Step because it was known to happen after other Collision events. The engine relies on this for proper function.

In GM Studio, the only order guaranteed each step is that of the 3 Step events and that of the Draw events.

Unless we want to muddy up one of our draw events (gross!) the only way we can ensure one collision check happens before another is by performing the checks in one or more of the 3 Step events.

E.g., we could do both checks in End Step, or do one in Step and another in End Step.

The downside of this is, we incur overhead when we perform a collision check in a Step event instead of using a collision event. (We also might have to rewrite the collision logic due to the change in locale.)

Ideally, we'd have a way to tell GM Studio something about collision event order dependency, but I don't know if this is possible with the way events are implemented.

For now, I'll put the checks in End Step, but if someone knows a way to indicate collision resolution order among objects, I'd much appreciate a reply.
« Last Edit: April 23, 2015, 04:36:16 PM by Pigmess »

klazen108

  • Administrator
  • The Kid
  • Posts: 286
  • your a kid now your a squid now
  • OS:
  • Windows 8.1/Server 2013 Windows 8.1/Server 2013
  • Browser:
  • Chrome 42.0.2311.90 Chrome 42.0.2311.90
    • View Profile
    • Delicious-Fruit
  • Playstyle: Keyboard
Re: GM 8.1 to Studio: colliding with playerKiller inside solid block
« Reply #5 on: April 23, 2015, 09:24:01 PM »
Unless we want to muddy up one of our draw events (gross!) the only way we can ensure one collision check happens before another is by performing the checks in one or more of the 3 Step events.

E.g., we could do both checks in End Step, or do one in Step and another in End Step.

The downside of this is, we incur overhead when we perform a collision check in a Step event instead of using a collision event. (We also might have to rewrite the collision logic due to the change in locale.)

I would say putting the collision checks in End Step would be fine. That way you can check block collision, rectify the kid's position, and then check for playerkillers in the new position. The slowdown you'll incur from that is negligible:



As you can see, using the collision event, the player spends 4% of the time handling collision. Using the step event, he spends 2% of the time handling the collision. Never do premature optimization!

I'll have to test to see if this performs identically; I just threw it together to profile it really quick.

Pigmess

  • Trial Wannabe
  • Posts: 3
  • OS:
  • Windows 8.1/Server 2013 Windows 8.1/Server 2013
  • Browser:
  • Chrome 42.0.2311.90 Chrome 42.0.2311.90
    • View Profile
  • Playstyle: Keyboard
Re: GM 8.1 to Studio: colliding with playerKiller inside solid block
« Reply #6 on: April 23, 2015, 09:35:06 PM »
Thanks for your reply.

You're looking at the frame where the collision event fires, right? I wouldn't expect a big difference in the time the event takes, but in my understanding, the step event fires every frame, whereas the collision event fires only when collision is detected.

I don't know the way this is implemented; I'm just going by hearsay around the Internet.

Side note:

I have tried transplanting the code from collision events to the End Step event, as you describe, but have had difficulty reproducing the correct behavior.

When I work on this tomorrow I'll post code to illustrate the changes I made in transplanting it; maybe then we can debug the resultant behavior.

UPDATE:

This is the (relevant) code I'm currently using in the player's End Step event. It more or less produces the desired behavior, but I'd rather find a more optimized, more exact refactor (more on this below).

Code: [Select]
var blockInstance = instance_place(x, y, block);
var collidingWithSolid = false;

while (blockInstance != noone)
{
    if (blockInstance.solid)
    {
        collidingWithSolid = true;
        break;
    }
   
    ds_stack_push(reactivationStack, blockInstance);
    instance_deactivate_object(blockInstance);
    blockInstance = instance_place(x, y, block);
}

while (!ds_stack_empty(reactivationStack))
{
    instance_activate_object(ds_stack_pop(reactivationStack));
}

if (!collidingWithSolid)
{
    if (place_meeting(x,y,playerKiller))
    {
        killPlayer();
    }
}

As you can see, I'm deactivating block instances in a loop (storing them on a stack for reactivation after the loop) so that successive calls to instance_place return unique instances IDs.

I've left the events for collision with block and platform alone.

The above is almost a true refactor, but completely ignores collision with a playerKiller on the frame where the player intersects a solid block. The original code running in GM 8.1 wouldn't ignore collision on this frame - instead, the end step code was running after x & y were set to xprevious & yprevious and after the collision events were processed (i.e., after the solid block had pushed the player out and the player had been moved up against the edge of the solid, and appropriate speeds zeroed). I've tried reproducing this in the End Step event with no success thus far; this is an approach I continue to consider.

Another possibility I'm considering (and will try next) is to wrap the end step logic to the next frame by putting it in the Begin Step event. This would guarantee it come after the collision events of the prior step, with the (small) downside that the player's death will occur one frame later, which I expect will be difficult to discern; I'll give it a go and see if it adversely affects the engine in other ways.

UPDATE:

Moving the playerKiller End Step logic (as it originally existed) into the Begin Step event, surprisingly, did not prevent the player from being killed by a spike embedded within a wall.

I had expected it would fix the issue, albeit perhaps creating new ones, since it would rectify the relative order of the position update, the block collision processing, and the playerKiller collision check.
« Last Edit: April 24, 2015, 10:51:31 AM by Pigmess »