Skip to content

Instantly share code, notes, and snippets.

@Geokureli
Last active September 30, 2021 16:51
Show Gist options
  • Save Geokureli/070adf01f764a154d0a075f00d957945 to your computer and use it in GitHub Desktop.
Save Geokureli/070adf01f764a154d0a075f00d957945 to your computer and use it in GitHub Desktop.
import flixel.FlxBasic;
import flixel.FlxObject;
import flixel.FlxG;
class MassUtil
{
/**
* Same as FlxG.collide but allows objects to ride other non-immovable objects.
*
* @param objectOrGroup1 The first object or group you want to check.
* @param objectOrGroup2 The second object or group you want to check. If it is the same as the first,
* Flixel knows to just do a comparison within that group.
* @param notifyCallback A function with two `FlxObject` parameters -
* e.g. `onOverlap(object1:FlxObject, object2:FlxObject)` -
* that is called if those two objects overlap.
* @return Whether any objects were successfully collided/separated.
*/
static public function collide(?objectOrGroup1:FlxBasic, ?objectOrGroup2:FlxBasic, ?notifyCallback:Dynamic->Dynamic->Void):Bool
{
return FlxG.overlap(objectOrGroup1, objectOrGroup2, notifyCallback, separate);
}
/**
* Same as FlxObject.separate but allows objects to ride other non-immovable objects.
*
* @param object1 Any `FlxObject`.
* @param object2 Any other `FlxObject`.
* @return Whether the objects in fact touched and were separated.
*/
public static function separate(object1:FlxObject, object2:FlxObject):Bool
{
// No mass calculations needed on immovable objects or tilemaps
@:privateAccess
if (object1.immovable || object2.immovable || object1.flixelType == TILEMAP || object2.flixelType == TILEMAP)
return FlxObject.separate(object1, object2);
var separatedX:Bool = separateX(object1, object2);
var separatedY:Bool = separateY(object1, object2);
return separatedX || separatedY;
}
/**
* The X-axis component of the object separation process.
*
* @param object1 Any `FlxObject`.
* @param object2 Any other `FlxObject`.
* @return Whether the objects in fact touched and were separated along the X axis.
*/
public static function separateX(object1:FlxObject, object2:FlxObject):Bool
{
@:privateAccess
var overlap:Float = FlxObject.computeOverlapX(object1, object2);
// Then adjust their positions and velocities accordingly (if there was any overlap)
if (overlap != 0)
{
var obj1v:Float = object1.velocity.x;
var obj2v:Float = object2.velocity.x;
overlap *= 0.5;
object1.x = object1.x - overlap;
object2.x += overlap;
var obj1velocity:Float = Math.sqrt((obj2v * obj2v * object2.mass) / object1.mass) * ((obj2v > 0) ? 1 : -1);
var obj2velocity:Float = Math.sqrt((obj1v * obj1v * object1.mass) / object2.mass) * ((obj1v > 0) ? 1 : -1);
var average:Float = (obj1velocity + obj2velocity) * 0.5;
obj1velocity -= average;
obj2velocity -= average;
object1.velocity.x = average + obj1velocity * object1.elasticity;
object2.velocity.x = average + obj2velocity * object2.elasticity;
return true;
}
return false;
}
/**
* The Y-axis component of the object separation process.
*
* @param object1 Any `FlxObject`.
* @param object2 Any other `FlxObject`.
* @return Whether the objects in fact touched and were separated along the Y axis.
*/
public static function separateY(object1:FlxObject, object2:FlxObject):Bool
{
@:privateAccess
var overlap:Float = FlxObject.computeOverlapY(object1, object2);
// Then adjust their positions and velocities accordingly (if there was any overlap)
if (overlap != 0)
{
var obj1delta:Float = object1.y - object1.last.y;
var obj2delta:Float = object2.y - object2.last.y;
var obj1v:Float = object1.velocity.y;
var obj2v:Float = object2.velocity.y;
overlap *= 0.5;
object1.y = object1.y - overlap;
object2.y += overlap;
var obj1velocity:Float = Math.sqrt((obj2v * obj2v * object2.mass) / object1.mass) * ((obj2v > 0) ? 1 : -1);
var obj2velocity:Float = Math.sqrt((obj1v * obj1v * object1.mass) / object2.mass) * ((obj1v > 0) ? 1 : -1);
var average:Float = (obj1velocity + obj2velocity) * 0.5;
obj1velocity -= average;
obj2velocity -= average;
object1.velocity.y = average + obj1velocity * object1.elasticity;
object2.velocity.y = average + obj2velocity * object2.elasticity;
// This is special case code that handles cases like horizontal moving platforms you can ride
if (object1.collisonXDrag && object2.active && object2.moves && (obj1delta > obj2delta))
{
object1.x += object2.x - object2.last.x;
}
else if (object2.collisonXDrag && object1.active && object1.moves && (obj1delta < obj2delta))
{
object2.x += object1.x - object1.last.x;
}
return true;
}
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment