Reputation: 13
First post, so I'll try to be as clear as I can. Basically, what I'm trying to do is create a little game, where you have a ship, and you can shoot bullets from it. The ship rotates accordingly to the player's deltaX and deltaY using a tangent formula. I use a standard game loop like this one:
public void run() {
long lastTime = System.nanoTime();
double amountOfTicks = 60.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
long timer = System.currentTimeMillis();
@SuppressWarnings("unused")
int frames = 0;
while(running){
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >=1){
tick();
delta--;
}
if(running)
repaint();
frames++;
if(System.currentTimeMillis() - timer > 1000)
{
timer += 1000;
frames = 0;
}
}
stop();
}
My "game" runs on a child of a JPanel, a class called Board. In the loop, I call the methods tick(), which updates the info, and repaint(), that works as a render method. This is my paintComponent(Graphics g) method:
public void paintComponent(Graphics g) {
//This is for background
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.black);
g2d.fill(new Rectangle(0, 0, Constants.width, Constants.height));
//This is where actual game rendering occurs
handler.render(g);
g.dispose();
}
As can be seen, I dont render everything on my Board class. I do so on my handler. This is how I deal with the handler:
public void render(Graphics g) {
for (int i = 0; i < handlerList.size(); i++) {
//handlerList is a LinkedList
handlerList.get(i).render(g);
}
}
The LinkedList handlerList contains Entities. Entities is an abstract class, which is parent of Creature, which is parent of Player and Bullet. This is the code for the rendering of a Player instance:
public void render(Graphics g) {
float centerX = x + (width / 2);
float centerY = y + (height / 2);
double theta = findAngle(deltaX, deltaY);
Graphics2D g2d = (Graphics2D) g;
if(!stopped) g2d.rotate(theta, centerX, centerY);
else g2d.rotate(stoppedTheta, centerX, centerY);
g2d.drawImage(shipImage, (int)x, (int)y, (int)width, (int)height, null);
}
There is a boolean "stopped" which keeps track of the objects condition. I use Graphics2D instead of Graphics due to the fact that I wanna be able to rotate my ship.
Here's the code for the bullet's rendering:
public void render(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.yellow);
g2d.fillOval((int)x, (int)y, (int)width, (int)height);
}
It looks right, as far as I'm aware. Whenever I don't have a bullet on, the game runs fine, as you can see in this GIF: DISCLAIMER: Sorry for low quality and the watermark, I've just formatted the computer and havent had time to install proper stuff....
When I add a bullet this happens:
The x and y position of the bullet doesn't change, but the bullet rotates with the ship. I'm assuming it has something to do with the misuse of the "dispose()" method, but I'm not sure what can be done to fix it.
Thank you in advance.
Upvotes: 1
Views: 43
Reputation: 347274
dispose
on a Graphics
context you did not explicitly create (or snapshot with create
), this can cause issues further down the rendering pipeline. Graphics
is a shared context, so you need to be mindful of the changes you make to it and undo any "significant" changes you make, especially transformationsIf it was me, I'd create a snapshot of the Graphics
context before each call to render
and the dispose
of it after, for example
public void render(Graphics g) {
for (int i = 0; i < handlerList.size(); i++) {
//handlerList is a LinkedList
Graphics2D g2d = (Graphics2D)g.create();
handlerList.get(i).render(g2d);
g2d.dispose();
}
}
This ensures that what ever changes that render
makes to the Graphics
context are undone before the next element is rendered
If the changes are compounding, then I'd make the snapshot before the start of the loop and dispose
of it after it.
In either case, it means you control the changes been made and how they affect other elements down the line.
Also, remember, transformations are compounding
Upvotes: 1