HaxeFlixel Tutorial: Single Separation Collisions

HaxeFlixel Speer Tutorial

Collision detection (and handling) is one of the most fiddly things when it comes to creating games, at least in my experience. There seems to be no shortage of weird bugs and issues that can pop up throughout the entire dev cycle of a game (the weirdest one I’ve encountered so far is this one right here). It’s a good thing then that HaxeFlixel comes with several functions that can take care of it for you. FlxG.collide(a,b) and you’re done, right?

Well yes, you can be. I have run into several instances where the default functions didn’t cut it for me though. The thing is that FlxCollide(a,b) separates both objects from each other when a collision occurs, which isn’t good when one of them is not supposed to be moving (for example a door). An easy fix for that is to set the immovable property of the immovable object to true; this will tell the physics code to leave that object where it is. The player will be stopped by it, but the door won’t fly off its hinges.

For truly stationary objects this is fine. However, there are cases where you want objects to act immovable some times but be movable at other times. Let me show you an example:

solidbox.gif

This metal block should stay where it is when the player walks into it. Setting immovable = true seems like a good option as it achieves that effect.

However, the game actually requires the player to move the block into position using a Speer. So I’ve added some code that sets the block’s velocity when it gets hit by a Speer. However…

phasebox.gif

The block phases through the wall! This is because it is marked as immovable which prevents the physics engine from touching its position, even if it notices the block going into a wall. Setting immovable = false will fix this, but also allow the player to push the block which we don’t want:

pushbox.gif

What a conundrum! But I’ve found a very simple way around these limitations. It’s really quite dumb but it works, so here it is!

Introducing: Single Separation

Without much ado, here’s the function I wrote to help me out in these cases:

public function separateFirst(obj:FlxObject, staticObject:FlxObject){
    var p = staticObject.immovable;
    staticObject.immovable = true;
    var r = FlxObject.separate(obj, staticObject);
    staticObject.immovable = p;
    return r;
}

This function will only separate obj, while the staticObject will stay right where it is. The function is quite simple but let’s step through it one by one.

First, we save the immovable object’s immovable value in p. Then we set the staticObject to be immovable.

We then call HaxeFlixel’s built-in FlxObject.separate function to handle the collision for us. We save the result of the separation in r so we can return it.

Finally, we restore the immovable property of staticObject to whatever it was before we called the function and return the result of the separation. Pretty simple, huh?

Implementation and Result

Using separateFirst we can now implement the behavior we want by using it to check the collision between player and block. To collide the block with the world we can simply use the default FlxG.collide(). Note: The block must have immovable = false set for this to work as intended!

separateFirst(player,block);
FlxG.collide(block,world);

This will make sure that if the player touches the block, the block will act as if it was solid, meaning the player can’t just push it around. However, the block will still properly collide with the world, be affected by gravity, etc.

finalbox.gif

There might be better or smarter ways to achieve this, but this solution has worked out quite well for me so far. If you have any better approaches let me know in the comments!

Hanging on Balloons

October 25, 2017
HaxeFlixel Speer Tutorial

Path Movement in Speer

October 17, 2017
HaxeFlixel Speer Tutorial
comments powered by Disqus