Hot questions for Using Lightweight Java Game Library in geometry

Question:

I am trying to bounce a projectile off of a wall in Slick. When the wall is vertical or horizontal, I can just invert the x or y velocity of the projectile, but when this is not the case I am struggling. I found another answer to a similar question in C# and have tried to implement it, but the result is just that the ball goes off at 180 degrees every time. What I have is:

Vector2f norm = wall.getNormal();
float comp = (vect.dot(norm)/norm.dot(norm));
Vector2f u = new Vector2f(norm.getX()*comp,norm.getY()*comp);
Vector2f w = new Vector2f(vect.getX()-u.getX(),u.getX());
vect.set(w.getX()-u.getX(),w.getY()-u.getY());

Where wall is a Vector2f that I am trying to bounce off of (converted from a line to a vector, but not sure if this was necessary) and vect is the trajectory of my projectile.

Any advice would be really helpful. I would love if someone could explain an answer to me rather than just giving me the code, because I think I may need to implement something slightly different later. Thanks.


Answer:

The answer here is going to wind up being mostly a question of math. I briefly go over the math/physics involved and trust that you should be able to implement the math/physics in code yourself.

How projectiles are supposed to bounce off of walls In classical physics, or at least in a reasonably representative model of classical physics, when a projectile collides with a wall, the magnitude of the angle at which it leaves the wall relative to the 'normal' vector of the wall is equal to the magnitude at which it approaches the wall relative to the 'normal' vector. In other words, draw a line perpendicular to the wall the object is colliding with. The angle between this line and the vector of your projectile moving towards the wall will be the same as the angle of the vector of your projectile moving away from the wall.

This is most commonly discussed for light rays, but it works the same way for simple projectiles. http://hyperphysics.phy-astr.gsu.edu/hbase/phyopt/fermat.html

How to calculate these angles So let's say you have a vector for the normal of the wall, and a vector for the projectile. For 2-dimensional vectors, this is actually quite easy. You should have a couple of decent options here. One way might be to get the angles of the two vectors and subtract them to find the difference.

Now we know the magnitude of the angle, but we now need to create a vector with the same angle but on the other side of the normal vector. Your vector library conveniently allows you to adjust your vector by a given angle. You should be able to take the projectile's current velocity vector and adjust in the correct direction it by twice the angle between it and the normal-to-wall vector and get the desired velocity vector post-reflection. The trick I will leave you to figure out is a good way to determine if you need to adjust your vector in the clockwise or counter-clockwise direction.

Some things to keep in mind about Vector2f

  • The getNormal() method returns a unit vector in the same direction as the vector
  • If you want a vector normal to a certain vector, you must use the getPerpendicular() method
  • A vector may be rotated/adjusted by a certain angle using the sub(double theta) method
  • If you would like to retrieve the angle of a vector, you may do so using the getTheta() method

Question:

I've created a method that draws a black border around a drawn texture. The border lines however do create little gaps at the corners. I think it has to do with the width of the border and tried to add the borderwidth to the length of the lines, but this makes them to short with some borderwidth values and to big with other borderwidth values.

public static void DrawBorder(float x, float y, float width, float height) {
    float borderWidth = 10.0f;
    glColor3f(0, 0, 0);
    glLineWidth(borderWidth);
    glTranslatef(x, y, 0);

    glBegin(GL_LINE_LOOP);
    glVertex2f(0, 0);
    glVertex2f(width, 0);
    glVertex2f(width, height);
    glVertex2f(0, height);
    glEnd();
    glColor3f(255, 255, 255);
}

Answer:

OpenGL does not draw end caps on lines, and it does not join lines together. There are two ways to solve this:

  1. Make each line a little longer, by borderWidth/2. This means that your lines can't share vertices.

  2. (Recommended) Use triangles instead. Something like this:

    float border = 10.0f;
    glColor3f(0, 0, 0);
    glTranslatef(x, y, 0);
    glBegin(GL_TRIANGLE_STRIP);
    glVertex2f(    0,      0); glVertex2f(      - border,        - border);
    glVertex2f(width,      0); glVertex2f(width + border,        - border);
    glVertex2f(width, height); glVertex2f(width + border, height + border);
    glVertex2f(    0, height); glVertex2f(      - border, height + border);
    glVertex2f(    0,      0); glVertex2f(      - border,        - border);
    glEnd();