problem with java buffered image

Started by
4 comments, last by Avalander 9 years, 10 months ago

I am trying to increase performance with buffered images. I have made a game loop that has increased my fps but i also want buffered images, however these aren't working.

its supposed to show a black background and print the amount of ticks and fps in the console


package game3;

import java.awt.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.image.*;
import java.util.logging.*;
import java.util.logging.*;
import javax.swing.*;

/**,
 *
 * @author djb
 */
public class Game extends Canvas implements Runnable{
    
    private boolean running = false;
    private Thread thread;
    
    private BufferedImage image = new BufferedImage(640,480,BufferedImage.TYPE_INT_RGB);
    
    private synchronized void start()
    {
        if(running)
            return;
        
        running = true;
        thread = new Thread(this);
        thread.start();
    }
    
    private synchronized void stop()
    {
        if(!running)
            return;
        
        running = false;
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.exit(1);
    }
    
    
    
    public void run() 
    { //game loop
        long lastTime = System.nanoTime();
        final double amountOfTicks = 60.0;
        double ns = 1000000000 / amountOfTicks;
        double delta = 0;
        int updates = 0;
        int frames = 0;
        long timer = System.currentTimeMillis();
        
        while(running)
        {
            //game loop
          long now = System.nanoTime();
          delta+=(now - lastTime)/ns;
          lastTime = now;
          if(delta >= 1)
          {
              tick();
              updates++;
              delta--;
          }
          render();
          frames++;
          
          if(System.currentTimeMillis() - timer > 1000)
          {
              timer  += 1000;
              System.out.println(updates + "ticks, Fps " + frames);
              updates = 0;
              frames = 0;
          } 
          
        }
        stop();
        
    }
    
    private void tick()
    {
        
    }
    
    private void render()
    {
        BufferStrategy bs = this.getBufferStrategy();
        if(bs == null)
        {
            createBufferStrategy(3);
            return;
        }
        
        Graphics g = bs.getDrawGraphics();
        //put objects between here and dispose to draw stuff
        
        g.drawImage(image, 0, 0, 630, 480, this);
        
       g.dispose();
        bs.show();
        
        
        
    }
    
    public static void main(String[]args)
    {
        
        Game game = new Game();
        
        JFrame frame = new JFrame();
        frame.pack();
        frame.setSize(640,480);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        game.start();
        
        
    }

    
    
}

could really use some help, thanks

Advertisement

You need to add your canvas object to the JFrame. Just add the following line to your main, after instantiating the JFrame:


frame.add(game);

I don't mean to be rude, but when you ask for help with a crashing program, you should post the error stack trace. And if you had googled for "java canvas java.lang.IllegalStateException: Component must have a valid peer" you wouldn't even had need to ask. I just say so the next time you can solve your problem faster.

Yeah that sorted it out. Im such a idiot!

Yeah that makes sense, sorry about that. won't happen again.

Thanks a lot

ok so I got the image on the screen and did key inputs, but instead of moving cleanly it leaves behind a trail of the image.

Its like its just cloning itself instead of moving.

It has to be something to do with the loop right?


package game3;

import java.awt.*;
import java.awt.*;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.image.*;
import java.io.IOException;
import java.util.logging.*;
import java.util.logging.*;
import javax.swing.*;

/**,
 *
 * @author djb
 */
public class Game extends Canvas implements Runnable{
    
    //Player p;
    
    private boolean running = false;
    private Thread thread;
    
    BufferedImage player = null;
    
    int speed = 2;
    
    private Player p;
    
    public void init() 
    {
        
        BufferedImageLoader loader = new BufferedImageLoader();
        try{
            player = loader.loadImage("/images/p1Up.png");
        }catch(IOException e)
        {
            e.printStackTrace();
        }
        
        addKeyListener(new KeyInput(this));
        this.requestFocus();
        p = new Player(200,200,this);
    }
    
    private synchronized void start()
    {
        if(running)
            return;
        
        running = true;
        thread = new Thread(this);
        thread.start();
    }
    
    private synchronized void stop()
    {
        if(!running)
            return;
        
        running = false;
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.exit(1);
    }
    
    
    
    public void run() 
    { //game loop
        init();
        long lastTime = System.nanoTime();
        final double amountOfTicks = 60.0;
        double ns = 1000000000 / amountOfTicks;
        double delta = 0;
        int updates = 0;
        int frames = 0;
        long timer = System.currentTimeMillis();
        
        while(running)
        {
            //game loop
          long now = System.nanoTime();
          delta+=(now - lastTime)/ns;
          lastTime = now;
          if(delta >= 1)
          {
              tick();
              updates++;
              delta--;
          }
          
          render();
          frames++;
         
          
          if(System.currentTimeMillis() - timer > 1000)
          {
              timer  += 1000;
              System.out.println(updates + "ticks, Fps " + frames);
              updates = 0;
              frames = 0;
              
          } 
          
        }
        stop();
        
    }
    
    private void tick()
    {
        p.tick();
        
    }
    
    private void render()
    {
        BufferStrategy bs = this.getBufferStrategy();
        if(bs == null)
        {
            createBufferStrategy(1);
            return;
        }
        
        Graphics g = bs.getDrawGraphics();
        //put objects between here and dispose to draw stuff
        
        
        
        //g.drawImage(player, 100, 100,32 ,32, this);
        
        p.render(g);
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        
        g.dispose();
        bs.show();      
        
    }
    
     public void keyPressed(KeyEvent e)
     {
         int key = e.getKeyCode();
         
         if(key==KeyEvent.VK_RIGHT){
             
             p.setX(p.getX() + 5*speed);
             
         }else if(key==KeyEvent.VK_LEFT){
             
             p.setX(p.getX() - 5*speed);
             
             
         }else if(key==KeyEvent.VK_UP){
             
             p.setY(p.getY() - 5*speed);
             
         }
         else if(key==KeyEvent.VK_DOWN){
             
            p.setY(p.getY() + 5*speed);
             
         }
     }
      public void keyReleased(KeyEvent e)
      {
          
      }
   
    
    public static void main(String[]args)
    {
        
        Game game = new Game();
        
        JFrame frame = new JFrame();
        frame.pack();
        frame.setSize(640,480);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(game);
        
        game.setFocusable(true);
        
        game.start();
        
        
    }

    

    
    
}

Mostly as an FYI before you get too far down this path...


BufferedImage (and several other image classes) have the annoying habit of being really bad for performance in games.

While they are sometimes accelerated, sometimes they are not. Even more annoyingly, the system can spontaneously decide to switch from hardware accelerated to software rendering for reasons your program is not told. Just suddenly *poof*, it changes from a jet flying through the sky in performance to a jet flying through jello, mucking along at a terrible pace.

Some operations are known to cause the problem (such as reading from images) but other times it switches mode from things like windows getting resized (even other windows, necessarily not yours) or from other windows getting rendering contexts, but it also happens for a bunch of reasons that people just guess at.

Google for BufferedImage performance problems. Java's inconsistent use of hardware acceleration for graphics is a big reason for moving to libraries that guarantee hardware acceleration.

If your game doesn't need the performance, that is fine. But if you want to develop something where you need framerate performance counters, better for you to learn up front that the built-in rendering system unfortunately will not cut it.

I guess that what you are doing is to draw the player in his actual position every frame, but you are not erasing him from his last position, so you are actually drawing each frame in the top of the previous one. That's why the image is leaving trails.

The easiest way to solve this is to redraw the whole background at the begining of the render function, so you'll start each frame with an empty background instead of the previous frame.

This topic is closed to new replies.

Advertisement