Graphics2D and Double Buffering hating each other in Java
5 replies, posted
Call for help to fix this:
What this is supposed to do:
Have Mr Blockman there (the black square), and his arm / gun (the red square) shoot bullets in the direction of the mouse and have the arm / gun point at the mouse. It does work, but has this pretty weird but that doesn't happen if I turn DB off (but then there's horrible frame tearing / flickering).
In this picture the first bullet fired is fine, but you can see the second bullet has a little bit of a line coming off it
[IMG]http://i119.photobucket.com/albums/o145/thrawn2787/help1.png?t=1270344038[/IMG]
Firing alot of bullets causing something like this:
[IMG]http://i119.photobucket.com/albums/o145/thrawn2787/help2.png?t=1270344261[/IMG]
Moving while a bullet is fired causes this:
[IMG]http://i119.photobucket.com/albums/o145/thrawn2787/help3.png?t=1270344298[/IMG]
[IMG]http://i119.photobucket.com/albums/o145/thrawn2787/help4.png?t=1270344348[/IMG]
^ Clearly the weird glitched thing is cut 90 degrees
Fyi it's an applet. Code, sorry if it's hard to follow, wasn't really expecting to need help:
[code]import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Panel;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Vector;
public class MoveAndShootTest extends Applet implements MouseMotionListener, KeyListener, MouseListener {
Rectangle2D arm, body;
int mouseX, mouseY;
int armX = 25, armY = 370, bodyX = 0, bodyY = 350;
Graphics dblBufGraphics;
Image dblBufImage;
public void init(){
addKeyListener(this);
addMouseListener(this);
this.setSize(800,400);
addMouseMotionListener(this);
Panel p = new Panel();
arm = new Rectangle2D.Double(0,0,10,10);
body = new Rectangle2D.Double(0,0,50,50);
}
public void update(Graphics g) {
if (dblBufImage == null) {
dblBufImage = createImage(this.getSize().width, this.getSize().height);
dblBufGraphics = dblBufImage.getGraphics();
}
dblBufGraphics.setColor(getBackground());
dblBufGraphics.fillRect(0, 0, this.getSize().width, this.getSize().height);
dblBufGraphics.setColor(getForeground());
paint(dblBufGraphics);
g.drawImage(dblBufImage, 0, 0, this);
}
RotateOnAxis rotate = new RotateOnAxis(mouseX, mouseY, armX, armY);
RotateOnAxis vector;
ArrayList<Bullet> bullets = new ArrayList();
public void paint(Graphics g){
g.setColor(Color.white);
g.fillRect(0, 0, 800, 800);
Graphics2D g2d = (Graphics2D)g;
AffineTransform at = new AffineTransform();
g2d.setTransform(at);
g.setColor(Color.black);
g2d.translate(bodyX, bodyY);
g2d.fill(body);
g2d.setTransform(at);
g2d.setColor(Color.red);
g2d.translate(armX, armY);
rotate = new RotateOnAxis(mouseX, mouseY, armX, armY);
g2d.rotate(rotate.radians());
g2d.fill(arm);
g2d.setTransform(at);
if(bullets.size() >= 1){
for(int i = 0; i < bullets.size(); i++){
bullets.get(i).setXRate(5);
bullets.get(i).run();
bullets.get(i).display(g);
if(bullets.get(i).getX() >= 800){
bullets.remove(i);
}
}
}
try{
Thread.sleep(25);
}catch (InterruptedException e) {
System.err.println("sleep exception - design falut\n");
}
repaint();
}
@Override
public void mouseDragged(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
mouseX = e.getX();
mouseY = e.getY();
rotate.setMX(mouseX);
rotate.setMY(mouseY);
repaint();
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if(e.getKeyCode() == e.VK_D){
bodyX += 5;
armX += 5;
repaint();
}
if(e.getKeyCode() == e.VK_A){
bodyX -= 5;
armX -= 5;
repaint();
}
if(e.getKeyCode() == e.VK_W){
bodyY -= 5;
armY -= 5;
repaint();
}
if(e.getKeyCode() == e.VK_S){
bodyX += 5;
armX += 5;
repaint();
}
}
@Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
System.out.println(armX);
bullets.add(new Bullet(armX, armY, mouseX, mouseY, 0.01));
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
}
[/code][code]import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
public class Bullet extends Thread {
Image img;
int originX = 0, originY = 0, mouseX = 0, mouseY = 0, x = 0, y = 0,
xRate = 0;
boolean isImg;
String imgPath;
double radians, spray = 0;
// Constructor for a bullet that uses an image
public Bullet(String imgPath, int originX, int originY, int mouseX, int mouseY, double spray) {
this.originX = originX;
this.originY = originY;
this.mouseX = mouseX;
this.mouseY = mouseY;
this.imgPath = imgPath;
isImg = true;
x = 0;
y = originY;
this.spray = spray;
radians = getRadians();
}
// Contructor for a bullet with no image. use only for testing
public Bullet(int originX, int originY, int mouseX, int mouseY, double spray) {
this.originX = originX;
this.originY = originY;
this.mouseX = mouseX;
this.mouseY = mouseY;
isImg = false;
x = 0;
y = originY;
this.spray = spray;
radians = getRadians();
System.out.println(x);
}
// Gets the radians that the bullet should be drawn upon.
// Is called in each constructor so that this is only called once
public double getRadians() {
int n = (int) (Math.random() * 2);
double timesPercent = 0;
if(n == 1){
timesPercent = Math.random() * spray;
}
if(n == 0){
timesPercent = -1* (Math.random() * spray);
}
double adder = (Math.PI / 2) * timesPercent;
Vector2D vec = new Vector2D(mouseX, mouseY, originX, originY);
double radians = adder + vec.radians();
return radians;
}
Rectangle2D rect;
public void display(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
AffineTransform at = new AffineTransform();
g2d.setTransform(at);
// Will perform this if an image isn't used for the bullet
if (isImg == false) {
g2d.setColor(Color.yellow);
rect = new Rectangle2D.Double(x, 0, 10, 10);
g2d.translate(originX, originY);
g2d.rotate(radians);
g2d.fill(rect);
}
if (isImg == true) {
g2d.translate(originX, originY);
g2d.rotate(radians);
//g2d.drawImage();
}
}
public void setX(int i) {
x = i;
}
public int getX() {
return x;
}
public void move() {
x += xRate;
}
public void setXRate(int i) {
xRate = i;
}
public void run() {
this.move();
}
}
[/code][code]import java.util.Vector;
public class Vector2D extends Vector {
int mouseX, mouseY, originX, originY;
public Vector2D(int mouseX, int mouseY, int originX, int originY){
this.mouseX = mouseX;
this.mouseY = mouseY;
this.originX = originX;
this.originY = originY;
}
// Returns the amount of radians the object should rotate
public double radians(){
double xDif = mouseX - originX;
double yDif = originY - mouseY;
yDif *= -1;
double hyp = Math.sqrt((Math.pow(xDif,2) + Math.pow(yDif, 2)));
double radians = Math.atan(yDif/xDif);
if(mouseX - originX < 0 || (mouseY - originY < 0 && mouseX - originX < 0 )){
radians -= Math.PI;
}
return radians;
}
}
[/code]And the last class
[code]import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
public class RotateOnAxis {
int mouseX, mouseY, originX, originY;
public RotateOnAxis(int mouseX, int mouseY, int originX, int originY){
this.mouseX = mouseX;
this.mouseY = mouseY;
this.originX = originX;
this.originY = originY;
}
// Returns the amount of radians the object should rotate
public double radians(){
double xDif = mouseX - originX;
double yDif = originY - mouseY;
yDif *= -1;
double hyp = Math.sqrt((Math.pow(xDif,2) + Math.pow(yDif, 2)));
double radians = Math.atan(yDif/xDif);
if(mouseX - originX < 0 || (mouseY - originY < 0 && mouseX - originX < 0 )){
radians -= Math.PI;
}
return radians;
}
// Sets the Xcoordinates of the mouse
public void setMX(int mouseX){
this.mouseX = mouseX;
}
// Sets the Ycoordinates of the mouse
public void setMY(int mouseY){
this.mouseY = mouseY;
}
}
[/code]Edit:
Fixed it by putting these two lines of code after drawing the bullet
g2d.rotate(-1 *radians);
g2d.translate(-1 * originX,-1 * originY);
Don't know why that took me so long to figure out. Turns out DB didn't hate it hehehe
[img]http://i119.photobucket.com/albums/o145/thrawn2787/lol-2.png?t=1270351088[/img]
dakka dakka dakka
Why does Bullet extend Thread?
A thread for each bullet? That will make your game butt slow. Here is a link to garrys take on threading. [url]http://www.garry.tv/?p=1397[/url] .
[QUOTE=Adil;21210573]A thread for each bullet? That will make your game butt slow. Here is a link to garrys take on threading. [URL]http://www.garry.tv/?p=1397[/URL] .[/QUOTE]
Thanks for the tip, I'll look into that once I start getting performace issues :P
Also does anyone have any idea how to have a MouseListener listen for the mouse to be moved, pressed, and released at the same time? Right now my guy can't turn (he points twards the mouse) and fire, or fire and turn. He can walk around and shoot so long as you don't move the mouse
[editline]08:47PM[/editline]
Basically meaning you have to stop the mouse to shoot, which will be a pain once there's enemies to shoot at
Look into the MouseMotionListener. It has mouseMoved and mouseDragged.
Yeah I am an idiot for forgetting mousedragged, but I had that epiphany 8 hours ago :P
Now time to code a rocket launcher and implement my particle editor system I just made... :|
Sorry, you need to Log In to post a reply to this thread.