【问题标题】:How to detect colision on c# forms如何检测 C# 表单上的冲突
【发布时间】:2020-06-09 18:11:34
【问题描述】:

我正在尝试检测 Player obj 与 C# 中 objectList 列表中的任何其他 PhisicalEntity 之间的冲突,但我无法让它工作。有什么想法吗?

using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Media;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MyGame
{
    public partial class GameCanvas : Form
    {
        public int BlockSize = 10;
        public Timer timer1;
        private static PlayerInputHandler UINPUT = new PlayerInputHandler();
        private static List<ObjContainer> playerList = new List<ObjContainer>();
        private static List<ObjContainer> objectList = new List<ObjContainer>();
        struct speedVec
        {
            public int NormalizeSpeedVector(int value)
            {
                return (value == 0) ? 0 : ((value < 0) ? -1 : 1);
            }
        }
        class PlayerInputHandler
        {
            public int x = 0;
            public int y = 0;
            public PlayerInputHandler()
            {
            }
            public void SenceUp()
            {
                this.y = (new speedVec()).NormalizeSpeedVector(this.y - 1);
            }
            public void SenceDown()
            {
                this.y = (new speedVec()).NormalizeSpeedVector(this.y + 1);
            }
            public void SenceRight()
            {
                this.x = (new speedVec()).NormalizeSpeedVector(this.x + 1);
            }
            public void SenceLeft()
            {
                this.x = (new speedVec()).NormalizeSpeedVector(this.x - 1);
            }
            public void SenceNull()
            {
                this.x = 0;
                this.y = 0;
            }
        }
        class ObjContainer
        {
            private int OID;
            public PhisicalEntity OBJ;
            public ObjContainer(int OID, PhisicalEntity OBJ)
            {
                this.OID = OID;
                this.OBJ = OBJ;
            }
        }
        abstract class PhisicalEntity
        {
            public static PictureBox OnScreenRepresentation;
            public abstract void Step();

            public int GetX()
            {
                return OnScreenRepresentation.Location.X;
            }
            public int GetY()
            {
                return OnScreenRepresentation.Location.Y;
            }
        }
        class Player : PhisicalEntity
        {
            public int x;
            public int y;
            public int xs;
            public int ys;
            public int health;
            public int gravity;
            public int friction;
            public Player(int x, int y, int xs, int ys, int health, int gravity, int friction, PictureBox repr)
            {
                this.x = x;
                this.y = y;
                this.xs = xs;
                this.ys = ys;
                this.health = health;
                this.gravity = gravity;
                this.friction = friction;
                OnScreenRepresentation = repr;
            }
            override public void Step()
            {
                if (CheckColision(this.x, this.y, this.xs, this.ys))
                {
                    this.xs = UINPUT.x;
                    this.ys = UINPUT.y;
                    UINPUT.SenceNull();
                    this.x += this.xs * 3;
                    this.y += this.ys * 3;
                    OnScreenRepresentation.Location = new Point(this.x, this.y);
                }
            }
            public bool isBetwen(int value, int min, int max)
            {
                return (value < max) ? ((value > min) ? true : false) : false;
            }
            private bool CheckColision(int x, int y, int xs, int ys)
            {
                foreach (ObjContainer phisicalEmu in objectList)
                {
                    PhisicalEntity obj = phisicalEmu.OBJ;
                    int phiX = obj.GetX();
                    int phiY = obj.GetY();
                    if (isBetwen(x + xs, phiX + 10, phiX) || isBetwen(x + 10 + xs, phiX + 10, phiX))
                    {
                        return true;
                    }
                    if (isBetwen(y + ys, phiY + 10, phiY) || isBetwen(y + 10 + ys, phiY + 10, phiY))
                    {
                        return true;
                    }
                }
                return false;
            }
        }
        class Structural : PhisicalEntity
        {
            public int x;
            public int y;
            public int xs;
            public int ys;
            public int health;
            public int gravity;
            public int friction;
            public PictureBox OnScreenRepresentation;
            public Structural(int x, int y, int xs, int ys, int health, int gravity, int friction, PictureBox repr)
            {
                this.x = x;
                this.y = y;
                this.xs = xs;
                this.ys = ys;
                this.health = health;
                this.gravity = gravity;
                this.friction = friction;
                this.OnScreenRepresentation = repr;
            }
            override public void Step()
            {
                this.xs = UINPUT.x;
                this.ys = UINPUT.y;
                UINPUT.SenceNull();
                this.x += this.xs * 3;
                this.y += this.ys * 3;
                OnScreenRepresentation.Location = new Point(this.x, this.y);
            }
        }
        public void InitTimer()
        {
            Timer timer = new Timer();
            timer.Tick += new EventHandler(Step);
            timer.Interval = 20;
            timer.Start();
        }
        public void Step(object sender, EventArgs e)
        {
            foreach (ObjContainer obj in playerList)
            {
                obj.OBJ.Step();
            }
        }
        public GameCanvas()
        {
            InitializeComponent();
        }
        private void GC_onLoad(object sender, EventArgs e)
        {
            RegisterNewPlayer(new Player(0, 0, 0, 0, 100, 3, 0, o_934), (new Random()).Next(((new Random()).Next())));
            RegisterNewStruc(new Structural(0, 0, 0, 0, 0, 0, 0, o_980), (new Random()).Next(((new Random()).Next())));
            InitTimer();   
        }
        private void RegisterNewPlayer(Player obj, int KeyGen)
        {
            int num = ((new DateTime()).Year + (new DateTime()).Month + (new DateTime()).Day + (new DateTime()).Hour + (new DateTime()).Second + (new DateTime()).Millisecond) * KeyGen;
            ObjContainer OnRegst = new ObjContainer(num, obj);
            playerList.Add(OnRegst);
        }
        private void RegisterNewStruc(Structural obj, int KeyGen)
        {
            int num = ((new DateTime()).Year + (new DateTime()).Month + (new DateTime()).Day + (new DateTime()).Hour + (new DateTime()).Second + (new DateTime()).Millisecond) * KeyGen;
            ObjContainer OnRegst = new ObjContainer(num, obj);
            objectList.Add(OnRegst);
        }
        private void ProccessKeyEvents(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Up)
            {
                UINPUT.SenceUp();
            }
            if (e.KeyData == Keys.Down)
            {
                UINPUT.SenceDown();
            }
            if (e.KeyData == Keys.Left)
            {
                UINPUT.SenceLeft();
            }
            if (e.KeyData == Keys.Right)
            {
                UINPUT.SenceRight();
            }
        }
    }
}

【问题讨论】:

    标签: c# windows forms


    【解决方案1】:

    使用您提供的带有小更新的代码的示例修复。

        using System;
        using System.Collections.Generic;
        using System.ComponentModel;
        using System.Data;
        using System.Diagnostics;
        using System.Drawing;
        using System.Linq;
        using System.Media;
        using System.Security.Cryptography;
        using System.Security.Cryptography.X509Certificates;
        using System.Text;
        using System.Threading.Tasks;
        using System.Windows.Forms;
    
        namespace MyGame
        {
            public partial class GameCanvas : Form
            {
                public int BlockSize = 10;
                public Timer timer1;
                private static PlayerInputHandler UINPUT = new PlayerInputHandler();
                private static List<ObjContainer> playerList = new List<ObjContainer>();
                private static List<ObjContainer> objectList = new List<ObjContainer>();
                struct speedVec
                {
                    public int NormalizeSpeedVector(int value)
                    {
                        return (value == 0) ? 0 : ((value < 0) ? -1 : 1);
                    }
                }
                class PlayerInputHandler
                {
                    public int x = 0;
                    public int y = 0;
                    public PlayerInputHandler()
                    {
                    }
                    public void SenceUp()
                    {
                        this.y = (new speedVec()).NormalizeSpeedVector(this.y - 1);
                    }
                    public void SenceDown()
                    {
                        this.y = (new speedVec()).NormalizeSpeedVector(this.y + 1);
                    }
                    public void SenceRight()
                    {
                        this.x = (new speedVec()).NormalizeSpeedVector(this.x + 1);
                    }
                    public void SenceLeft()
                    {
                        this.x = (new speedVec()).NormalizeSpeedVector(this.x - 1);
                    }
                    public void SenceNull()
                    {
                        this.x = 0;
                        this.y = 0;
                    }
                }
                class ObjContainer
                {
                    private int OID;
                    public PhisicalEntity OBJ;
                    public ObjContainer(int OID, PhisicalEntity OBJ)
                    {
                        this.OID = OID;
                        this.OBJ = OBJ;
                    }
                }
                abstract class PhisicalEntity
                {
                    protected PictureBox OnScreenRepresentation;
                    public abstract void Step();
    
                    public int GetX()
                    {
                        return OnScreenRepresentation.Location.X;
                    }
                    public int GetY()
                    {
                        return OnScreenRepresentation.Location.Y;
                    }
    
                    public int GetHeight()
                    {
                        return OnScreenRepresentation.Height;
                    }
    
                    public int GetWidth()
                    {
                        return OnScreenRepresentation.Width;
                    }
                }
                class Player : PhisicalEntity
                {
                    //public int x;
                    //public int y;
                    //public int xs;
                    //public int ys;
                    public int health;
                    public int gravity;
                    public int friction;
                    public Player(int health, int gravity, int friction, PictureBox repr)
                    {
                        //this.x = x;
                        //this.y = y;
                        //this.xs = xs;
                        //this.ys = ys;
                        this.health = health;
                        this.gravity = gravity;
                        this.friction = friction;
                        OnScreenRepresentation = repr;
                    }
                    override public void Step()
                    {
                        if (CheckColision(this.GetX() + UINPUT.x, this.GetY() + UINPUT.y))
                        {
                            //this.xs = UINPUT.x;
                            //this.ys = UINPUT.y;
                            //UINPUT.SenceNull();
                            //this.x += this.xs * 3;
                            //this.y += this.ys * 3;
                            //this.x += this.xs;
                            //this.y += this.ys;
                            OnScreenRepresentation.Left += UINPUT.x;
                            OnScreenRepresentation.Top += UINPUT.y;
                        }
                        UINPUT.SenceNull();
                        //else
                        //{
                        //    UINPUT.x = this.x;
                        //    UINPUT.y = this.y;
                        //}
                    }
                    public bool isBetwen(int value, int min, int max)
                    {
                        return (value < max) ? ((value > min) ? true : false) : false;
                    }
    
                    private bool CheckColision(int x, int y)
                    {
                        var height = this.GetHeight();
                        var width = this.GetWidth();
                        var coordinates = new List<int[]>() { new[] {x,y }, new[] { x, y+height }, new[] { x+width, y }, new[] { x+width, y+height } };
    
                        foreach (ObjContainer phisicalEmu in objectList)
                        {
                            PhisicalEntity obj = phisicalEmu.OBJ;
                            int phiX = obj.GetX();
                            int phiY = obj.GetY();
                            var phiHeight = obj.GetHeight();
                            var phiWidth = obj.GetWidth();
    
                            var phiCoordinates = new List<int[]>() { new[] { phiX, phiY }, new[] { phiX, phiY + phiHeight }, new[] { phiX + phiWidth, phiY }, new[] { phiX + phiWidth, phiY + phiHeight } };
                            int maxPhiX = phiX + phiWidth;
                            int maxPhiY = phiY + phiHeight;
    
                            //Check if edge points in phi are directly part of the player object
                            foreach(var coordinate in coordinates)
                            {
                                if (isBetwen(coordinate[0], phiX, maxPhiX) && isBetwen(coordinate[1], phiY, maxPhiY))
                                {
                                    return false;//Collision
                                }
                            }
    
                            int maxX = x + width;
                            int maxY = y + height;
    
                            //Check if edge points in the player object are directly part of phi
                            foreach (var coordinate in phiCoordinates)
                            {
                                if (isBetwen(coordinate[0], x, maxX) && isBetwen(coordinate[1], y, maxY))
                                {
                                    return false;//Collision
                                }
                            }
    
    
    
                        }
                        return true;
                    }
                }
                class Structural : PhisicalEntity
                {
                    //public int x;
                    //public int y;
                    //public int xs;
                    //public int ys;
                    public int health;
                    public int gravity;
                    public int friction;
                    //public PictureBox OnScreenRepresentation;
                    public Structural(int health, int gravity, int friction, PictureBox repr)
                    {
                        //this.x = x;
                        //this.y = y;
                        //this.xs = xs;
                        //this.ys = ys;
                        this.health = health;
                        this.gravity = gravity;
                        this.friction = friction;
                        this.OnScreenRepresentation = repr;
                    }
                    override public void Step()
                    {
                        //this.xs = UINPUT.x;
                        //this.ys = UINPUT.y;
                        //UINPUT.SenceNull();
                        //this.x += this.xs * 3;
                        //this.y += this.ys * 3;
                        //OnScreenRepresentation.Location = new Point(this.x, this.y);
                        OnScreenRepresentation.Top += UINPUT.y;
                        OnScreenRepresentation.Left += UINPUT.x;
                        UINPUT.SenceNull();
                    }
                }
                public void InitTimer()
                {
                    Timer timer = new Timer();
                    timer.Tick += new EventHandler(Step);
                    timer.Interval = 20;
                    timer.Start();
                }
                public void Step(object sender, EventArgs e)
                {
                    foreach (ObjContainer obj in playerList)
                    {
                        obj.OBJ.Step();
                    }
                }
                public GameCanvas()
                {
                    InitializeComponent();
                }
    
                private void GC_onLoad(object sender, EventArgs e)
                {
    
                    RegisterNewPlayer(new Player(100, 3, 0, o_934), (new Random()).Next(((new Random()).Next())));
                    RegisterNewStruc(new Structural(0, 0, 0, o_980), (new Random()).Next(((new Random()).Next())));
                    InitTimer();
                }
                private void RegisterNewPlayer(Player obj, int KeyGen)
                {
                    int num = ((new DateTime()).Year + (new DateTime()).Month + (new DateTime()).Day + (new DateTime()).Hour + (new DateTime()).Second + (new DateTime()).Millisecond) * KeyGen;
                    ObjContainer OnRegst = new ObjContainer(num, obj);
                    playerList.Add(OnRegst);
                }
                private void RegisterNewStruc(Structural obj, int KeyGen)
                {
                    int num = ((new DateTime()).Year + (new DateTime()).Month + (new DateTime()).Day + (new DateTime()).Hour + (new DateTime()).Second + (new DateTime()).Millisecond) * KeyGen;
                    ObjContainer OnRegst = new ObjContainer(num, obj);
                    objectList.Add(OnRegst);
                }
                private void ProccessKeyEvents(object sender, KeyEventArgs e)
                {
                    if (e.KeyData == Keys.Up)
                    {
                        UINPUT.SenceUp();
                    }
                    if (e.KeyData == Keys.Down)
                    {
                        UINPUT.SenceDown();
                    }
                    if (e.KeyData == Keys.Left)
                    {
                        UINPUT.SenceLeft();
                    }
                    if (e.KeyData == Keys.Right)
                    {
                        UINPUT.SenceRight();
                    }
                }
            }
        }
    

    【讨论】:

      【解决方案2】:

      尝试查看 Rectangle 的方法 https://docs.microsoft.com/en-us/dotnet/api/system.drawing.rectangle?view=netcore-3.1

      还可以考虑使用调试模式,在调试模式下运行时,您可以绘制调试项以显示边界、碰撞,以帮助开发。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-10-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多