GMS 2 Issues with 'Movement and Collision with Multiple Moving Objects'

Issue 1: Order of instance code execution affects movement behavior.

Visual Aid for Issue 1:

Move and Collision Problem.png

Scenario: 4 block instances are lined up one directly behind another and all are going to move together in the same direction.

First they will all be moving to the right. (left side of visual aid)
the blue block is determined to be first in the order of code execution; there is nothing in the way, so it is moved to it's new position.
then the green block is executed; same resolution as the blue block.
same story for the orange and red blocks.
Each game step shows all the blocks moving together as one cohesive unit. All looks good.

Then all the blocks stop and will move to left (right side of visual aid)
the blue block is still the first instance to have it's code executed; this time there is something in the way (the green block), so it can't and doesn't move for this step.
then the green block is executed; it also cannot move (orange block in the way). same story for the orange block.
finally the red block is executed; there is nothing in the way so it moves.
repeating this order of execution sees the blue block not get to move at all until the 5th round of code execution.
as a direct result, the blocks are no longer in a cohesive unit; they have been spaced apart


So, is this something that can be reconciled, or is this something that isn't that big of a deal and can be ignored in the course of development?
If it can be fixed, what would the method be?

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Issue 2: Two moving objects not positioned correctly when colliding into each other.

Visual Aid for Issue 2:

Move and Collision Problem 2.png

Scenario: Two blocks are moving to meet at a point between them.

the light blue block is where the dark blue block intends to go; similar story for light and dark red blocks.
due to the order of code execution having the blue block move first, it makes it's full movement, while the red block must stop short


Now, would the ideal situation be where each block moves part way and meets somewhere in the middle, or is this also a case of something that is less of an issue than it seems?
If the ideal movement can be done, what would the method be? Would it have noticeable overhead in doing so?
 

TheouAegis

Member
If this is for a space Invaders style movement, justjust have a global variable tell the enemies whether to move left or right. When an enemy reaches the edge of the screen or an obstacle, change the variable period no collision checking needed between the enemies.

As far as actual collision checking between enemies, I'll pass that off on the someone else.
 

GarbageHaus

Member
Taking a few shots in the dark here:

Scenario 1 seems expected as per the order of operations. So, there needs to be some sort of check to determine direction, and then use that value to determine which order of blocks you want to use.
GML:
if !place_meeting(x+1,y,obj_Box) {
//If this box doesn't hit another box going right, your regular code here
}
if !place_meeting(x-1,y,obj_Box) {
//If this box doesn't hit another box going left, The same code above but reverse order
}
My example is really inelegant, but should illustrate my point, one order for right to left, the other for left to right. There's certainly a better way of doing this but I'm still learning and can't suggest anything else.

Scenario 2: No idea. Are these boxes tiles by any chance? I know tiles will snap to a particular dimension.

Might need the specific code to suggest best course of action.
 

chamaeleon

Member
One approach could be to let each instance move in the step event without the collision/overlap restriction, and then use the end step event to revert/adjusr invalid movement. Whether the revert/adjustment is handled by each instance or a single control instance might depend on how complex the reversion/adjustment process might end up being.
 

TheouAegis

Member
One approach could be to let each instance move in the step event, and then use the end step event to revert/adjusr invalid movement. Whether the revert/adjustment is handled by each instance or a single control instance might depend on how complex the reversion/adjustment process might end up being.
I had almost said this, but consider the scenario where an object does move into collision and then in the next event moves back out of the collision but into collision with another object that has already detected that it was not in a collision.

You could do a recursive collision check if any enemy detects that it is in the collision. If a collision is detected, move back to your original position, then if that causes a collision, change the focus to the collided instance and have it moved back, then have it check for a new collision and change the focus to that new collision... I hate these kinds of collision handling, which is why I passed on it.
 

chamaeleon

Member
I had almost said this, but consider the scenario where an object does move into collision and then in the next event moves back out of the collision but into collision with another object that has already detected that it was not in a collision.

You could do a recursive collision check if any enemy detects that it is in the collision. If a collision is detected, move back to your original position, then if that causes a collision, change the focus to the collided instance and have it moved back, then have it check for a new collision and change the focus to that new collision... I hate these kinds of collision handling, which is why I passed on it.
I quite agree. I just wanted to mention it, in case it is suitable for the problem at hand, which of course depends on just how complex the movement might be. Personally, I have used a single control instance to manage the position of all instances that move in tandem to some extent.
 

TheouAegis

Member
I mean if you watch Mario games, they just bump into each other back and forth back and forth and get thrown off anyway.
 

GameDevDan

The Jam Host
Moderator
GMC Elder
for issue #1 if your game is grid based and you know that all the objects should definitely move at the same time you can do something like this in each object (and alter it for your needs).

GML:
var freeToMove = 0;

for (var i=0; i <= maxDistanceToCheck; i += gridSize) {

    if !(place_meeting( x-i, y, objectThatBlocksTheWay)) {
   
        freeToMove += 1;
   
    }

}

x -= freeToMove*gridSize;
I used this in a grid-based puzzle game (it was a bit like 2048) to check how many "cells" were clear in a given row.

Each object checks how many empty squares in total are to the left of it (up to some specified maximum distance) so it already compensates for the fact that a solid box to its left will also be moving one square to the left into any empty space. This obviously only works on the condition that all solid objects currently blocking the way will definitely move in the same direction at the same time, but you may be able to adapt the principles to your needs. In any case you will definitely need to use some kind of loop (like the for loop in the example) to get the effect you want.
 
for issue #1 if your game is grid based and you know that all the objects should definitely move at the same time you can do something like this in each object (and alter it for your needs).
My game is not grid-based. It's supposed to be a multiplayer game (just local right now, no networking planned for awhile) so I'm dealing with several player-controlled instances.
The goal for the max number of players is 20-24, so there's going to be some work involved.

One approach could be to let each instance move in the step event without the collision/overlap restriction, and then use the end step event to revert/adjusr invalid movement. Whether the revert/adjustment is handled by each instance or a single control instance might depend on how complex the reversion/adjustment process might end up being.
I had almost said this, but consider the scenario where an object does move into collision and then in the next event moves back out of the collision but into collision with another object that has already detected that it was not in a collision.

You could do a recursive collision check if any enemy detects that it is in the collision. If a collision is detected, move back to your original position, then if that causes a collision, change the focus to the collided instance and have it moved back, then have it check for a new collision and change the focus to that new collision... I hate these kinds of collision handling, which is why I passed on it.
I'm liking that idea, Chamaeleon, and I also grasp that potential pitfall, TheouAegis.

During some initial testing of player movement and collision, I saw how characters moving in a line would show this behavior based on collision and the order the game decides to run each instance's code.
I'm thinking the move-reverter/adjuster might operate by checking each instance's collisions in the same order as their movement, and taking the direction of movement for each instance into account to solve for Issue 2.

Now I'm just concerned about how difficult such a system is to implement, and what sort of overhead would result from it.
It might be something that people may ignore, but these things are just nagging at me right now.
 
Top