Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Java game application just won't run smooth

Options
  • 29-04-2006 10:31pm
    #1
    Registered Users Posts: 8,449 ✭✭✭


    Hey, if anyone has some time on their hands could they please compile these two and take a look at the app?

    I'm trying to lay down some fundamentals for a simple action game but I want to get it draw something moving smoothly first.

    Currently, in my main game loop I instruct the thread to yeild if the time taken in that loop was less than a certain speed, say 20 ms, but its still slightly jittery, whereas other games have perfect smoothness in movement.

    Any help would be greatly appreciated, thanks :)

    PS: Even though I am using a buffer strategy, could the fact that I'm drawing the whole background behind the ball each time be the problem?

    Game.java
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.imageio.ImageIO;
    import java.util.*;
    
    import java.awt.event.*;
    import java.awt.image.*;
    import java.awt.*;
    import java.net.*;
    
    public class Game extends Canvas{
    	public static final int WIDTH = 800;
    	public static final int HEIGHT = 600;
    	public static final int GAMESPEED = 18;
    	public HashMap sprites;
    	public BufferStrategy strategy;
    	public BufferedImage smiley;
    	public long usedTime;
    	Ball b;
    
    
    	public Game(){ // Game Constructor
    	    sprites = new HashMap();
    
    	    //create jframe and make it visible
    		JFrame jf = new JFrame("Game");
    		jf.setBounds(0,0,WIDTH,HEIGHT);
    		jf.setVisible(true);
    		jf.setResizable(false);
    		setIgnoreRepaint(true);
    
            //connect jframe to panel so it can override 
    		//the paint method
    		JPanel panel = (JPanel)jf.getContentPane();
    		setBounds(0,0,WIDTH,HEIGHT);
    		panel.setPreferredSize(new Dimension(WIDTH,HEIGHT));
    		panel.setLayout(null);
    		panel.add(this);
    
            //windowlistener for closing the window
    		jf.addWindowListener(new WindowAdapter(){
    			public void windowClosing(WindowEvent e){
    				System.exit(0);
    			}
    		}); //============== end Game Constructor
    
    		createBufferStrategy(2);
    		strategy = getBufferStrategy();
    
    		requestFocus();
    
    	}
    
    
    
    	//=====IMAGE LOADING METHOD=====//
    	public BufferedImage loadImage(String name){
    		URL url = null;
    		try{
    			url = getClass().getClassLoader().getResource(name);
    			return ImageIO.read(url);
    		}
    		catch(Exception e){
    			System.out.println("Couldn't load " + name);
    			return null;
    		}
    	}
    
        //=====GET SPRITE AND ADD TO LIST OF SPRITES METHOD====//
    	public BufferedImage getSprite(String name){
    		BufferedImage img = (BufferedImage)sprites.get(name);
    		if(img == null){
    			img = loadImage("resources/" + name);
    			sprites.put(name,img);
    		}
    		return img;
    	}
    
        //===== INITIALISE WORLD =======//
    	public void initWorld(){
    		b = new Ball(this);
    	}
       
        //=======UPDATE WORLD =========//
    	public void updateWorld(){
    		b.act();
    
    	}
    
    	//=====PAINT METHOD=====//
    	public void paintWorld(){
    		Graphics2D g = (Graphics2D)strategy.getDrawGraphics();
    
    		g.setColor(Color.black);    //could this be the jittery problem?
    		g.fillRect(0,0,WIDTH,HEIGHT); //could this be the jittery problem?
    
    		b.paint(g);
    
    
            //FPS ------------
    		if(usedTime > 0)
    			g.drawString(String.valueOf(1000/usedTime) + " fps",0,HEIGHT-50);
    		else
    			g.drawString("--- fps",0,HEIGHT-50);
    		//END FPS ----------
    		strategy.show();
    
    	}
    
        //====== MAIN GAME LOOP =======//
    	public void gameLoop(){
    		usedTime = 1000;
    		initWorld();
    		while(isVisible()){
    			long startTime = System.currentTimeMillis();
    			updateWorld();
    			paintWorld();
    			usedTime = System.currentTimeMillis()-startTime;
    			startTime += 10;
    
    			do{
    				Thread.yield();
    			}
    			while(System.currentTimeMillis() - startTime < 17);
    		}
    	}
    
    
    
    	public static void main(String[] args){
    		Game game = new Game();
    		game.gameLoop();
    	}
    
    
    }
    
    
    Ball.java
    import java.awt.*;
    
    public class Ball{
    	protected int x,y;
    	protected int width,height;
    	protected int vx, vy;
    	private Game game;
    
    	public Ball(Game g){
    		x = 100; y = 100;
    		vx = 5; vy = 0;
    		width = 10; height = 10;
    		game = g;
    
    		
    	}
    
    	public void act(){
    		x+=vx;
    		if(x< 0 || (x + width) > game.WIDTH){
    			vx = -vx;
    		}
    	}
    
    	public void setVX(int n){
    		vx = n;
    	}
        
    	public void paint(Graphics2D g){
    		g.setColor(Color.white);
    		g.fillRect(x,y,width,height);
    	}
    
    }
    


Comments

  • Registered Users Posts: 8,449 ✭✭✭Call Me Jimmy


    yeah i said I have used a BufferStrategy which is a built in feature of java that does double buffering


  • Closed Accounts Posts: 261 ✭✭bishopLEN


    I'm not a game programmer (YET)

    Did a bit of tinkering; hope it helps :o

    Lower the vx value to 1

    Set the 17 to 5

    I was trying other stuff out with Thread.sleep(20) etc. but it's much the same
    vx = 1;
    
    while(System.currentTimeMillis() - startTime < 5);
    
    


  • Registered Users Posts: 1,272 ✭✭✭i_am_dogboy


    What OS are you using? I had a horrible time with the milli second timer in windows, 2k was the worst but XP was still prety crap. Use the java 3d timer or the nano second time instead see if it helps.

    For the timing I'd do something like
    long aim = 1000000000L / 60L;
    long then, now, diff;
    then = System.nanoTime();
    while (isVisible())
    {
      now = System.nanoTime();
      diff = then - now;
      then = now;
      updateWorld();
      paintWorld();
      try
      {
        Thread.sleep(aim - diff);
      }
      catch(Exception e){}
    }
    

    aim is the max amount of time you will sleep for, in this case to allow for 60 frames.
    diff is the amount of time taken to update and render the scene

    I'm not saying what you're doing is wrong btw, it's just the way I've always done it and it's always worked perfectly for me. All i'm doing is calculating the amount of time it's taken to do the whole frame, and sleeping by the allowed time for a frame - the amount of time taken. This might come up with negatives in Thread.sleep() but there's some extra code i've left out for the sake of simplicity that prevents this, you can just have an if statement if you want...

    Your rendering code looks fine so I would think the problem with performance is timing related. This Book covers the topic of java timers in a good bit of depth, it also has excellent examples of rendering code and stuff so have a look at it.

    Also look into FSEM(Full Screen Exclusive Mode) to improve performance, it was pretty iffy outside of windows last time I did any fullscreen java 2d apps but that was a good while ago and I would think it's improved since then.


  • Registered Users Posts: 8,449 ✭✭✭Call Me Jimmy


    Hey thanks a lot guys.

    I'm on Windows XP yea.
    I'll give the nano time thing a try. I think full screen exclusive mode might be tricky but i might give it a try if nano timer aint working as I would hope.

    Yea I have a book called "Developing games in java" coming from the States atm so hopefully when that arrives i'll be able to do this perfect.


  • Registered Users Posts: 8,449 ✭✭✭Call Me Jimmy


    Hey there must be a logical error in the nanoTime thing, the game just stops at the start (but is still running). Are you sure that method has worked like that before?


  • Advertisement
  • Registered Users Posts: 1,272 ✭✭✭i_am_dogboy


    Hey there must be a logical error in the nanoTime thing, the game just stops at the start (but is still running). Are you sure that method has worked like that before?
    I forgot to convert diff to milli seconds, just change the line

    diff = then - now;
    to
    diff = (then - now) / 1000000L;

    Should have spotted that the first time.


Advertisement