Search code examples
javaprocessingangledirection

Make a shape go in an angular direction


I'm making Asteroids and I was trying to make the bullet mechanic. The bullet should go in the ship facing direction (an angle), but I don't know how to make the bullet go into that angular direction. Instead it goes up, down or right/left. The code I tried and does not work:

class Bullet
{
    float x,y,vx,vy;
    Bullet()
    {
        rectMode(CENTER);
        x = 0;
        y = 0;
        vx = 100 * cos(ang);
        vy = 100 * sin(ang);
    }

    void draw2()
    {
        vx = 100 * cos(ang);
        vy = 100 * sin(ang);
        x += vx;
        y += vy;
        pushMatrix();
        translate(width/2,height/2);
        translate(5,0);
        rotate(ang);
        rect(x,y,10,10);
        popMatrix();
    }
}

The rest of the code:

float ang = 0;
boolean spara = false;
Bullet b;

void setup()
{
    size(800,600);
    rectMode(CENTER);
    frameRate(60);
    asteroidi = new Asteroide[10];
    b = new Bullet();
}

void update()
{

}

void draw()
{
    update();
    background(200,200,200);
    fill(255);
    pushMatrix();
    translate(width/2,height/2);
    translate(25,0);
    rotate(ang);
    rect(0,0,50,50);
    popMatrix();
    if(spara)
        b.draw2();
}

void keyPressed()
{
    switch (keyCode)
    {
      case RIGHT:
          ang += 0.1;
          break;
      case LEFT:
          ang -= 0.1;
          break;
      case 32:
          if (spara) spara = false;
          if (!spara); spara = true;

          break;
    }
}

I call the draw2() function, when the boolean spara is true.


Solution

  • You've to do the following:

    • draw the bullet rectangle in that way, that it's center is at (0, 0):
      rect(0, 0, 10, 10);

    • rotate rectangle in direction of move:
      rotate(ang);

    • translate rectangle to new position:
      translate(x, y);

    Since the operations like translate and rotate define a new matrix and multiply the current matrix by the new matrix, the matrix operations have to be done in reverse order.

    Note that the angle to sin() and cos() has to be set in radians ratherr than degrees.
    By the way, are you sure that a velocity of 100 is not far to much?

    class Bullet
    {
        float x, y, v, ang;
        Bullet(float x, float y, float v, float ang)
        {
            this.x = x;
            this.y = y;
            this.v = v;
            this.ang = ang;
        }
    
        void update() {
            x += v * cos(ang);
            y += v * sin(ang);
        }
    
        void draw()
        {
            pushMatrix();
    
            // transalte rectangle to new position
            translate(x, y);
    
            // rotate rectangle in direction of move
            rotate(ang);
    
            // draw rectangle around center
            rect(0, 0, 10, 10);
    
            popMatrix();
        }
    }
    

    Manage the bullets in an ArrayList and spawn (add) a new bullet when SPACE is pressed:

    ArrayList<Bullet> bullets = new ArrayList<Bullet>();
    
    float ang = 0.7;
    void keyPressed()
    {
        switch (keyCode)
        {
            case RIGHT:
                ang += 0.1;
                break;
            case LEFT:
                ang -= 0.1;
                break;
            case 32:
                bullets.add(new Bullet(width/2, height/2, 2, ang));
                break;
        }
    }
    

    Update (move) all the bullets in the array in update. Keep just the bullets which are still in the window. Store the bullets which are in the window to a new array and replace the array of bullets by the new array:

    void update()
    {
        // array for bullets which ar still in window
        ArrayList<Bullet> bulletsInWindow = new ArrayList<Bullet>();
    
        for( int i = 0; i < bullets.size(); ++i ) {
            Bullet b = bullets.get(i);
    
            // move bullet
            b.update();
    
            // evaluate eif bullet is still in window
            if ( b.x >= 0 && b.y >= 0 && b.x <= width && b.y <= height ) {
                bulletsInWindow.add(b);
            }
        }
    
        // keep the bullets which are still in the window
        bullets = bulletsInWindow;
    }
    

    Draw the bullets in a loop in draw():

    void draw() 
    {
        update();
    
        background(200,200,200);
        rectMode(CENTER);
        fill(255);
    
        for( int i = 0; i < bullets.size(); ++i ) {
            Bullet b = bullets.get(i);
            b.draw();
        }
    
        pushMatrix();
        translate(width/2,height/2);
        rotate(ang);
        rect(0, 0, 50, 50);
        popMatrix();
    }