Jump to content

  • Log In with Google      Sign In   
  • Create Account


[java] Double Buffer


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
9 replies to this topic

#1 BASICFreak   Members   -  Reputation: 115

Like
0Likes
Like

Posted 08 August 2010 - 05:09 PM

Okay here is the code I got thus far only been working for a few minutes, and my first time with a double buffer.
import java.io.*;
import java.net.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.*;
import java.lang.Math;
import javax.swing.JApplet;
import java.sql.*;
import javax.imageio.*;

public class HalfDoomed extends JApplet implements Runnable, ActionListener, KeyListener, MouseListener, MouseMotionListener
{
//USER types - 0=normal 1=admin 2=mod 3=member
//CHAT types - 0=all 1=private

int debug = 1;

Image background = null;
Image foreground = null;
Thread runner;
Thread chatter;
Thread fighter;
Thread walker;
String currentScreen = "login";
int XPos;
int YPos;
int loggedin = 0;

int field = 0;
String username = "";
String password = "";
String passshow = "";

@Override
public void init()
{
setSize( 800, 600 );
//Container content = getContentPane();
//content.setLayout(new GridBagLayout()); // Used to center the panel
//content.add(myGame);
addMouseListener(this);
addKeyListener(this);
addMouseMotionListener(this);
runner = new Thread(this);
runner.setPriority(10);
runner.start();
}
public void mouseClicked (MouseEvent me)
{
int got = 0;
int X=me.getX();
int Y=me.getY();

}
public void mouseDragged (MouseEvent mme)
{

}
public void mouseMoved (MouseEvent mme)
{
XPos = mme.getX();
YPos = mme.getY();
}
public void mouseEntered (MouseEvent me)
{

}
public void mousePressed (MouseEvent me)
{

}
public void mouseReleased (MouseEvent me)
{

}
public void mouseExited (MouseEvent me)
{

}
public void actionPerformed(ActionEvent e)
{

}
public void keyTyped(KeyEvent event)
{

}
public void keyPressed(KeyEvent event)
{

}
public void keyReleased(KeyEvent event)
{

}
public void run()
{
while (runner == Thread.currentThread() )
{
repaint();
try
{
Thread.sleep(1);
}
catch(InterruptedException ien)
{
}
}

}
@Override
public void paint (Graphics gg)
{
Graphics2D g = (Graphics2D)gg;
Graphics BGg;
background = null;
background = createImage(800, 600);
BGg = background.getGraphics();
//menu all screens 25 down 1024 over
screen(gg, background);
paint(BGg);
Graphics FGg;
foreground = null;
foreground = createImage(800, 600);
BGg = foreground.getGraphics();
//menu all screens 25 down 1024 over
game(gg, foreground);
paint(BGg);
g.drawImage(background, 0, 0, this);
g.drawImage(foreground, 0, 0, this);
}
@Override
public void update(Graphics g)
{
paint(g);
}
void game(Graphics g, Image gg)
{
if(loggedin == 1)
{
g.setColor(Color.decode("0x000000"));
g.fill3DRect(0, 0, 600, 400, true);
}
}
void screen(Graphics g, Image gg)
{
if(currentScreen.equals("login"))
{
g.setColor(Color.decode("0x000000"));
g.fill3DRect(0,0,800,600,true);
g.setColor(Color.decode("0xED1C24"));
g.setFont(new Font ("Courier New", Font.PLAIN, 52));
g.drawString("Half-Doomed v.0.01 BETA", 20, 60);
g.setColor(Color.decode("0x880015"));
g.fill3DRect(18, 91, 757, 478, true);
g.setColor(Color.decode("0x000000"));
g.setFont(new Font ("Courier New", Font.BOLD, 24));
g.drawString("Username", 21, 221);
g.drawString("Password", 21, 285);
g.setColor(Color.decode("0xFFFFFF"));
g.fill3DRect(174, 199, 582, 32, true);
g.fill3DRect(174, 259, 582, 32, true);
g.setColor(Color.decode("0x000000"));
g.setFont(new Font ("Courier New", Font.PLAIN, 16));
if(field == 0)
{
g.drawString(username+"_", 180, 220);
g.drawString(passshow, 180, 280);
}
if(field == 1)
{
g.drawString(username, 180, 220);
g.drawString(passshow+"_", 180, 280);
}
g.setColor(Color.decode("0xC3C3C3"));
g.fill3DRect(310, 325, 145, 50, true);
g.setColor(Color.decode("0x000000"));
g.setFont(new Font ("Courier New", Font.BOLD, 24));
g.drawString("Log In", 335, 355);
}
if(debug == 1)
{
g.setColor(Color.decode("0x000000"));
g.setFont(new Font ("Courier New", Font.BOLD, 24));
g.drawString(XPos+", "+YPos, 40, 530);
}
}
}



The problem I am having is it takes between 2 and 5 seconds to render the image, if it wasn't going to become a game in the long run then I wouldn't mind but I would like to get at least 10FPS not .5 to .2 FPS.

So far the only way I know to speed it up is to remove the buffer, but then it flickers too much.

Can anyone tell me what I could do to speed up this process.

Just so you don't blame my PC the specs are:
2.67GHz Core2 Quad Q9400
8GB ram
NVidia 9400GT - 1GB
Windows 7 Ultimate x64 and UBUNTU 10.04 x64


Thanks in advance,
THoover

Sponsor:

#2 fastcall22   Crossbones+   -  Reputation: 3625

Like
0Likes
Like

Posted 08 August 2010 - 05:43 PM

I'm no java expert, however, if I were to guess what points in the code may be possible bottlenecks, it would probably be these things:

  1. It seems to me that you're reallocating memory for your foreground and background images, both of which are 800x600, probably allocating 1.83MB per 800x600 image per repaint. This may (or may not, depending on Java's resource-caching behavior, if any), in addition to increased memory usage, cause Java to garbage-collect quite frequently. Consider removing the two statements,foreground = null; and foreground = createImage(800, 600);, and instead use a filling method to erase the previous image.

  2. Consider using only one image and drawing the background before drawing the foreground, instead of drawing the foreground and background on separate images, then combining them. This can save you some drawing time and some memory.

  3. As with the background and foreground images, you seem to be recreating several different fonts every frame. Consider moving the fonts you use as members, as you did with the background and foreground members. This way, you can avoid recreating the fonts each frame, which may (or may not, depending on Java's resource-caching behavior, if any) save resources and time.

WW91J3ZlIGdvdCBhIHNlY3JldCBib251cyBwb2ludCE=


#3 BASICFreak   Members   -  Reputation: 115

Like
0Likes
Like

Posted 08 August 2010 - 06:40 PM

Quote:
Original post by _fastcall
I'm no java expert, however, if I were to guess what points in the code may be possible bottlenecks, it would probably be these things:

  1. It seems to me that you're reallocating memory for your foreground and background images, both of which are 800x600, probably allocating 1.83MB per 800x600 image per repaint. This may (or may not, depending on Java's resource-caching behavior, if any), in addition to increased memory usage, cause Java to garbage-collect quite frequently. Consider removing the two statements,foreground = null; and foreground = createImage(800, 600);, and instead use a filling method to erase the previous image.

  2. Consider using only one image and drawing the background before drawing the foreground, instead of drawing the foreground and background on separate images, then combining them. This can save you some drawing time and some memory.

  3. As with the background and foreground images, you seem to be recreating several different fonts every frame. Consider moving the fonts you use as members, as you did with the background and foreground members. This way, you can avoid recreating the fonts each frame, which may (or may not, depending on Java's resource-caching behavior, if any) save resources and time.


1. I Tried this and it made it slower, it was quicker to null out the image and create a new one.
2. There will be a point to this in the future, I have before done it all as one, but it became too hectic too fast.
3. I could try this but I believe that will only a few ms faster not a whole second or two (I will work on this to improve my code layout though)

#4 elFarto   Members   -  Reputation: 206

Like
0Likes
Like

Posted 09 August 2010 - 01:15 AM

I posted a reasonably fast renderer a while back here.

You should be able to use some of that.

Regards
elFarto

#5 kunos   Crossbones+   -  Reputation: 2149

Like
0Likes
Like

Posted 09 August 2010 - 01:24 AM

perhaps I am missing something here but:

public void paint (Graphics gg)
{
Graphics2D g = (Graphics2D)gg;
Graphics BGg;
background = null;
background = createImage(800, 600);
BGg = background.getGraphics();
//menu all screens 25 down 1024 over
screen(gg, background);
paint(BGg);


you're calling paint again in a recursive fashion?
I am surprised you get any output AT ALL.

I guess you want something like:

public void paint (Graphics gg)
{
Graphics2D g = (Graphics2D)gg;
Graphics BGg;
//background = null;
//background = createImage(800, 600); // NO!! PREALLOCATE THIS ONE
BGg = background.getGraphics(); // ACQUIRE THE GRAPHICS FOR THE BACKGROUND
//menu all screens 25 down 1024 over
screen(gg, background); // DO YOUR STUFF ON THE BACKGROUND
g.drawImage(background, 0, 0, this); // DRAW THE BACKGROUND

}



#6 phresnel   Members   -  Reputation: 949

Like
0Likes
Like

Posted 09 August 2010 - 01:48 AM

Quote:
Original post by Thoover
My sites:
Dr. iPhone
Dr. L33T
Dr. Computer
Half-Doomed


OT: How much do your earn for screwing search-machines and gamedev.net-users by letting three out of four of your signature-urls point to the same site, a.k.a. link-spamming or simply spammage; also because, by simply comparing the other site with the rest w.r.t. quality, they don't seem to be part of your realm but of some paying ad'der?

#7 BASICFreak   Members   -  Reputation: 115

Like
0Likes
Like

Posted 09 August 2010 - 05:27 AM

Quote:
Original post by kunos
perhaps I am missing something here but:

public void paint (Graphics gg)
{
Graphics2D g = (Graphics2D)gg;
Graphics BGg;
background = null;
background = createImage(800, 600);
BGg = background.getGraphics();
//menu all screens 25 down 1024 over
screen(gg, background);
paint(BGg);


you're calling paint again in a recursive fashion?
I am surprised you get any output AT ALL.

I guess you want something like:

public void paint (Graphics gg)
{
Graphics2D g = (Graphics2D)gg;
Graphics BGg;
//background = null;
//background = createImage(800, 600); // NO!! PREALLOCATE THIS ONE
BGg = background.getGraphics(); // ACQUIRE THE GRAPHICS FOR THE BACKGROUND
//menu all screens 25 down 1024 over
screen(gg, background); // DO YOUR STUFF ON THE BACKGROUND
g.drawImage(background, 0, 0, this); // DRAW THE BACKGROUND

}


Your exactly right, but now with the code changed:
public void paint (Graphics gg)
{
Graphics2D g = (Graphics2D)gg;
Graphics BGg;
//background = null;
//foreground = null;
background = createImage(800, 600);
//foreground = createImage(600, 400);
BGg = background.getGraphics();
//menu all screens 25 down 1024 over
screen(gg, background);
//paint(BGg);
//Graphics FGg;
//BGg = foreground.getGraphics();
//menu all screens 25 down 1024 over
//game(gg, foreground);
//paint(FGg);
g.drawImage(background, 0, 0, this);
//g.drawImage(foreground, 0, 0, this);
}

I flickers but my frame rate is somewhere between 10-15, now I have to work on a way to keep the flicker down.



Quote:
OT: How much do your earn for screwing search-machines and gamedev.net-users by letting three out of four of your signature-urls point to the same site, a.k.a. link-spamming or simply spammage; also because, by simply comparing the other site with the rest w.r.t. quality, they don't seem to be part of your realm but of some paying ad'der?

Nothing, I own halfdoomed.com and I am one of 2 admins on the doctor computer site.

#8 kunos   Crossbones+   -  Reputation: 2149

Like
0Likes
Like

Posted 09 August 2010 - 05:54 AM


change:

screen(gg, background)

to

screen(BGg, background)

and the flicker should be gone.. also, but this is a suggestion a function named "screen" means nothing. The word "screen" is an object not an action.. wouldn't it better like "renderScene"?



#9 BASICFreak   Members   -  Reputation: 115

Like
0Likes
Like

Posted 09 August 2010 - 06:23 AM

Quote:
Original post by kunos

change:

screen(gg, background)

to

screen(BGg, background)

and the flicker should be gone.. also, but this is a suggestion a function named "screen" means nothing. The word "screen" is an object not an action.. wouldn't it better like "renderScene"?


Thanks for that, it is almost flawless now.
THoover

#10 skar88   Members   -  Reputation: 100

Like
0Likes
Like

Posted 15 August 2010 - 12:01 AM

JPanels are double-buffered automatically.

If, however, you're positive that you need to double-buffer manually, it's not too complicated - you just need a Graphics2D object and an Image object. Here's a snippet of code that explains how; it looks long, but it's just heavily commented:
public void paint(Graphics g) {

//Create a temporary image with the appropriate width and height.
Image bufferedImage = createImage(100, 75);

//Create a Graphics2D object that refers to 'bufferedImage'
Graphics2D buffer = (Graphics2D) bufferedImage.getGraphics();

//Draw to the temporary image by using the name of the Graphics object that
//refers to it - in this case 'buffer'
buffer.setColor(Color.white);
buffer.fillRect(0, 0, 150, 150);
buffer.setColor(Color.black);
buffer.drawString(String.valueOf(i++), 55, 55);

//Finally, draw the temporary image to the screen using 'drawImage()'
g.drawImage(bufferedImage, 0, 0, this);
}

--------------------------
chairs| office chairs








Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS