Jon
Jon

Reputation: 8021

Calculate points around a circle in android

I'm programming a game in android where an enemy ship needs to fire in a star pattern around itself. Basically, for any X number of shots I set the enemy ship to fire, I want it to divide 360 degrees around itself by the number of shots and fire the shots off at exactly equilateral angles. So, 3 shots would be fired off with the first shot at 360 degrees, the second shot at 120 degrees and the third shot at 240 degrees. 4 shots would be 360,90,180,270 and so on. Then each shot will travel outwards in a diagonal line until it hits the edge of the screen (or something else on the way). So far so good. Here is my code - I'm obviously doing something wrong, because although four shots will fire in four equal directions (north, south, east and west), 3 shots or 6 shots or 8 shots (etc) will fire in the wrong directions. The angles just aren't correct. I'd appreciate any help on this as I've been struggling with it for quite a while now. In the below example iShotNumber is the number of shots being fired in a salvo. Distance is the distance in pixels the shot will travel in one 'tick'. The shots are added around the circumference of the ship in an array, which is then run through every 'tick' to advance the shots one more step outwards.

Logic for drawing the shots around the circumference of the ship:

public void addShot(Context ctx, int iShotNumber, float distance) {



for (int iShot=1; iShot<=iShotNumber; iShot++) {

double 
        dAngle =0, //angle of the shot
        dCosFactor=0, //factor on the x-axis
        dSinFactor=0; //factor on the y-axis

        float 
        fNewX = 0, //new position on the x-axis
        fNewY =0; //new position on the y-axis

        dAngle = 360/iShotNumber;
        dAngle = dAngle*iShot;

        if (iShotNumber == 1) {dAngle=180;} //if there's only one shot then fire straight down

        if (dAngle!=360 && dAngle!=180) //if its 360 or 180 then fire straight up or straight down - no need for X
        {
            fNewX = (float) (getShipRadius()*Math.cos(Math.toRadians(dAngle)));

            if (dAngle<=180) {fNewX=fNewX+distance;} else {fNewX=fNewX-distance;}

            fNewX=fNewX+getXLocation();

        }
        else {fNewX=getXLocation();}        

        if (dAngle!=90 && dAngle !=270) //if its 90 or 270 then fire straight right or straight left - no need for Y
        {
            fNewY = (float) (getShipRadius()*Math.sin(Math.toRadians(dAngle)));

            if (dAngle<=90||dAngle>=270) {fNewY=fNewY+distance;} else {fNewY=fNewY-distance;}

            fNewY=fNewY+getYLocation();
        }
        else {fNewY=getYLocation();}


        if (dAngle>=90&&dAngle<=180) {dSinFactor = Math.sin(Math.toRadians(dAngle)-90); dCosFactor = Math.cos(Math.toRadians(dAngle)-90);}
        else if (dAngle>=181&&dAngle<=270) {dSinFactor = Math.sin(Math.toRadians(dAngle)-180); dCosFactor = Math.cos(Math.toRadians(dAngle)-180);}
        else if (dAngle>=271&&dAngle<360) {dSinFactor = Math.sin(Math.toRadians(dAngle)-270); dCosFactor = Math.cos(Math.toRadians(dAngle)-270);}
        else if (dAngle==360) {dSinFactor = Math.sin(Math.toRadians(dAngle)-271); dCosFactor = Math.cos(Math.toRadians(dAngle)-271);}
        else {dSinFactor = Math.sin(Math.toRadians(dAngle)); dCosFactor = Math.cos(Math.toRadians(dAngle));}

        //dSinFactor = Math.sin(Math.toRadians(dAngle)); dCosFactor = Math.cos(Math.toRadians(dAngle));

        //if (dSinFactor<=0){dSinFactor = dSinFactor*-1;} //neutralize negative angles on upshots
        //if (dCosFactor<=0){dCosFactor = dCosFactor*-1;} //neutralize negative angles on rightshots

        if ( MainActivity.iDebugLevel >= 1) {Log.d("EnemyShip-addShot","add shot number " +String.valueOf(iShot) 
                + " with dAngle " +String.valueOf(dAngle) +" cosan was " +String.valueOf(dCosFactor) +" sinan was " +String.valueOf(dSinFactor));}
        if ( MainActivity.iDebugLevel >= 2) {Log.d("EnemyShip-addShot","add shot number " +String.valueOf(iShot) + " with fNewX " +String.valueOf(fNewX));}
        if ( MainActivity.iDebugLevel >= 2) {Log.d("EnemyShip-addShot","add shot number " +String.valueOf(iShot) + " with fNewY " +String.valueOf(fNewY));}

        if (dAngle==90||dAngle==270) {newShot = new ShotClass(ctx, fNewX, fNewY, dCosFactor /*x-angle*/, 0 /*y-angle*/);} //fire straight to the right or left
        else if (dAngle==360||dAngle==180) {newShot = new ShotClass(ctx, fNewX, fNewY, 0 /*x-angle*/, dSinFactor /*y-angle*/);} //fire straight up or down
        else {newShot = new ShotClass(ctx, fNewX, fNewY, dCosFactor /*x-angle*/, dSinFactor /*y-angle*/);} //fire at an angle

        if ( dAngle <= 90 || dAngle >= 270) {
            newShot.setShotGoingUp(true);
        }
        else
        {
            newShot.setShotGoingUp(false);
        }

        if ( dAngle <= 180 ) {
            newShot.setShotGoingRight(true);
        }
        else
        {
            newShot.setShotGoingRight(false);
        }

        if ( MainActivity.iDebugLevel >= 1) {Log.d("EnemyShip-addShot","add shot number " +String.valueOf(iShot) + " with goingup " +String.valueOf(newShot.getShotGoingUp()) +" with goingright " +String.valueOf(newShot.getShotGoingRight()));}

        arShots.add(newShot);
        if ( MainActivity.iDebugLevel >= 2) {Log.d("EnemyShip-addShot","add shot number " +String.valueOf(iShot) + " with position " +String.valueOf(getXLocation()) +" " +String.valueOf(getYLocation()) +" firing params: " +String.valueOf(dCosFactor) +" " +String.valueOf(dSinFactor) +" angle was " +String.valueOf(dAngle));}
    }

Logic for sending the shots out in a diagonal line:

        inpDistance = inpDistance * .2f; //slow down the shot to one fifth speed

        for (int iShotInTheSequence=1;iShotInTheSequence<=inpNumberShots;iShotInTheSequence++) {

            fFactor = (float) (inpDistance * getYFiringAngle());
            if ( getShotGoingUp() ) { //shot is going up

                fYLocation = fYLocation - fFactor;
            } //shot is going up
            else {//shot is going down

                fYLocation = fYLocation + fFactor; 
            } //shot is going down

            fFactor = (float) (inpDistance * getXFiringAngle());
            if ( getShotGoingRight() ) { //shot is going right
                fXLocation = fXLocation + fFactor;
            } //shot is going right
            else {//shot is going left
                fXLocation = fXLocation - fFactor;
            } //shot is going left


        }

Upvotes: 0

Views: 493

Answers (2)

HAL9000
HAL9000

Reputation: 3751

First error:

dAngle = 360/iShotNumber;

You want a double as a result of the division, then you cannot simply do an integer division. You should do:

dAngle = 360.0/(double)iShotNumber;

I'm checking to find other errors.

Upvotes: 1

Joni
Joni

Reputation: 111259

The trigonometric functions in most programming languages, Java included, measure the argument in radians, not degrees. There is a helper function to do the conversion, so everywhere you call sin or cos you can add a call to toRadians:

Math.cos(Math.toRadians(dAngle))

Upvotes: 3

Related Questions