0

I am making a little asteroid shooter game for fun, and I am running into some problems. I have it set up so when you press a right or left arrow, the space ship rotates. This works well, but the issue is that it is also rotating the bullets after they have been shot. The bullets are supposed to travel straight, so I do not want to rotation to apply to the bullets.

****Updated post under this****

I have a basic JPanel setup in a JFrame, in my case they are set as 600x600 for size.

I have a ship object that is being used as the users spacecraft that can be rotated. I created it using this code:

public class Ship
{
private int rotation;
private int[] xList = {310, 300, 305};
private int[] yList = {310, 310, 300};

public Ship(int rotation)
{
    this.rotation = rotation;
}

public void draw(Graphics g)
{
    Graphics2D g2d = (Graphics2D) g.create();
    g.setColor(Color.WHITE);
    g2d.rotate(Math.toRadians(this.rotation), Main.WIDTH/2 + 5, Main.HEIGHT/2 + 5);
    g2d.drawPolygon(xList, yList, 3);
    g2d.drawLine(305, 300, 305, 295);

    g2d.dispose();
}

public int getRotation() {
    return rotation;
}

public void setRotation(int rotation) {
    this.rotation = rotation;
}

That class also has the draw method that is what I am using to draw the ship and rotate it. I am trying to use g.create() and g2d.dispose() to only rotate the ship object, but my issue is when I add those bits of code, the ship does not rendered on the screen.

I also have a bullet class that is being used to create the bullet objects

public class Bullet implements Runnable
{
private int x;
private int y;
private int xSpeed;
private int ySpeed;

public Bullet(int x, int y, int xSpeed, int ySpeed)
{
    this.x = x;
    this.y = y;
    this.xSpeed = xSpeed;
    this.ySpeed = ySpeed;
}

public void draw(Graphics g)
{
    g.drawOval(this.x, this.y, 5, 5);
}

public void move()
{
    this.x += this.xSpeed;
    this.y += this.ySpeed;
}

@Override
public void run() {
    try
    {
        while(true)
        {
            move();
            Thread.sleep(60);
        }
    }
    catch(Exception e)
    {
        System.err.println(e.getMessage());
    }
}

I have some getters and setters in there that I did not include, but those are pretty self explanatory and likely do not pertain to the problem.

Finally, I have my main class. This is being used to draw all of the objects on the screen and to take in user input (being used for ship rotation and spawning of bullet objects)

public class Main extends JFrame implements KeyListener
{
private static Screen screen;
private static int WIDTH = 600;
private static int HEIGHT = 600;
private ArrayList<Bullet> bullets = new ArrayList<>();

public static Ship ship;

public Main()
{
    ship = new Ship(0);
    //basic code left out here that sets up JFrame and adds the JPanel

    addKeyListener(this);
}

@Override
public void paint(Graphics g)
{
    super.paint(g);
    ship.draw(g);

    for(int i = 0; i < bullets.size(); i++)
    {
        bullets.get(i).draw(g);
    }

    repaint();
}

public static void main(String[] args)
{
    Main m = new Main();
    ship = new Ship(WIDTH/2, HEIGHT/2, 0);
}

@Override
public void keyPressed(KeyEvent e) {

    if(e.getKeyCode() == KeyEvent.VK_SPACE)
    {
        bullets.add(new Bullet(WIDTH/2 + 2, HEIGHT/2 + 2, 0, -5, true));
        for (int i = 0; i < bullets.size(); i++)
        {
            new Thread(bullets.get(i)).start();
        }

        for(int i = 0; i < bullets.size(); i++)
        {
            if(bullets.get(i).getX() > WIDTH || bullets.get(i).getX() < 0
            || bullets.get(i).getY() > HEIGHT || bullets.get(i).getY() < 0)
            {
                bullets.remove(i);
            }
        }
    }
}

}

At the bottom of my Main class I have the KeyEvent stuff that is being used to spawn bullets and to rotate the ship (I left the rotation code out because it is just using the left and right arrows to increase/decrease the rotation value in the ship class)

My issue was that the rotation in the ship class was rotating all the objects, including the bullets, but now my issue is once I added the .create() and .dispose(), it stopped rendering my ship. It did, however, stop the rotation of the bullets.

brent_mb
  • 337
  • 1
  • 2
  • 14
  • Make a copy of your Graphics/Graphics2D object, rotate with the copy, then dispose of the copy (not the original) when done. That's it. – Hovercraft Full Of Eels May 12 '19 at 22:32
  • `Graphics2D gg = (Graphics2D) g.create();` – Hovercraft Full Of Eels May 12 '19 at 22:34
  • 1
    Yes, this is how "transformations" work. You "transform" the context and start drawing, everything painted after the transformation is applied is then transformed accordingly. As Hovercraft has said. You should first make a copy of the context, transform it, paint what you need then dispose of it. This will leave the original context in it's original state and allow you to continue painting normally – MadProgrammer May 12 '19 at 22:34
  • @HovercraftFullOfEels I have tried this, but whenever I do the `.create()` and then later do `.dispose()`, it does not draw the ship at all. It renders nothing – brent_mb May 12 '19 at 22:36
  • 1
    @brent_mb: then you need to show us what you're doing wrong. Specifically, consider posting a valid [mcve] with your question. Check out the link as it will explain what I'm requesting (not a snippet, and not the whole program) and how it can help you get a decent answer. – Hovercraft Full Of Eels May 12 '19 at 22:37
  • 1
    @brent_mb Considering the large number of work examples which demonstrate the use of `create` and `dispose`, I doubt the issue is with the use of that functionality and instead in how you are using it (or more specifically, the way you are transforming your context) – MadProgrammer May 12 '19 at 22:39
  • Other issues -- you almost never want to override paint but rather the `protected void paintComponent(Graphics g)` method of a JPanel or JComponent, and you *definitely* never want to call `repaint` from within any painting method. That will give you a terrible and uncontrollable animation. – Hovercraft Full Of Eels May 12 '19 at 22:39
  • @HovercraftFullOfEels I appreciate the thorough help/advice. I am very new to visual programming, so anything that deals with JPanel or JFrame, I am still learning. I updated the question, specifically the `ship.draw` method to show how I have been using the `.create()` and `.dispose()` – brent_mb May 12 '19 at 22:44
  • Please read or re-read the [MCVE](https://stackoverflow.com/help/mcve) link that I gave you. Again, the link will explain *why* it is important for you to create this. Mainly it 1) ensures that you post the offending code -- your assumptions on which code is offending may be wrong, and 2) it allows us to easily reproduce your problem. Please comment back to both myself and @MadProgrammer when done. – Hovercraft Full Of Eels May 12 '19 at 22:48
  • `g2d.rotate(Math.toRadians(this.rotation), this.x + 5, this.y + 5)` is anchoring the rotation at the `x`/`y` position of the object, this could rotate the object beyond the bounds of the graphics context (which is a common issue), but this is just guess work – MadProgrammer May 12 '19 at 22:51
  • @MadProgrammer That rotates the `ship` object at the objects center point, so that should not be the problem. At least, before I added the `.create()` and `.dispose()` it was rotating properly in the center of the screen. I have updated my question as per question of @HovercraftFullOfEels – brent_mb May 12 '19 at 23:03
  • @HovercraftFullOfEels please let me know if I updated the question properly. I feel like i may have added too much information, but I tried to narrow it down as I felt appropriate. – brent_mb May 12 '19 at 23:03
  • I'm afraid that I still can't compile nor run your code as it is incomplete -- it requires a Screen class, it calls constructors that don't exist in the posted code, it implements interfaces without implementing their methods... Again the link will explain what you need to do, but usually this involves creating a new and small program, one that destills the essential functions necessary to demonstrate the problem, one with enough code to compile and run by us without needing image files, databases, other classes,.... – Hovercraft Full Of Eels May 13 '19 at 00:36
  • .... It can contain a few small classes, usually only one public class with the main method. It can use images that are freely available online, but again it needs to be small but runnable. – Hovercraft Full Of Eels May 13 '19 at 00:37
  • @HovercraftFullOfEels The problem was I had `g.setColor` instead of `g2d.setColor` in my `ship` class – brent_mb May 13 '19 at 01:04

0 Answers0