繁体   English   中英

C#-我的碰撞代码不会导致播放器停止在其音轨中

[英]C# - My Collision code won't result in the player stopping in his tracks

我一直在研究我的LWJGL引擎之一的C#和SFML重制。 到目前为止,一切都很好,但是,当我尝试复制/转换碰撞代码时,事情进展得并不顺利。

这是我的玩家/实体类,边界框和游戏代码。

实体:

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SFML.Graphics;
using SFML.System;
using SFML.Window;

namespace FastSrc_CS.Core
{
    public class FSEntity
    {
        public Vector2f Position, Size;
        public Color EColor;

        public RectangleShape sprite;

        public BoundingBox Bounds;

        public bool canMove;
        public float VelX, VelY;

        public FSEntity()
        {

        }

        public virtual void Init(Vector2f pos, Vector2f size, Color color)
        {
            Position = pos;
            Size = size;
            EColor = color;

            sprite = new RectangleShape();
            sprite.FillColor = EColor;
            sprite.Position = Position;
            sprite.Size = Size;
            //sprite.Origin = new Vector2f(size.X / 2, size.Y / 2);

            Bounds = new BoundingBox(Position, Size);
        }

        public void SetVelX(float x)
        {
            VelX = x;
        }

        public void SetVelY(float x)
        {
            VelY = x;
        }

        public Vector2f GetOrigin()
        {
            return new Vector2f(Size.X / 2, Size.Y / 2);
        }

        public virtual void Update()
        {

        }

        public void UpdatePos()
        {
            Position.X += VelX;
            Position.Y += VelY;
            sprite.Position = Position;
            Bounds.UpdateBounds(Position, Size);
        }

        public virtual void Render(RenderWindow w)
        {
            w.Draw(sprite);
        }
    }
}

玩家:

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SFML.Graphics;
using SFML.System;
using SFML.Window;

namespace FastSrc_CS
{
    class Player : Core.FSEntity
    {
        public float speed = 6f;

        public override void Init(Vector2f pos, Vector2f size, Color color)
        {
            canMove = true;
            base.Init(pos, size, color);
        }

        public override void Update()
        {
            base.Update();

            Movement();

            Position.X += VelX;
            Position.Y += VelY;
            sprite.Position = Position;
            Bounds.UpdateBounds(Position, Size);
        }

        public void Movement()
        {
            if (Keyboard.IsKeyPressed(Keyboard.Key.A) && canMove == true)
            {
                SetVelX(-speed);
                SetVelY(0);
            }
            else if (Keyboard.IsKeyPressed(Keyboard.Key.D) && canMove == true)
            {
                SetVelX(speed);
                SetVelY(0);
            }
            else if (Keyboard.IsKeyPressed(Keyboard.Key.W) && canMove == true)
            {
                SetVelY(-speed);
                SetVelX(0);
            }
            else if (Keyboard.IsKeyPressed(Keyboard.Key.S) && canMove == true)
            {
                SetVelY(speed);
                SetVelX(0);
            }
            else
            {
                SetVelX(0);
                SetVelY(0);
            }
        }

        public override void Render(RenderWindow w)
        {
            base.Render(w);
        }
    }
}

边界框:

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SFML.Graphics;
using SFML.System;
using SFML.Window;

namespace FastSrc_CS.Core
{
    public class BoundingBox
    {
        public FloatRect Rectangle;

        public BoundingBox(Vector2f pos, Vector2f size)
        {
            Rectangle = new FloatRect(pos, size);
        }

        public bool Collide(BoundingBox b)
        {
            bool col = false;

            if (this.Rectangle.Intersects(b.Rectangle))
            {
                col = true;
            }
            else
            {
                col = false;
            }

            return col;
        }

        public void UpdateBounds(Vector2f pos, Vector2f size)
        {
            Rectangle.Width = size.X;
            Rectangle.Height = size.Y;
            Rectangle.Left = pos.X;
            Rectangle.Top = pos.Y;
        }
    }
}

游戏:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FastSrc_CS.Core;
using SFML.Graphics;
using SFML.System;
using SFML.Window;

namespace FastSrc_CS
{
    public class Game : FSGame
    {
        Player p = new Player();
        Wall w = new Wall();

        public override void Init()
        {
            p.Init(new Vector2f(400, 300), new Vector2f(32, 32), Color.Red);
            w.Init(new Vector2f(100, 100), new Vector2f(32, 32), Color.Blue);

            Entities.Add(p);
            Entities.Add(w);
        }

        public override void Update()
        {
            Console.WriteLine(p.Position.X);

            //COLLISION CODE FOR WALLS
            if (p.Bounds.Collide(w.Bounds))
            {
                //Right Collision
                if (p.VelX > 0)
                {
                    Console.WriteLine("Right Collision");
                    p.canMove = false;
                    p.Position.X = w.Position.X - 32;
                    p.SetVelX(0);
                }
                else if (p.VelX < 0)
                {
                    Console.WriteLine("Left Collision");
                    p.canMove = false;
                    p.Position.X = w.Position.X + 32;
                    p.SetVelX(0);
                }

                if (p.VelX == 0)
                {
                    p.canMove = true;
                }
            }

            Entities.ForEach(k => k.Update());
        }

        public override void Render(RenderWindow w)
        {
            Entities.ForEach(k => k.Render(w));
        }
    }
}

问题出在该区域的“游戏”类之内:

        //COLLISION CODE FOR WALLS
        if (p.Bounds.Collide(w.Bounds))
        {
            //Right Collision
            if (p.VelX > 0)
            {
                Console.WriteLine("Right Collision");
                p.canMove = false;
                p.Position.X = w.Position.X - 32;
                p.SetVelX(0);
            }
            else if (p.VelX < 0)
            {
                Console.WriteLine("Left Collision");
                p.canMove = false;
                p.Position.X = w.Position.X + 32;
                p.SetVelX(0);
            }

            if (p.VelX == 0)
            {
                p.canMove = true;
            }
        }

当我执行此操作时,播放器将停止移动,但会稍微植入墙壁。 我知道您在想什么,“将使p.canMove = true的if语句p.canMove = true冲突的if语句之外。” 我已经尝试过了,它导致播放器与立方体来回弹跳。 我尝试过不同的方法,以至于我考虑将这段代码省去。 我决定退回到Stack Overflow,看看是否有人可以帮助我。 提前致谢。

我认为代码根本不是您的引擎-给定结果,并且在扫描代码后,这似乎还不错。 由于播放器夹在墙上,因此播放器和墙壁的硬编码值32都是不正确的。 尝试这个:

        if (p.VelX > 0)
        {
            Console.WriteLine("Right Collision");
            p.canMove = false;
            //move the right of our player to the left of the wall by setting
            //his x to the wall's x minus his width.
            p.Position.X = w.Position.X - p.Size.Width;
            p.SetVelX(0);
        }
        else if (p.VelX < 0)
        {
            Console.WriteLine("Left Collision");
            p.canMove = false;
            //Move the left of our player to the right of the wall, or
            //the wall's x plus the wall's width
            p.Position.X = w.Position.X + w.Size.Width;
            p.SetVelX(0);
         }

希望对您有所帮助。

编辑

实际上,我认为我发现了另一个问题。 当在检测到碰撞后移动其X后更改玩家的位置时,您忘记调用UpdatePos()方法。 因此,您移动的是他的位置,而不是实际的矩形,这可能会导致错误。 而是,在移动他的x之后,立即调用UpdatePos()

暂无
暂无

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

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