Search code examples
javamathmethodscollision-detection

Method to keep object inside of oval failing


This method is run during a larger simulation I am developing. Essentially this Gladiator object is moving around on a screen screenX by screenY (my variablea are set to 1000,720). Gladiator.center[0] is the x position, Gladiator.center[1] is the y position. The purpose of the below method is to keep the Gladiator from moving outside of the oval I have drawn on the screen with this command:

g.fillArc(0,0, screenX,screenY, 0, 360);    

It is run immediately after the Gladiator has completed its movement, so the end point is its current center. The start point is endpoint - Gladiator.xMove and Gladiator.yMove, variables describing the change that was just made in position.

The move method this all ends with offsets position by an integer value. As I am using pixels as coordinates I would prefer to keep the inputs there integers rather than doubles... thus I have inserted that logic statement that makes sure the end result will be just inside the oval rather than just outside of it.

public void wallsStop(Gladiator glad, int screenX, int screenY) {

double value;
double gladX;
double gladY;
double finalX;
double finalY;
double v;
int n = 1;
double slope;
double rise = (int)glad.yMove;
double run = (int)glad.xMove;
slope = rise/run;
v = run;
gladX = glad.center[0]-(int)glad.xMove;
gladY = glad.center[1]-(int)glad.yMove;
value = (Math.pow((glad.center[0]-(screenX/2)),2)/(Math.pow(screenX/2,2)))+(Math.pow((glad.center[1]-(screenY/2)),2)/(Math.pow(screenY/2,2)));
    if (value > 1) {
    System.out.println("Centers: ("+glad.center[0]+","+glad.center[1]+")");
        while ( value > 1 && n < 8) {
        System.out.println("Value: "+value);
            if (value > 1) {
            v=v-v/Math.pow(2,n);
            System.out.println("Testing "+v);
            } else if (value <= .99 && n < 8) {
            v=v+v/Math.pow(2,n);
            System.out.println("Testing "+v);
            }
            value = (Math.pow(((gladX+v)-(screenX/2)),2)/(Math.pow(screenX/2,2)))+(Math.pow(((gladY+v*slope)-(screenY/2)),2)/(Math.pow(screenY/2,2)));
            n++;
        }
        finalX = v-run;
        finalY = v*slope-rise;

        if ( v - run < 0 ) {
        finalX = v - run - 1;
        finalY =v * slope - rise - slope;
        } else if (v - run > 0) {
        finalX = v - run + 1;
        finalY = v * slope - run + slope;
        }


        System.out.println("Value "+value+" Slope: "+slope+" finals: "+finalX+","+finalY+" Start and end point ("+gladX+","+gladY+"),("+glad.center[0]+","+glad.center[1]+")");
        glad.move((int)finalX,(int)finalY);

    }
}

Essentially the program keeps splitting the difference of where it has looked up or down until it finds a value which is less than 1, but has also split the difference at least 8 times to make sure its accurate enough. This result means it is inside the oval.

Current tests result in the Gladiator object being slowed dramatically but slowly moving outside of the oval anyway.

In this test I just did, I got optimal results for bug fixing as the coordinates lined up nicely with the center of the top of the screen allowing for easy comprehension of where the edge should be.

Starting point: (506,8), ending point (501,-9) Slope is 3.4 First v tested was -2.5, value was 1.002 Second v tested was -1.875 value was .991... used that one.

Finals found as finalX = 4.125 finalY = 2.025... clearly incorrect. Any help would be appreciated... I am stumped on this one!

Edit: Removed some unused variables from earlier attempts and also I should mention that the reason I am casting my xMove and yMove to int is that while they are doubles, whenever they are used they are casted.

Edit 2: The formula I am using for value is taken from this page, top answer... they explain it pretty well over there. https://math.stackexchange.com/questions/76457/check-if-a-point-is-within-an-ellipse


Solution

  • Assuming that only finalY is 'clearly incorrect', since the rest looks fine. You're using 'run' for y where you should be using 'rise'.

    else if (v - run > 0) {
        finalX = v - run + 1;
        finalY = v * slope - run + slope;<--- THIS LINE
        }