So, in my breakout clone, I’ve encountered points the place the ball will typically part by bricks and the borders if it collides with one after which instantly collides with one other after. My guess is that because the collisions are so shut collectively, it is resolving one, and by the point it is presupposed to resolve the opposite, it is already put the ball previous no matter different collision to resolve, inflicting it to part by the thing.
Instance of what I imply:
I’ve seen and tried to implement an answer the place the ball will discover and resolve the collision closest to it, determine how lengthy into the body it occurred, after which name the replace perform, however it would not appear to work.
That is what my ball class appears to be like like (Pastebin hyperlink):
namespace brickbreakerRewrite.Asset.Recreation
{
public enum BallState
{
Lively,
Inactive
}
public class Ball : GameObj
{
float pace;
public Vector2 course;
Courtroom court docket;
public BallState CurrentState;
protected void ReverseDirX() { course.X *= -1; }
protected void ReverseDirY() { course.Y *= -1; }
protected void BounceLeft() { course.X = -Math.Abs(course.X); }
protected void BounceRight() { course.X = Math.Abs(course.X); }
protected void BounceUp() { course.Y = -Math.Abs(course.Y); }
protected void BounceDown() { course.Y = Math.Abs(course.Y); }
public Ball(Vector2 Place, float pace, Courtroom court docket): base(Place)
{
Listing<Texture2D> photographs = new();
photographs.Add(GetContent.GetTexture("ball_0"));
photographs.Add(GetContent.GetTexture("ball_1"));
photographs.Add(GetContent.GetTexture("ball_2"));
photographs.Add(GetContent.GetTexture("ball_3"));
photographs.Add(GetContent.GetTexture("ball_4"));
Picture = photographs[1];
this.pace = pace;
this.court docket = court docket;
course = new Vector2 (0, 1);
}
public Ball(Vector2 Place, float pace, Courtroom court docket, BallState startingstate): base(Place)
{
Listing<Texture2D> photographs = new();
photographs.Add(GetContent.GetTexture("ball_0"));
photographs.Add(GetContent.GetTexture("ball_1"));
photographs.Add(GetContent.GetTexture("ball_2"));
photographs.Add(GetContent.GetTexture("ball_3"));
photographs.Add(GetContent.GetTexture("ball_4"));
Picture = photographs[1];
this.pace = pace;
this.court docket = court docket;
course = new Vector2 (0, -1);
CurrentState = startingstate;
}
protected Vector2 Velocity(float deltaTime)
{
Vector2 Velocity = new Vector2(pace * course.X * deltaTime,
pace * course.Y * deltaTime);
return Velocity;
}
protected Vector2 ProjectPosition(float deltaTime)
{
Vector2 projectedPosition = (new Vector2(CollideBox.Middle.X, CollideBox.Middle.Y) + Velocity(deltaTime));
return projectedPosition;
}
personal void ResolveBrickCollision(Brick brick, int injury)
{
brick.Weaken(injury);
}
personal CollidePoint GetClosestCollidePoint(float deltaTime, out float closestMagnitude)
{
Listing<CollidePoint> collidePoints = new();
foreach (GameObj merchandise in court docket.ObjectList)
{
if ((merchandise != this) &&
(GetCollisions.DoesLineIntersectRect(CollideBox.Middle.X, CollideBox.Middle.Y,
ProjectPosition(deltaTime).X, ProjectPosition(deltaTime).Y, merchandise.CollideBox)))
{
Collision collisionType = GetCollisions.LineRectCollision(CollideBox.Middle.X, CollideBox.Middle.Y,
ProjectPosition(deltaTime).X, ProjectPosition(deltaTime).Y,
merchandise.CollideBox, out Vector2 intersectPoint);
collidePoints.Add(new CollidePoint(intersectPoint, merchandise, collisionType));
}
}
CollidePoint closest = null;
closestMagnitude = float.MaxValue;
foreach (CollidePoint level in collidePoints)
{
float present = ExtendedMath.Magnitude(level.Place.X - Place.X, level.Place.Y - Place.Y);
if (present < closestMagnitude)
{
closestMagnitude = present;
closest = level;
}
}
return closest;
}
protected void CheckCollisions(float deltaTime)
{
change(CurrentState)
{
case BallState.Lively:
CollidePoint present = GetClosestCollidePoint(deltaTime, out var magnitudeClosest);
if (present != null)
{
change (present.CollisionType)
{
case Collision.Left:
Place.X = present.GameObj.CollideBox.Left - CollideBox.Width;
Console.WriteLine("L");
BounceLeft();
break;
case Collision.Proper:
Place.X = present.GameObj.CollideBox.Proper;
BounceRight();
Console.WriteLine("R");
break;
case Collision.Prime:
Place.Y = present.GameObj.CollideBox.Prime - CollideBox.Top;
BounceUp();
Console.WriteLine("T");
break;
case Collision.Backside:
Place.Y = present.GameObj.CollideBox.Backside;
BounceDown();
Console.WriteLine("B");
break;
}
if (present.GameObj is Paddle)
{
course.X = (CollideBox.Middle.X - present.GameObj.CollideBox.Middle.X) / 15f;
course.Normalize();
}
if (present.GameObj is Brick)
{
ResolveBrickCollision((Brick)present.GameObj, 1);
}
float udt = deltaTime * (magnitudeClosest / ExtendedMath.Magnitude(ProjectPosition(deltaTime).X, ProjectPosition(deltaTime).Y));
Replace(deltaTime - udt);
}
break;
}
}
protected void Transfer(float deltaTime)
{
change (CurrentState)
{
case BallState.Lively:
Place += Velocity(deltaTime);
break;
case BallState.Inactive:
Place = new Vector2(court docket.Participant.Place.X + (court docket.Participant.CollideBox.Width / 2) - CollideBox.Width / 2, court docket.Participant.CollideBox.Y - 6);
break;
}
}
public override void Replace(float deltaTime)
{
ProjectPosition(deltaTime);
CheckCollisions(deltaTime);
Transfer(deltaTime);
if(Place.Y > 260)
court docket.KillList.Add(this);
}
}
}



