Пересечение игр C# и SFML

У меня проблема с моим MoveEntity() метод в 2D платформерной игре (например, PacMan). Когда игрок находится на пересечении пути, я хочу сделать:

e.IsAtIntersection = true;

а затем позвоните UpdateDirection(),

Но он не останавливается, вместо этого он идет путями, и не имеет значения, есть ли стены или пустые пути. Программа никогда не достигает вышеуказанной линии. Член остается false, Возможно, есть возможность написать это более простым способом или что я допустил простую ошибку. Вот полный метод:

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;
}

3 ответа

Оператор == с плавающей точкой проверяет точное равенство. Часто даже поплавки, которые прошли через очень похожие операции, все равно не будут равны. Когда вы сравниваете равенство на поплавках, лучше всего делать следующее:

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

Здесь someSmallFloat часто устанавливается как float.Epsilon, но в вашем случае вы можете использовать большее число, чтобы допустить допустимое отклонение от ошибки, более увлекательным, чтобы игрок мог двигаться, даже если он немного выключен, чем наказывать игрока за очень маленькое неточностей.

Маловероятно, что дополнение с плавающей запятой для e.X а также e.Y попадает точно в целевое значение. Вы должны проверить, переместился ли объект через соответствующую строку:

Например, что-то вроде этого для движения вправо:

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

Вы также можете исправить положение, если хотите.

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

Вы также можете переместить его по оси Y, чтобы компенсировать обратное движение по оси X.

Вот для вас мой отредактированный рабочий код:

        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;
    }
Другие вопросы по тегам