Per-pixel collision problem in C#

后端 未结 3 1534
猫巷女王i
猫巷女王i 2021-01-16 05:33

I am writing a small 2d game engine in C# for my own purposes, and it works fine except for the sprite collision detection. I\'ve decided to make it a per-pixel detection (e

相关标签:
3条回答
  • 2021-01-16 06:10

    I think I've found your problem.

    internal static Rectangle GetRotateDimensions(int imgx, int imgy, int imgwidth, int imgheight, double rotation, bool Crop) {
        Rectangle sz = new Rectangle(); // <-- Default constructed rect here.
        if (Crop == true) {
                // absolute trig values goes for all angles
                double dera = de_ra(rotation);
                double sin = Math.Abs(Math.Sin(dera));
                double cos = Math.Abs(Math.Cos(dera));
                // general trig rules:
                // length(adjacent) = cos(theta) * length(hypotenuse)
                // length(opposite) = sin(theta) * length(hypotenuse)
                // applied width = lo(img height) + la(img width)
                sz.Width = (int)(sin * imgheight + cos * imgwidth);
                // applied height = lo(img width) + la(img height)
                sz.Height = (int)(sin * imgwidth + cos * imgheight);
    
                // <-- Never gets the X & Y assigned !!!
        }
    

    Since you never assigned imgx and imgy to the X and Y coordinates of the Rectangle, every call of GetRotateDimensions will produce a Rectangle with the same location. They may be of differing sizes, but they will always be in the default X,Y position. This would cause the really early collisions that you are seeing because any time you tried to detect collisions on two sprites, GetRotateDimensions would put their bounds in the same position regardless of where they actually are.

    Once you have corrected that problem, you may run into another error:

    Rectangle rect;
    Image img1 = GraphicsHandler.ResizeImage(GraphicsHandler.RotateImagePoint(s1.Image, s1.Position, s1.Origin, s1.Rotation, out rect), s1.Scale);
    // <-- Should resize rect here.
    int posx1 = rect.X;
    int posy1 = rect.Y;
    

    You get your boundary rect from the RotateImagePoint function, but you then resize the image. The X and Y from the rect are probably not exactly the same as that of the resized boundaries of the image. I'm guessing that you mean for the center of the image to remain in place while all points contract toward or expand from the center in the resize. If this is the case, then you need to resize rect as well as the image in order to get the correct position.

    0 讨论(0)
  • 2021-01-16 06:15

    I don't think many people here will bother to scrutinize your code to figure out what exactly is wrong. But I can come with some hints to how you can find the problem.

    If collision happens long before it is supposed to I suggest your bounding box check isn't working properly.

    I would change the code to dump out all the data about rectangles at collision. So you can create some code that will display the situation at collision. That might be easier than looking over the numbers.

    Apart from that I doubt that per pixel collision detection easier for you to implement. When you allow for rotation and scaling that quickly becomes difficult to get right. I would do polygon based collision detection instead.

    I have made my own 2D engine like you but I used polygon based collision detection and that worked fine.

    0 讨论(0)
  • 2021-01-16 06:22

    I doubt this is the actual problem, but LockBits doesn't guarantee that the bits data is aligned to the image's Width.

    I.e., there may be some padding. You need to access the image using data[x + y * stride] and not data[x + y * width]. The Stride is also part of the BitmapData.

    0 讨论(0)
提交回复
热议问题