2
\$\begingroup\$

I'm working on making my first Pong game with XNA Framework 4.0. Right now i've put 2 pong paddles and a ball (they have separate classes). In the "Paddle" class i've made a function that returns a Vector2 list of the normals to its edges (i'm going to leave all 4 of them as i'm considering adding rotation and other things in the future).

Right now i'm trying to do my own implementation of the separating axis theorem. My question is: is there a more efficient method of computing the edges(or the normals to them), other than doing them by hand? Here's my code from the Paddle class:

public List<Vector2> NormalsToEdges()
    {
        Vector2 Edge = Vector2.Zero;
        List<Vector2> lst = new List<Vector2>();

        //take this normal because our reference axes have the origin in the top left corner
        //upper edge
        Edge = (this.paddlePosition + new Vector2(this.Width, 0)) - this.paddlePosition;
        if (Edge != Vector2.Zero)
        {
            Edge.Normalize();
            lst.Add(new Vector2(Edge.Y, -Edge.X));
        }

        //right edge
        Edge = (this.paddlePosition + new Vector2(this.Width, this.Height)) - (this.paddlePosition + new Vector2(this.Width, 0));
        if (Edge != Vector2.Zero)
        {
            Edge.Normalize();
            lst.Add(new Vector2(Edge.Y, -Edge.X));
        }


        //bottom edge
        Edge = (this.paddlePosition + new Vector2(0, this.Height)) - (this.paddlePosition + new Vector2(this.Width, this.Height));
        if (Edge != Vector2.Zero)
        {
            Edge.Normalize();
            lst.Add(new Vector2(Edge.Y, -Edge.X));
        }

        //left edge
        Edge = this.paddlePosition - (this.paddlePosition + new Vector2(0, this.Height));
        if (Edge != Vector2.Zero)
        {
            Edge.Normalize();
            lst.Add(new Vector2(Edge.Y, -Edge.X));
        }

        return lst;
    }

I don't know why but i have a feeling that i'm over-complicating things (considering that i have to update these edges on every update cycle in the main game). For example, if i decide to change the sprite to some convex irregular polygon with 50+ (or 500+) edges will the performance impact be high? (suppose i know all the vertex coordinates and/or that i can actually get the list of edge-vectors somehow, in CCW or CW order).

Second issue. Suppose i want to heighten one of the paddles under certain conditions in the game. I know i can use scaling for this (on Draw) and test the scale factor (like if it's 1.0f i use height/width of the original sprite, otherwise i make a new property that gives the scaled values), but is there a way to actually scale the sprite itself? (so that height/width/etc values will return the scaled versions). I'm asking this because i think it might save additional coding of properties, recalculation of rectangles etc.

All in all, i'm aiming for maximum efficiency.

Thanks

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

First of all if you are not rotating the paddle then you do not need to recalculate the normals every frame.

In case you have a world matrix then you can get the normals easily from it using its front, right, up etc vectors.

As you are using c# which has a garbage collector creating a new list every frame is not a good idea (if you are targeting xbox or wp7 you're likely to notice problems). Instead you can have an array that is updated every frame in case the solution with a world matrix does not suit you.

SAT is very demanding on bodies with many faces (or edges) so I guess you would have to use some modified variant of it if you had a 500+ edge body. You could divide a convex body into subsets but I have never done anything like that myself. Personally I think I would just go for using a simpler body for collision detection if that was the case.

In case the width and height was to increase I would do so by having vectors represent their corners and actually moving these (in local space of course). Then let physics, rendering etc handle that accordingly. It might be good for you to have an array of corner points anyway when you are going to go through collision handling.

\$\endgroup\$
8
  • \$\begingroup\$ Thank you. Basically should I store the normals to the edges of the paddle in a static array that i can access from the main game's class? Going a little further, updating this array only when a rotation occurred should be the most efficient way too,right? \$\endgroup\$
    – X Y
    Aug 10, 2012 at 12:35
  • \$\begingroup\$ Not a static array as different paddles could have different orientations. Yes you could just update it when a rotation occurs but if you in the future have physics that may cause several rotations per frame then update it once per frame. I wouldn't bother too much with optimizations like that right now though, just get it to work and optimize later if you need to. Good luck with your project! \$\endgroup\$ Aug 10, 2012 at 13:28
  • \$\begingroup\$ Ok, i got it to work but only partially. The problem is that i need to update the paddle vertex positions every update cycle and for the center of the ball also. It runs ok but it's not efficient in my eyes. Secondly, the collision is not always done properly. Sometimes the ball passes through the paddles (in very specific positions) and i really cannot understand why. The minimum translation vector is done correctly(the direction too) but somehow the collision is not registered. I think it has to do with the axis from ball's center to paddle center (or it's normalization). \$\endgroup\$
    – X Y
    Aug 13, 2012 at 10:05
  • \$\begingroup\$ Ig you want to have efficient collision detection then you will need to update your bounding boxes for all your objects every frame. This is not inefficient but will save you a lot of calulations as you can do a course collision detection before your SAT. As for your collision handling you could check out my answer at gamedev.stackexchange.com/questions/33309/… this might be a similar problem. If not you might need to describe the problem in more detail, maybe in a new question. \$\endgroup\$ Aug 13, 2012 at 10:13
  • \$\begingroup\$ Thanks for the answer. It doesn't seem to be the case of multiple collisions. I've put a boolean variable that checks for this and it doesn't go through there. Also there is no change in the ball animation while re-checking for collisions. My left paddle is scaled to 2*vertical size, and the exact point where the collision check misses is right at the top of the paddle. My right paddle isn't scaled but the issue occurs in the same position (at the top). At least this rules out the Draw method. Any more ideas? should i post a new question(or an answer to this one to add the code)? \$\endgroup\$
    – X Y
    Aug 13, 2012 at 11:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .