Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (527)
Games in Android Showcase (127)
games submitted by our members
Games in WIP (594)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Double Buffering implementation  (Read 1579 times)
0 Members and 1 Guest are viewing this topic.
Offline hug0x

Senior Newbie





« Posted 2012-12-11 11:43:50 »

Hello everyone, I made a game (not finished yet), and I want to implement the double Buffering to solve the tearing/flashing effect.

Problem, all the tutorials I tried don't work because I don't use a common way to paint on the screen (I think  Cry )

What can I do (simpliest way) to implement Double Buffering ?

Sorry for my bad English, I'm French. Thanks

Here's my code (simplified) :


My Main :

             
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
   public static JFrame frame = new JFrame("The wake");


                frame.add(new Box());
      frame.setSize(LargeurFenetre+5,HauteurFenetre+27);  // les bords de la fenetre  &  l'en tete de la fenetre
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
      frame.setResizable(false);
      frame.createBufferStrategy(2);


Class Box :

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
package hugo;
import java.awt.*;
import java.awt.event.*;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;




public class Box extends JPanel implements ActionListener,MouseListener,MouseMotionListener{




   
   static Image Hero= new ImageIcon(Main.InstallPath+"hero/herocrouch.png").getImage();
        ... loading few images.
   

   float alphacomposite = 0;

   Timer time;

   Font font = new Font("Arial", Font.PLAIN, 20);
   static boolean handCursor = false;
   static boolean beating = false;

   static int crouchdecal = 0;

   static inputBoy Input = new inputBoy();

   Objects[] visible;
   human[] humans;

   static Particle[] particles;
   static Particle[] Bloodparticles;
   static Particle[] RainParticles;

   private double rainDarkness = 0.60f;
   private Color SkyColor = new Color(129, 107, 112);
   private Color flashColor = new Color(253,239,74);



   public Box(){

      addKeyListener(new AL());
      addMouseListener(this);
      addMouseMotionListener(this);
      setFocusable(true);
      setBackground(Color.BLACK);


      time = new Timer (Main.FPStiming, this);

      time.start();
      Main.maps.setCurrentMap(Main.maps.getCurrentMap().getID());

      particles = new Particle[20];
      Bloodparticles = new Particle[20];
      RainParticles = new Particle[600];




   }

   public void actionPerformed(ActionEvent e) {

      repaint();

   }

   public void paint(Graphics g){



      super.paint(g);
      Graphics2D g2d = (Graphics2D) g;
     
      g2d.clearRect(0, 0, 1200, 500);      //On supprime le fond
      g2d.setColor(SkyColor);
      g2d.fillRect(0, 0, 1200, 200);     //On dessine le fond
      for (int i=0;i<250;i++){

         g2d.setColor(new Color(SkyColor.getRed()+i/2,SkyColor.getGreen()+i/2,SkyColor.getBlue()+i/2));
         g2d.fillRect(0, 200+i, 1200, 2);
         i++;
      }
      g2d.setColor(Color.BLACK);
     
      ThunderEffect(g2d);


   
   }

   private void ThunderEffect(Graphics2D g2d){

      if (Nature.Thunder!=null && Nature.Thunder.alive){

         Nature.Thunder.ttl--;
         Stroke s = g2d.getStroke();

         for (int i = 0; i<9;i++){

            //System.out.println("point en:"+Nature.Thunder.getTree()[i+1][0]+" , "+Nature.Thunder.getTree()[i+1][1]+ "case :"+i);


            g2d.setStroke(new BasicStroke(5));
            if (!(Nature.Thunder.getTree()[i+1][0]==0)){
               g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,1f));
               g2d.setColor(Color.WHITE);
               g2d.drawLine(Nature.Thunder.getTree()[i][0], Nature.Thunder.getTree()[i][1], Nature.Thunder.getTree()[i+1][0], Nature.Thunder.getTree()[i+1][1]);
               //lumièe autour du l'éclair
               g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.6f));
               g2d.setStroke(new BasicStroke(10));
               g2d.drawLine(Nature.Thunder.getTree()[i][0], Nature.Thunder.getTree()[i][1], Nature.Thunder.getTree()[i+1][0], Nature.Thunder.getTree()[i+1][1]);
               //lumière lointaine
            }

            if (Nature.Thunder.getTree()[i+1][1]>300){   // quand l'eclair touche le sol
               g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.09f));
               g2d.fillRect(0, 0,1200, 505);
               g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,1f));
            }

         }




         g2d.setStroke(s);
         g2d.setColor(Color.BLACK);

         if (Nature.Thunder.ttl<1){
            Nature.Thunder.alive=false;
         }
      }




   }

   public void FadeOut(Graphics2D g2d){
   }

   public void paintMenu(Graphics2D g2d){
}

   public void paintDeath(Graphics2D g2d){
   }

   public void paintSettings(Graphics2D g2d){
   }

   public void paintInventory(Graphics2D g2d){
   }
Offline ReBirth
« Reply #1 - Posted 2012-12-11 13:35:50 »

Quote
Problem, all the tutorials I tried don't work because I don't use a common way to paint on the screen

If you mean that g2d using methods, as long you pass along same Graphics2D object (which you got from one thing) then okay.

Have you try Canvas?

Offline hug0x

Senior Newbie





« Reply #2 - Posted 2012-12-11 13:49:22 »

No, I didn't tried Canvas. In fact, I was thinking about using JPanel.

Every tutorial about Double Buffering use "MyClass extends Frame"

I use MyClass extends JPanel.

Is there any better way (more stable/fast) to paint on screen?

My game works fine on my laptop but run with a non decent framerate on friends pc (with good hardware)

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Ultroman

JGO Knight


Medals: 25
Projects: 1


Snappin' at snizzes since '83


« Reply #3 - Posted 2012-12-11 13:52:30 »

Instead of this...
1  
2  
3  
4  
5  
6  
7  
8  
      g2d.setColor(SkyColor);
      g2d.fillRect(0, 0, 1200, 200);     //On dessine le fond
      for (int i=0;i<250;i++){

         g2d.setColor(new Color(SkyColor.getRed()+i/2,SkyColor.getGreen()+i/2,SkyColor.getBlue()+i/2));
         g2d.fillRect(0, 200+i, 1200, 2);
         i++;
      }

...you can use a GradientPaint instead of a Color in setColor().

Syntax for GradientPaint:
GradientPaint(startX, startY, startColor, endX, endY, endColor, true)

startX - It represents the X-coordinate of the starting point.
startY - It represents the Y-coordinate of thestarting point.
startColor - It is used to set the starting color.
endX - It represents the X-coordinate of the ending point.
endY - It represents the Y- coordinate of the ending point.
endColor - It is used to set the ending color.
true - It is a boolean value mentioned for the cyclic presentation of color in the shape mean the starting color and the ending color are repeated up to the size of the shape.

- Jonas
Offline hug0x

Senior Newbie





« Reply #4 - Posted 2012-12-11 13:55:28 »

Thx ultroman, but do you think using graphics2D as I do is good for a "complex" game?
Offline Ultroman

JGO Knight


Medals: 25
Projects: 1


Snappin' at snizzes since '83


« Reply #5 - Posted 2012-12-11 14:02:41 »

Thx ultroman, but do you think using graphics2D as I do is good for a "complex" game?
Not really. I'd go with libgdx. That's what I did, after doing (and trashing) my first platform shooter. After climbing the learning curve, you'll be spitting out games in no time. But it IS a good idea to do something complicated in Java2D, to learn WHY you should go with a library.

Give me a sec, and I'll PM you a project I made to explain a Java2D setup for a friend of mine. It is well documented, and includes space for menu-panels in the sides (which are easily removed).

- Jonas
Offline hug0x

Senior Newbie





« Reply #6 - Posted 2012-12-11 14:13:05 »

Thanks !

So i need to recode my game entirely? Can i use JOGL/LWJGL instead?
Offline ReBirth
« Reply #7 - Posted 2012-12-11 14:14:30 »

Yeah you can use LWJGL too. In fact Libgdx uses LWJGL underhood. For JPanel double buffer, you can swapping between BufferedImage.

Offline hug0x

Senior Newbie





« Reply #8 - Posted 2012-12-11 14:17:36 »

Ok, thanks, i'll try LWJGL so. It seems good. I hope this isn't much harder than g2d wich I found easy to use.

What are the advantages to use LWJGL instead of graphics2D ?

Offline ReBirth
« Reply #9 - Posted 2012-12-11 14:23:05 »

Huge performance. But I can't say it's easier than using g2d Wink To use LWJGL feature but with g2d API, use Slick2D.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline hug0x

Senior Newbie





« Reply #10 - Posted 2012-12-11 14:25:25 »

Ok, thanks ! So i'll try LWJGL and if my brain explode, I'll go for Slick2D..

Pray for me =)
Offline Ultroman

JGO Knight


Medals: 25
Projects: 1


Snappin' at snizzes since '83


« Reply #11 - Posted 2012-12-11 14:46:21 »

Heheh, good luck. You won't need that example, then.

The advantage is, that when you're using OpenGL you're communicating with the graphics device in your computer, instead of throwing most of it at the CPU. It will be a tough start, but we're here to help Smiley

- Jonas
Offline nsigma
« Reply #12 - Posted 2012-12-11 14:46:36 »

For JPanel double buffer, you can swapping between BufferedImage.

Now there's a daft idea!  Tongue  JPanel is double buffered by default, so ignoring a potentially hardware accelerated buffer strategy (using VolatileImages under the hood) for your own using BufferedImage makes no sense!

hug0x - why are you creating a buffer strategy and then not using it?  This might be screwing up the inbuilt double buffering.  You should use either use BufferStrategy or the repaint() method.

I'm not trying to dissuade you from looking at an LWJGL option (I'd recommend libgdx over Slick2D), but that will take you a while - there are some quick wins in using the Java2D API correctly which might give you enough of a performance boost for now.

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Offline hug0x

Senior Newbie





« Reply #13 - Posted 2012-12-11 14:51:32 »

the BufferStrategy  line wasn't here 10minutes before posting, I just forgot to remove it.

You mean the repaint(); method is already doublebuffered?Because I use it with ease =)

I just want to choose a faster way to paint on screen.. LWJGL seems a bit hard for me x) and slick2D don't convice me..

Can you lie to me and tell me that I can make it work in few days... (I keep my old files, i just change my graphic classes).
Offline Ultroman

JGO Knight


Medals: 25
Projects: 1


Snappin' at snizzes since '83


« Reply #14 - Posted 2012-12-11 15:03:52 »

With slick2d, you should be able to make a full move in very little time.
The others...not so much. You're in for a lot of prototyping and trying out simple ways of drawing images and doing resource management Smiley

- Jonas
Offline nsigma
« Reply #15 - Posted 2012-12-11 15:11:04 »

You mean the repaint(); method is already doublebuffered?Because I use it with ease =)

It is, though it doesn't always mean you don't see tearing - also depends on vsync, OS, etc.

Also, repaint() doesn't call your render methods immediately, coupled with the fact that the Swing timer isn't that accurate.

Try switching to an active rendering loop, something like this one from ra4king - http://www.java-gaming.org/topics/about-on-my-main-loop/26222/msg/229028/view.html#msg229028  You should be able to keep all your rendering code.  This approach should give you the best performance you can out of Java2D.

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Offline hug0x

Senior Newbie





« Reply #16 - Posted 2012-12-11 15:12:34 »

Thanks, I will test both of the solutions!
Offline alesky

Junior Devvie


Medals: 3
Exp: 15 years


mmm....


« Reply #17 - Posted 2012-12-11 22:53:33 »

Man u are using java2D and it implement natively the doble buffering  in the jpanel
you don't need to use other libraries is absolutely easy

look hire this pice of code and chek in the java doc if u don't belive

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
public abstract class AbstractGameJPanel implements Game {

   
   // off screen rendering
   protected Graphics2D dbg = null;
   protected Image dbImage = null;  
   protected JPanel gamePanel = null;
   protected int pWidth,pHeight;   //size of the panel
   
   public void renderGame() throws Exception {

      if (dbImage == null){
         dbImage = gamePanel.createImage(pWidth, pHeight);  //LOOK THIS it is automatically double buffering
         if (dbImage == null) {
            System.out.println("dbImage is null");
            return;
         }
         else
            dbg = (Graphics2D) dbImage.getGraphics();
      }
     
      internalRenderGame(dbg);
   
   }  


and this is the code that paint on the screen
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
   public void paintScreen() {
      Graphics2D g;
      try {
         g = (Graphics2D) gamePanel.getGraphics();

         g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

         if ((g != null) && (dbImage != null)){
           
            g.drawImage(doFinalEffect(dbImage), 0, 0,pWidth,pHeight, null);
         }

         
         // Sync the display on some systems.
         // (on Linux, this fixes event queue problems)
         Toolkit.getDefaultToolkit().sync();
         g.dispose();
      }
      catch (Exception e){   // quite commonly seen at applet destruction
         System.out.println("Graphics error: " + e);  
      }
   }


Offline ReBirth
« Reply #18 - Posted 2012-12-12 03:32:06 »

Now there's a daft idea!  Tongue  JPanel is double buffered by default, so ignoring a potentially hardware accelerated buffer strategy (using VolatileImages under the hood) for your own using BufferedImage makes no sense!
That's why I suggested (a correct implementation of ) Canvas first. I myself never use raw JPanel (or whatever you call it, I mean by not using Canvas+BufferStrategy).

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

PocketCrafter7 (12 views)
2014-11-28 16:25:35

PocketCrafter7 (8 views)
2014-11-28 16:25:09

PocketCrafter7 (9 views)
2014-11-28 16:24:29

toopeicgaming1999 (76 views)
2014-11-26 15:22:04

toopeicgaming1999 (66 views)
2014-11-26 15:20:36

toopeicgaming1999 (15 views)
2014-11-26 15:20:08

SHC (29 views)
2014-11-25 12:00:59

SHC (27 views)
2014-11-25 11:53:45

Norakomi (32 views)
2014-11-25 11:26:43

Gibbo3771 (28 views)
2014-11-24 19:59:16
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!