简体   繁体   中英

C# and SFML game intersection

I have problem with my MoveEntity() method in a 2D platformer game (like PacMan). When player is on intersection path I want to make:

e.IsAtIntersection = true;

and then call UpdateDirection() .

But he doesn't stop, instead he goes through paths and it doesn't matter if there are walls or empty paths. The program never reaches the above line. The member stays false . Maybe there is the possibility to write it in an easier way or that there is a simple mistake I made. Here is the complete method:

private void MoveEntity(Entity e)
{
    int angle = 0;

    if (e.currentDirection == Direction.RIGHT) angle = 0;
    else if (e.currentDirection == Direction.DOWN) angle = 90;
    else if (e.currentDirection == Direction.LEFT) angle = 180;
    else if (e.currentDirection == Direction.UP) angle = 270;

    var scalex = Math.Round(Math.Cos(angle * (Math.PI / 180.0)));
    var scaley = Math.Round(Math.Sin(angle * (Math.PI / 180.0)));

    var velocityx = (float)(e.Speed * scalex);
    var velocityy = (float)(e.Speed * scaley);

    Sprite sp = sprites[e.Name];
    Vector2f v = new Vector2f(sp.Position.X + velocityx, sp.Position.Y + velocityy);
    sp.Position = v;

    var eCenterX = sp.Position.X + sp.TextureRect.Width / 2;
    var eCenterY = sp.Position.Y + sp.TextureRect.Height / 2;

    var tileY = Math.Floor((eCenterY) / TILEHEIGHT);
    var tileX = Math.Floor((eCenterX) / TILEWIDTH);

    var tileXpos = TILEWIDTH * Math.Floor(tileX + 1);
    var tileYpos = TILEHEIGHT * Math.Floor(tileY + 1);

    e.X = (int)tileY;
    e.Y = (int)tileX;

    if (eCenterX == tileXpos && eCenterY == tileYpos)
        e.IsAtIntersection = true;
    else
        e.IsAtIntersection = false;
}

The == operator, with floating points, checks for exact equality. Often even floats that have gone through very similar operations will still not be equal. When you compare equality on floats the best practice is to do the following:

if(Math.Abs(floatA-floatB) <= someSmallFloat)

someSmallFloat here is often set to float.Epsilon but in your case you may want to use a higher number to allow a margin for error, more fun to allow the player to move even if they are slightly off, than punish the player for very small inaccuracies.

It is very unlikely that the floating point addition for eX and eY hits exactly the target value. You should check if the entity moved across the according line:

Eg something like this for the rightwards movement:

if(e.currentDirection == Direction.RIGHT 
   && eCenterX - velocityx< tileXpos && eCenterX >= eCenterX)
    e.IsAtIntersection = true;

You can also correct the position if you like.

...
    e.IsAtIntersection = true;
    e.X = tileXpos;

You could also move it along the y-coordinate to compensate for the back-movement along the x-coordinate.

Here is for you my edited working code:

        private void MoveEntity(Entity e)
    {
        int angle = 0;

        if (e.currentDirection == Direction.RIGHT) angle = 0;
        else if (e.currentDirection == Direction.DOWN) angle = 90;
        else if (e.currentDirection == Direction.LEFT) angle = 180;
        else if (e.currentDirection == Direction.UP) angle = 270;

        var scalex = Math.Round(Math.Cos(angle * (Math.PI / 180.0)));
        var scaley = Math.Round(Math.Sin(angle * (Math.PI / 180.0)));

        var velocityx = (float)(e.Speed * scalex);
        var velocityy = (float)(e.Speed * scaley);

        Sprite sp = sprites[e.Name];
        Vector2f v = new Vector2f(sp.Position.X + velocityx, sp.Position.Y + velocityy);
        sp.Position = v;

        var tileY = (int)sp.Position.Y / 60;
        var tileX = (int)sp.Position.X / 60;

        var tileXpos = tileX * 60;
        var tileYpos = tileY * 60;

        e.X = (int)tileY;
        e.Y = (int)tileX;

        if (sp.Position.X == tileXpos && sp.Position.Y == tileYpos)
            e.IsAtIntersection = true;
        else
            e.IsAtIntersection = false;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM