0
votes

I have a project in which I want to make a game that uses Asteroids-style ships in order to demonstrate AI pathfinding and steering behaviors.

The object stores values for the position the centroid of the triangle (Otherwise the player's position) and the ships' orientation in degrees, then calculates the position of the three vertices like so:

A is the nose of the triangle. When the the orientation is 0 degrees, the ship's nose sits on the X-axis offset by SIZE, which detemines the size of the ship which is equal to the radius of its bounding circle.

Vertices B and C are rotated from the position of A 120 and 240 degrees respecively, then the program draws line segments between each vertex.

When I start the program, this works beautifully, and my bounding circle, orientation vector, and ship look how I expect them to.

However, I implemented a control such that angle is incremented and decremented with the left and right arrow keys. This control has been tested and proven to work as desired. When this happens, the orientation vector adjusts accordingly, and the ship rotates... but only sort of. The points immediately move in to the center of the mass until they collapse on the center and disappear forever, regardless of which direction I rotate in.

//Convert degrees into radians
float Ship::convert(float degrees){
    return degrees*(PI/180);
}

//Rotation X-Coord
int Ship::rotateX(int x, int y, float degrees){
    return (x*cos(convert(degrees)))-(y*sin(convert(degrees)));
}

//Rotate Y-Coord
int Ship::rotateY(int x, int y, float degrees){
    return x*sin(convert(degrees))+y*cos(convert(degrees));
}

//Rotate the Ship
void Ship::rotateShip(float degrees){
    vertA [0]=rotateX(vertA [0], vertA [1], degrees);
    vertA [1]=rotateY(vertA [0], vertA [1], degrees);
    vertB [0]=rotateX(vertB [0], vertB [1], degrees);
    vertB [1]=rotateY(vertB [0], vertB [1], degrees);
    vertC [0]=rotateX(vertC [0], vertC [1], degrees);
    vertC [1]=rotateY(vertC [0], vertC [1], degrees);
}

The rotate functions work fine, but I can't be sure that rotating the Ship is working. It seems that it should- the vert variables are arrays that store the X and Y coord of that vertex. If I rotate each vertex by the orientation angle of the ship, it should in theory spin the triangle on its center, right?

The verts are all calibrated about the origin, and the drawShip() function in the Game object takes those coords and adds the playerX and playerY to translate the fully drawn ship to the position of the player. So essentially, translating it to the origin, rotating it, and translating it back to the position of the player.

If it helps, I will include the relevant functions from the Game Object. In this code, psp is the Ship object. Draw ship takes all the parameters of the ship object and should work, but I'm getting unwanted results.

//Draw Ship
void Game::drawShip1(int shipX, int shipY, int vel, int alpha, int size, int* vertA, int* vertB, int* vertC, int r, int g, int b){
    //Draw a bounding circle
    drawCircle(shipX, shipY, size, 0, 255, 255);
    //Draw the ship by connecting vertices A, B, and C
    //Segment AB
    drawLine(shipX+vertA[0], shipY+vertA[1], shipX+vertB [0], shipY+vertB [1], r, g, b);
    //Segment AC
    drawLine(shipX+vertA[0], shipY+vertA[1], shipX+vertC [0], shipY+vertC [1], r, g, b);
    //Segment BC
    drawLine(shipX+vertB[0], shipY+vertB[1], shipX+vertC [0], shipY+vertC [1], r, g, b);

}


void Game::ComposeFrame()
{
    float pAlpha=psp.getAlpha();
    if(kbd.LeftIsPressed()){
        pAlpha-=1;
        psp.setAlpha(pAlpha);
        psp.rotateShip(psp.getAlpha());
    }
    if(kbd.RightIsPressed()){
        pAlpha+=1;
        psp.setAlpha(pAlpha);
        psp.rotateShip(psp.getAlpha());
    }
    //Draw Playership
    drawShip1(psp.getX(), psp.getY(), psp.getV(), psp.getAlpha(), psp.getSize(), psp.getVertA(), psp.getVertB(), psp.getVertC(), psp.getR(), psp.getG(), psp.getB());
    drawLine(psp.getX(), psp.getY(), psp.getX()+psp.rotateX(0+psp.getSize(), 0, psp.getAlpha()), psp.getY()+psp.rotateY(0+psp.getSize(), 0, psp.getAlpha()), psp.getR(), psp.getG(), psp.getB());
}
1
Start by modifying rotateX and rotateY. They assume rotation around (0,0). Add a "center point" to their parameters instead.Drew Dormann

1 Answers

0
votes

I see several problems in your code which might add up to the result you are seeing.

The first thing is that you handle coordinates as integers. Due to this, decimal places get cut off and the value gets smaller and smaller. Use float or even double.

The second thing is that the rotation is applied in two steps. The first step (calculating the x coordinate) is correct. However, the second step (calculating the y coordinate) is errornous. You use the new x-coordinate, but should provide the old one. You should implement a method that rotates the complete vector and not part of them, anyway. Why don't you use the DirectX maths functions?