简体   繁体   English

C#和SFML游戏交集

[英]C# and SFML game intersection

I have problem with my MoveEntity() method in a 2D platformer game (like PacMan). 在2D平台游戏(例如PacMan)中,我的MoveEntity()方法有问题。 When player is on intersection path I want to make: 当玩家在交叉路口时,我要进行以下操作:

e.IsAtIntersection = true;

and then call UpdateDirection() . 然后调用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 . 成员保持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. Epsilon通常设置为float错误。

It is very unlikely that the floating point addition for eX and eY hits exactly the target value. eXeY的浮点加法极不可能恰好达到目标值。 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. 您也可以沿y坐标移动它,以补偿沿x坐标的向后移动。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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