1

I'm trying to create a simple game library mainly to teach myself. I read some posts here and in the web as such. But I think my problem is a bit different because I'm using my "own logic".

The basics:

All my objects on screen are called "entity" and they are capable to implement an interface called "EntityActionListener" wich allows to interact with the mouse, the keyboard, to move on the screen etc.

How to move the entity the best way?

Idea:

First of all I want to implement the movement, then the bouncing and then the collision for the entities.

For the movement and bouncing, and this is where I have problems, I want the following variables and functions:

protected float posx = 0, posy = 0;
protected float v = 0, vx = 0, vy = 0;
protected int direction = 0;

I use the setVelocity(float arg1) function to set the velocity (v) to arg1 and update the velocity on the axis (vx, vy):

/**
 * Set the velocity on both axis according to the direction given
 *
 * @param arg1 the direction in degrees
 * @param arg2 the velocity
 */
private void setVelocityOnAxis(int arg1, float arg2)
{
    // Check for speed set to 0
    if (arg2 == 0) {
        vx = 0;
        vy = 0;
        return;
    }

    // Set velocity on axis
    vx = (float) (Math.cos(arg1 * Math.PI / 180) * arg2);
    vy = (float) (Math.sin(arg1 * Math.PI / 180) * arg2);
}

So the velocity (v) may updates within a triggered event for example. => This step seems to work fine.

But I'm having some troubles with the direction which should be handled as follows:

/**
 * Set the entity direction
 *
 * @param arg1 the direction in degrees
 */
protected final void setDir(int arg1)
{
    // Update direction
    direction = arg1;

    // Update velocity on axis
    setVelocityOnAxis(direction, v);
}

/**
 * Get the enity direction based on the axis
 *
 * @param arg1 the x velocity
 * @param arg2 the y velocity
 */
protected final int getPointDir(float arg1, float arg2)
{
    // Set the direction based on the axis
    return (int) (360 - Math.abs(Math.toDegrees(Math.atan2(arg1, arg2)) % 360));
}

I wanted to have a bouncing on the border of the frame so I checked for the 4 directions by comparing the x and y coordinates and set either the vx or the vy according to the side to its additive inverse (like 1 to -1). But this does fail.

If I would just update the vx or vy on each side it would bounce like expected but the direction is not updated for this reason.

Here is the code I used:

// ...
// Hit bounds on x axis
direction = -vx; // works.
setDir(getPointDir(-vx, vy)); // does not work.

I'm not that good in geometry and trigonometry. The problem is that I can't say why a collision with a horizontal speed of 1 in direction 360 results in 45 degrees or other strange things I got from the debug prints ...

I really hope someone out there can help me. I just can't fix it.

EDIT:

My question is: Why is this not working. Some code in either setDir() or getPointDir() must be wrong.

EDIT 2

So, I finally get it work. The problem was that the entity had a direction of 45 and moved downwards instead of upwards so I additive inverse for the v speed - this causes this stupid error because minus and minus are positive and while I was bouncing it changed always both velocities, the vx and the vy. I just had to change something in the calculation for the degrees instead. Thank you for your help.

F. Müller
  • 3,969
  • 8
  • 38
  • 49
  • I can't work out what the specific question is here. If it's just about trigonometry, then Stack Overflow probably isn't the most suitable place... – Oliver Charlesworth Apr 18 '12 at 23:57
  • Really confusing what the code's supposed to do... Btw you can also give your arguments more meaningful names than `arg1` and `arg2` :) – Torious Apr 18 '12 at 23:58
  • There are many comment on each function. Well one could change the names but this won't matter anyway. – F. Müller Apr 19 '12 at 00:03
  • I wouldn't bother with 'v' or 'direction' unless you really need them (or for init), just remember 'vx' and 'vy'. It's very easy to bounce off a horizontal or vertical wall then, just flip one of them. You can calculate v and direction from vx and vy, like: v = hypot(vx, vy), dir = atan2(y, x). Be glad if you're not doing object-to-object collisions and bouncing, that's a lot more difficult, I suggest a physics lib in that case. Maybe your bug was to call atan2(x, y) instead of atan2(y, x) ? – Sam Watkins Apr 19 '12 at 03:55

3 Answers3

1

I'm taking a guess that getPointDir() and setVelocity() should calculate a direction in degrees from an x,y and an x,y from a direction in degrees (respectively). In that case, here's the proper line of getPointDir():

return (int) (360 + Math.toDegrees(Math.atan2(arg2, arg1))) % 360;

A simple test:

public static void main(String[] args) {
    Test t = new Test();

    for (int i = 0; i < 360; i++) {
        t.setVelocityOnAxis(i, 10);
        System.out.println("Angle: " + i + " vx: " + t.vx + " vy: " + t.vy);
        System.out.println("getPointDir: " + t.getPointDir(t.vx, t.vy));
    }

}

Edit as for the error, atan2() is always y,x -- easier to spot with variables names other than arg1, arg2. The other error was in the Math.abs logic.

Fuhrmanator
  • 11,459
  • 6
  • 62
  • 111
  • I found the error in atan2() like you wrote I then wrote something similar to this. The debug prints were right. But the bouncing is still strange (not working properly) sometimes it does not bounce it just slides along the side :| until it reaches the edge and then bounces. I updated the post above - please have a look. – F. Müller Apr 19 '12 at 10:32
0

Check this answer. It has the bounce on an axis correctly. You have to think the incoming angle is just as big as the outgoing angle, just opposite. The picture in the post describes this. Good luck.

Community
  • 1
  • 1
Mads
  • 724
  • 3
  • 10
  • Well thats just what I wanted to implement. But the problem is not how to do it. The problem is that I don't know why it is not working. – F. Müller Apr 19 '12 at 00:13
0

Maybe this is what you're looking for... (still not sure I get your code).

In getPointDir():

double deg = Math.toDegrees(Math.atan2(arg1, arg2));
if (deg < 0) deg += 360;
return (int) deg;

And then use setDir(getPointDir(-vx, vy)) like in your original post.

Torious
  • 3,364
  • 17
  • 24