Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using polymorphism for collision detection in an elegant way

I am trying to set up some simple 2D shapes which can be dragged about the window using the mouse. I want the shapes to register a collision when I drag one into another. I have an interface.

interface ICollidable
{
    bool CollidedWith(Shape other);
}

I then have an abstract class Shape that implements the above interface.

abstract class Shape : ICollidable
{
    protected bool IsPicked { private set; get; }
    protected Form1 Form { private set; get; }

    protected int X { set; get; } // Usually top left X, Y corner point
    protected int Y { set; get; } // Used for drawing using the Graphics object

    protected int CenterX { set; get; } // The center X point of the shape
    protected int CenterY { set; get; } // The center X point of the shape

    public Shape(Form1 f, int x, int y)
    {
        Form = f;
        X = x; Y = y;
        Form.MouseDown += new MouseEventHandler(form_MouseDown);
        Form.MouseMove += new MouseEventHandler(Form_MouseMove);
        Form.MouseUp += new MouseEventHandler(Form_MouseUp);
    }

    void Form_MouseMove(object sender, MouseEventArgs e)
    {
        if(IsPicked)
            Update(e.Location);
    }

    void Form_MouseUp(object sender, MouseEventArgs e)
    {
        IsPicked = false;
    }

    void form_MouseDown(object sender, MouseEventArgs e)
    {
        if (MouseInside(e.Location))
            IsPicked = true;
    }

    protected abstract bool MouseInside(Point point);
    protected abstract void Update(Point point);
    public abstract void Draw(Graphics g);
    public abstract bool CollidedWith(Shape other);
}

I then have ten concrete classes Circle, Square, Rectangle etc that extend the Shape class and implement the abstract methods. What I would like to do is come up with some oop clean and elegant way to do the collosion detection instead having a large block of if statements in the CollidedWith method such is

public bool CollidedWith(Shape other)
{
    if(other is Square)
    {
        // Code to detect shape against a square
    }
    else if(other is Triangle)
    {
        // Code to detect shape against a triangle
    }
    else if(other is Circle)
    {
        // Code to detect shape against a circle
    }
    ...   // Lots more if statements
}

Has anyone any ideas. It's a problem I've thought about before but am only putting into practice now.

like image 613
John ClearZ Avatar asked Sep 06 '12 17:09

John ClearZ


People also ask

Which method is used to collision detection between to rectangle objects?

Axis-Aligned Bounding Box One of the simpler forms of collision detection is between two rectangles that are axis aligned — meaning no rotation. The algorithm works by ensuring there is no gap between any of the 4 sides of the rectangles. Any gap means a collision does not exist.

What is a collision detection in programming?

Collision detection concerns the detection of collisions between objects in the virtual environment. Primarily employed to stop objects moving through each other and the environment. Collision Detection is everywhere in computer games: between characters and characters, between characters and terrain, etc.

How do you check for collisions?

If both the horizontal and vertical edges overlap we have a collision. We check if the right side of the first object is greater than the left side of the second object and if the second object's right side is greater than the first object's left side; similarly for the vertical axis.


2 Answers

Is the collision detection so "Shape Specific" that there's a different implementation for every permutation of

Circle vs. Other Circle
Circle vs. Other Square
Circle vs. Other Triangle
Square vs. Other Circle
...

It sounds like you're trying to create a matrix of all possibilities but if you come up with 10 new shapes, 20 in total, you have 400 possibilites.

Instead, I would try to come up with a generic Shape.Overlaps(Shape other) method in your abstract class that would satisfy all of them.

If this is just 2D Geometry if should be trivial to figure out if the Edge Paths of any shapes intersect.

like image 58
Eoin Campbell Avatar answered Oct 22 '22 01:10

Eoin Campbell


Instead of specific shapes, all they ALL are are Paths or Regions.

A square is just a poly with 4 points, that happen to be at right angles. Then just write one Path.CollidesWith(Path) method and be on your way.

Check out some related questions.

like image 38
hometoast Avatar answered Oct 21 '22 23:10

hometoast