Celeste and TowerFall Physics

Actor Basics

public void MoveX(float, Action); 
public void MoveY(float, Action);
public void MoveX(float amount, Action onCollide) 
{
xRemainder += amount;
int move = Round(xRemainder);
if (move != 0)
{
xRemainder -= move;
int sign = Sign(move);
while (move != 0)
{
if (!collideAt(solids, Position + new Vector2(sign, 0))
{
//There is no Solid immediately beside us
Position.X += sign;
move -= sign;
}
else
{
//Hit a solid!
if (onCollide != null)
onCollide();
break;
}
}
}
}

Moving Solids Prep

public void Move(float, float);
public virtual bool IsRiding(Solid solid); 
public virtual void Squish();

The Heavy Lifting

public void Move(float x, float y) 
{
xRemainder += x;
yRemainder += y;
int moveX = Round(xRemainder);
int moveY = Round(yRemainder);
if (moveX != 0 || moveY != 0)
{
//Loop through every Actor in the Level, add it to
//a list if actor.IsRiding(this) is true
List riding = GetAllRidingActors();
//Make this Solid non-collidable for Actors,
//so that Actors moved by it do not get stuck on it
Collidable = false;
if (moveX != 0)
{
xRemainder -= moveX;
Position.X += moveX;
if (moveX > 0)
{
foreach (Actor actor in Level.AllActors)
{
if (overlapCheck(actor))
{
//Push right
actor.MoveX(this.Right — actor.Left, actor.Squish);
}
else if (riding.Contains(actor))
{
//Carry right
actor.MoveX(moveX, null);
}
}
}
else
{
foreach (Actor actor in Level.AllActors)
{
if (overlapCheck(actor))
{
//Push left
actor.MoveX(this.Left — actor.Right, actor.Squish);
}
else if (riding.Contains(actor))
{
//Carry left
actor.MoveX(moveX, null);
}
}
}
}
if (moveY != 0)
{
//Do y-axis movement

}
//Re-enable collisions for this Solid
Collidable = true;
}
}

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store