Sudden random jitter when moving an image in game loop

I’m getting a random jitter when moving an image in a loop. I’m I the only one experiencing this?

I tried various attempts to fix this problem like changing my game loop to tick based instead of time based loop, Changing JFrame to AWT Frame, putting the game loop in EDT, use JPanel instead of canvas, using two threads to separate update() from draw(), use other jvm like openj9. All these attempts didn’t solve the issue.

After all of those attempts, I found a solution by using the full screen exclusive mode. But, my game needs to be switched in windowed mode.

I found a solution for windowed mode by manually activating the openGL pipeline.

System.setProperty("sun.java2d.opengl", "True");

Seems like everything is fine, when I remove the game loop and just put the update() and draw() method in an infinite loop, the image moves smoothly and the fps stays at 60 fps without a game loop. How’s that happened? When I don’t activate openGL or don’t use full screen exclusive mode, the fps is so fast. Same goes if I activate the d3d pipeline. Does this happen to all machines or it depends on the machine? If this happens in all machine then this is a great solution to my problem, but I think it varies. I hope somebody can answer this question because I couldn’t find any article regarding to this. I tried reading some article on oracle and still couldn’t find the answer.

https://docs.oracle.com/javase/8/docs/technotes/guides/2d/flags.html

https://docs.oracle.com/javase/8/docs/technotes/guides/2d/new_features.html

https://www.oracle.com/technetwork/java/perf-graphics-135933.html

When I put back the game loop like this:

while(true)
        {
               
              currentTime = System.nanoTime();
			  totalTime += currentTime - initialTime;
              t2 += currentTime - initialTime;
              initialTime = currentTime;
              
              if( totalTime > NANOS_PER_SECOND ) {
                totalTime -= NANOS_PER_SECOND;
                st.fps = frames;
                frames = 0;
              } 
               
			   
              if(t2 > FRAMES_PER_NANO)
              {
                  st.update_Game();
		  st.drawGraphics();
                  frames += 1;
                  t2 -= FRAMES_PER_NANO;
              }

			  //st.update_Game();
			  //st.drawGraphics();
               
              Thread.yield();
        }

I put the Update_game() and drawGraphics() in if statement, and the image starts to randomly jitter again even I manually activate the openGL pipeline.

When I do my game loop like this with openGL pipeline activated

while(true)
        {
	    st.update_Game();
	    st.drawGraphics();
        }

The image moves smoothly.

This kind of code arrangement in game loop also has no jitter as long as the openGL pipeline is activated.

while(true)
        {
               
              currentTime = System.nanoTime();
			  totalTime += currentTime - initialTime;
              t2 += currentTime - initialTime;
              initialTime = currentTime;
              
              if( totalTime > NANOS_PER_SECOND ) {
                totalTime -= NANOS_PER_SECOND;
                st.fps = frames;
                frames = 0;
              } 

			  st.update_Game();
			  st.drawGraphics();
                          frames += 1;

                         Thread.yield();
               
        }

As you can see I didn’t put the update_Game(), drawGraphics() and frames += 1; in an if statement this time. In my machine this loop frame count is 60 as long as the openGL pipeline is activated or full screen exclusive mode is activated. Otherwise, It will go up to a thousand frame counts.

Is there something wrong with my loop? Or the main loop is being block by other third party thread like gc or EDT? Or it’s just java is so bad doing active rendering when not accelerated?

Here’s my test code in case you want to try if random jitter happens in your machine.

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.GraphicsDevice;
import java.awt.GraphicsConfiguration;
import java.awt.Color;
import java.awt.Toolkit;

import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
import java.awt.image.BufferStrategy;

import java.awt.geom.AffineTransform;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import javax.imageio.ImageIO;

import java.io.File;

import java.util.Random;

public class ScreenTest extends JFrame
{
	private static ScreenTest st;
	
	private Graphics2D g2dbf;
	//
	private Graphics g;
	
	private VolatileImage bgImage;
	
	private Canvas frameCanvas;
	//JFrame size
	private int frameWidth,frameHeight;
	
	//Identity transform
	private AffineTransform identityTrans;
	//Object transform
	private AffineTransform objTrans;
	//
	private BufferStrategy bufferS;
	
	//platform's graphics attributes...
    GraphicsEnvironment ge;
    GraphicsDevice gd;
    GraphicsConfiguration gc;
	
	public double posX, posY;
	private double velX, velY;
	public double recentPosY;
	
	int fps;
	private BufferedImage myImg;
	
	Random rand = new Random();
	
	ScreenTest()
	{
		//JFrame properties
		setTitle("Screen Test");
		setIgnoreRepaint(true);
		setResizable(false);
		setUndecorated(true);
		
		// Get platform's graphics attributes...
		ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
		gd = ge.getDefaultScreenDevice();
		gc = gd.getDefaultConfiguration();
		
		//Set transform to identity transform
		identityTrans = new AffineTransform();
		//object transform
		objTrans = new AffineTransform();
        
		//Exclusive Full Screen Mode
		
		/*
		gd.setFullScreenWindow( this );
        if( gd.isDisplayChangeSupported() ) {
		DisplayMode dm = gd.getDisplayMode();
		frameWidth = dm.getWidth();
		frameHeight = dm.getHeight();
		
        gd.setDisplayMode( new DisplayMode( frameWidth, frameHeight, dm.getBitDepth(), dm.getRefreshRate() ));
        }
		*/
		
		
		//Simulated full screen mode
		//Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        //frameWidth = (int)screenSize.getWidth();
        //frameHeight = (int)screenSize.getHeight();
		
		//Windowed Mode
		frameWidth = 640;
        frameHeight = 480;
		
		try { myImg = ImageIO.read(new File("img.png")); }
		catch(IOException e){ System.err.println(e); }
		
		posX = frameWidth/2;
		posY = frameHeight/2;
		
		velX = 0;
		velY = -6;
		recentPosY = posY;
		
		
		setSize(frameWidth,frameHeight);
		setVisible(true);
		
		
		createBufferStrategy( 2 );
        bufferS = getBufferStrategy();
		
		
		
		//back buffer image
		bgImage = gc.createCompatibleVolatileImage(frameWidth,frameHeight);
		
	}
	
	void update_Game()
	{
		updateImg(); 
	}
	
	void drawGraphics()
	{
		try
		{
			String str1 = String.format("Velocity X: %.2f",velX);
            String str2 = String.format("Velocity Y: %.2f",velY);
			
			g2dbf = bgImage.createGraphics();
            g2dbf.setTransform(identityTrans);
            //set background
            g2dbf.setColor(Color.BLACK);
            g2dbf.fillRect(0,0,frameWidth,frameHeight);
		    
		    drawImg();
		        
				
		    //print some status information
            g2dbf.setColor(Color.WHITE);
            g2dbf.drawString("Image: " + Math.round(posX) + "," +
                Math.round(posY) , 5, 40);
	        g2dbf.drawString(str1, 5, 60);
            g2dbf.drawString(str2, 5, 80);
			
			g2dbf.drawString( String.format( "FPS: %s", fps ), 5, 140 );
			
			g = bufferS.getDrawGraphics();
		    g.drawImage(bgImage,0,0,null);
			
		    if( !bufferS.contentsLost() ) bufferS.show();
			Toolkit.getDefaultToolkit().sync();
		}
		finally
		{
			if(g != null) g.dispose();
			if(g2dbf != null) g2dbf.dispose();
		}
	}

	synchronized void drawImg()
	{
		g2dbf.setTransform(identityTrans);
		objTrans.setToIdentity();
		objTrans.translate(posX, posY);
		g2dbf.drawImage(myImg,objTrans,null);
	}
	
	synchronized void updateImg()
	{
		
		posX += velX;
		posY += velY;
		
        if (posX < -70) posX = frameWidth + 10;
        else if (posX > frameWidth + 10) posX = -10;
		
        if (posY < -10) posY = frameHeight + 10;
        else if (posY > frameHeight + 10) posY = -10;
		
	}
	
	public static void main(String[]args) throws InterruptedException,InvocationTargetException
	{
		System.setProperty("sun.java2d.opengl", "True");
		
		//System.setProperty("sun.java2d.d3d", "True");
		
		SwingUtilities.invokeAndWait(new Runnable(){
			@Override
			public void run()
			{
		       st = new ScreenTest();
			}
		});
			
			
         int frames = 0;
         long totalTime = 0,t2 = 0;
         long initialTime = System.nanoTime();
         long currentTime = 0;
         final short FRAMES_PER_SECOND = 60;
         final int NANOS_PER_SECOND = 1_000_000_000;
         final float FRAMES_PER_NANO = NANOS_PER_SECOND / FRAMES_PER_SECOND;
		 int count = 0;
          
        while(true)
        {
               
              currentTime = System.nanoTime();
			  totalTime += currentTime - initialTime;
              t2 += currentTime - initialTime;
              initialTime = currentTime;
              
              if( totalTime > NANOS_PER_SECOND ) {
                totalTime -= NANOS_PER_SECOND;
                st.fps = frames;
                frames = 0;
              } 
               
			   
              if(t2 > FRAMES_PER_NANO)
              {
                  st.update_Game();
				  st.drawGraphics();
                  frames += 1;
                  t2 -= FRAMES_PER_NANO;
              }

			  //st.update_Game();
			  //st.drawGraphics();
               
              Thread.yield();
        }
			
         
	}
}

I think i had an issue that might be similar to you. i still hadnt got to work on it because i had other project

when two object(you can use as an example rectangle) are going same speed from top to bottom. Some of object will step back at a random time creating jitter
this is the representation of it

do u see those two boxes that are nearly same y-position? those boxes originally were in same y-position but some lags that i dont know causing it

if you still dont catch it i have the raw project of it
you can check it here >> https://github.com/hadezbladez/DodgeThis_project

was your issues same as mine?

I’ll try it later. I edited and added more detail in my question.

Update: I just found out that the v-sync settings in my computer causes my game fps to cap at 60 fps because v-sync allow the gamer to synchronize the frame rate of the game with the monitor refresh rate for better stability. My monitor refresh rate is 60hz that’s why my game fps is capped at 60 fps. When I turned off v-sync and run my game in an infinite loop without capping the frame rate, my frame count went high even the openGL pipeline was activated.

Still, the random jitter of a moving image is still not solved. I think it’s probably because of the loop. I’ll try to tweak my game loop more.

so the vsync is not much the problem, eh? ??? ??? ???

i think i had talked about this in this thread
http://www.java-gaming.org/topics/the-game-loop/38861/msg/370944/view/topicseen.html#msg370944 :point:

i still havent tried it out

Lazy response on my part, as I am not taking the time to look at the code right now.

Some basic questions:

Do you employ blocking or synchronization? (Wondering if occasional deadlocks are hidden in your code somewhere.)

Do you always use loose-coupling when passing data between threads?

Yeah, I think the problem is the game loop. My objective is to cap the frame rate of my game to 60 fps. v-sync does that but the monitor refresh rate must be 60hz, So, I can’t rely on v-sync to cap my game fps. When I use my game loop to cap my fps to 60, the random jitter appears.

The jitter is mild but noticeable at some point.

In my code example that I posted here, I used synchronized methods. I tried to use a non-synchronized method and the problem still persist.

I just use a single class in my example here and one anonymous class(the runnable class in SwingUtilities), I’m not sure if I implemented coupling here(since I’m not familiar with that kind of object oriented design).

Loose coupling mostly just means that classes are very hands-off in how they interact with each other. I was thinking, for example, that if you want to send a value to another class, and find that you have to use synchronization to do so, a better way would likely be to have a method in the target class that simply accepts the parameter and stores it in an instance variable and does nothing else. This should never block. Meanwhile, the target method which needs the value just grabs it from the instance variable, and thus is never required to pause due to synchronization code.

Another way to cap the rate on the game loop would be to use a util.Timer or ExecutorService, where you can set the repetition rate and dispense with the timing calculations. Each has two modes for repeating, depending on if you want some auto-correction on the timing.

If there is jitter, something is not right. Plenty of people have succeeded in producing smooth-running Java graphics.

I tweaked my loop and the jitter is barely noticeable now when opengl pipeline is activated or my game is in full screen exclusive mode. When I disable opengl pipeline, the mild jitter will start to appear.

I’m not sure if anyone experiences it or it’s just in my machine. There’s a sample code in my question that anyone can try, let me know if you’re experiencing the same issue.

[quote]I’m not sure if anyone experiences it or it’s just in my machine.
[/quote]
Tried the example code and it’s a good 60fps experience after a few initial micro-stutters.

I cleaned the loop up a little:

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.GraphicsDevice;
import java.awt.GraphicsConfiguration;
import java.awt.Color;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
import java.awt.image.BufferStrategy;

import java.awt.geom.AffineTransform;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.imageio.ImageIO;

import java.io.File;

import java.util.Random;

public class ScreenTest extends JFrame {
	private static ScreenTest st;

	private Graphics2D g2dbf;
	//
	private Graphics g;

	private VolatileImage bgImage;

	private Canvas frameCanvas;
	// JFrame size
	private int frameWidth, frameHeight;

	// Identity transform
	private AffineTransform identityTrans;
	// Object transform
	private AffineTransform objTrans;
	//
	private BufferStrategy bufferS;

	// platform's graphics attributes...
	GraphicsEnvironment ge;
	GraphicsDevice gd;
	GraphicsConfiguration gc;

	public double posX, posY;
	private double velX, velY;
	public double recentPosY;

	int fps;
	private BufferedImage myImg;

	Random rand = new Random();

	ScreenTest() {
		
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		// JFrame properties
		setTitle("Screen Test");
		setIgnoreRepaint(false);
		setResizable(true);
		setUndecorated(false);
		
		
		// Get platform's graphics attributes...
		ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
		gd = ge.getDefaultScreenDevice();
		gc = gd.getDefaultConfiguration();

		// Set transform to identity transform
		identityTrans = new AffineTransform();
		// object transform
		objTrans = new AffineTransform();

		// Exclusive Full Screen Mode

		/*
		 * gd.setFullScreenWindow( this ); if( gd.isDisplayChangeSupported() ) {
		 * DisplayMode dm = gd.getDisplayMode(); frameWidth = dm.getWidth(); frameHeight
		 * = dm.getHeight();
		 * 
		 * gd.setDisplayMode( new DisplayMode( frameWidth, frameHeight,
		 * dm.getBitDepth(), dm.getRefreshRate() )); }
		 */

		// Simulated full screen mode
		// Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		// frameWidth = (int)screenSize.getWidth();
		// frameHeight = (int)screenSize.getHeight();

		// Windowed Mode
		frameWidth = 640;
		frameHeight = 480;

		try {
			myImg = ImageIO.read(new File("img.png"));
		} catch (IOException e) {
			System.err.println(e);
		}

		posX = frameWidth / 2;
		posY = frameHeight / 2;

		velX = 0;
		velY = -6;
		recentPosY = posY;

		setSize(frameWidth, frameHeight);
		setVisible(true);
		
		createBufferStrategy(1);
		bufferS = getBufferStrategy();

		// back buffer image
		bgImage = gc.createCompatibleVolatileImage(frameWidth, frameHeight);
	}
	
	void update_Game() {
		updateImg();
	}

	void drawGraphics() {
		try {
			String str1 = String.format("Velocity X: %.2f", velX);
			String str2 = String.format("Velocity Y: %.2f", velY);

			g2dbf = bgImage.createGraphics();
			g2dbf.setTransform(identityTrans);
			// set background
			g2dbf.setColor(Color.BLACK);
			g2dbf.fillRect(0, 0, frameWidth, frameHeight);

			g2dbf.setTransform(identityTrans);
			objTrans.setToIdentity();
			objTrans.translate(posX, posY);
			g2dbf.drawImage(myImg, objTrans, null);

			// print some status information
			g2dbf.setColor(Color.WHITE);
			g2dbf.drawString("Image: " + Math.round(posX) + "," + Math.round(posY), 5, 40);
			g2dbf.drawString(str1, 5, 60);
			g2dbf.drawString(str2, 5, 80);

			g2dbf.drawString(String.format("FPS: %s", fps), 5, 140);

			g = bufferS.getDrawGraphics();
			g.drawImage(bgImage, 0, 0, null);

			if (!bufferS.contentsLost())
				bufferS.show();
			
			Toolkit.getDefaultToolkit().sync();

		} finally {
			if (g != null)
				g.dispose();
			if (g2dbf != null)
				g2dbf.dispose();
		}
	}

	synchronized void updateImg() {

		posX += velX;
		posY += velY;

		if (posX < -70)
			posX = frameWidth + 10;
		else if (posX > frameWidth + 10)
			posX = -10;

		if (posY < -10)
			posY = frameHeight + 10;
		else if (posY > frameHeight + 10)
			posY = -10;

	}

	public static void main(String[] args) throws InterruptedException, InvocationTargetException {
		
		System.setProperty("sun.java2d.opengl", "True");

		// System.setProperty("sun.java2d.d3d", "True");

		SwingUtilities.invokeAndWait(new Runnable() {
			@Override
			public void run() {

				st = new ScreenTest();
				
			}
		});

		long timeOfLastUpdate = System.nanoTime();
		
		final long FRAMES_PER_SECOND = 60;
		final long NANOS_PER_SECOND = 1_000_000_000;
		
		final long NANOS_PER_FRAME = NANOS_PER_SECOND / FRAMES_PER_SECOND;

		
		while (true) {

			long currentTime = System.nanoTime();
			
			long totalTime = currentTime - timeOfLastUpdate;

			if (totalTime >= NANOS_PER_FRAME) {
				
				// This will show 59 fps but that's because it's really 59.999... and then rounded down.
				st.fps = (int)( NANOS_PER_SECOND / totalTime );
				
				timeOfLastUpdate = currentTime;

				st.update_Game();
				st.drawGraphics();
			}

			Thread.yield();
		}
	}
}

Thanks for checking out my sample code. just found out that if I reduce the createBufferStrategy() count to 1( createBufferStrategy(1); ), it makes the jitter more noticeable but the jitter frequency(how frequent jitter appears) is most likely the same. Although, createBufferStrategy(1); is working fine in the sample code program that I included in my question but it’s not working well in my main game where images are abundant.

I feel satisfied with my loop right now. Maybe, the problem is the java2d pipeline itself.

I tried to increase the priority of my game loop thread to high priority assuming that the problem lay in the thread scheduler context switching and it seems like the jitter frequency is more less now.

This article just recently posted might be interesting:

Cas :slight_smile:

Thanks for the link dude. It looks like a great article. I’m going to read it later.

The 59.94Hz problem has plagued me for years too and I never realised what caused it. That simple 59…61 loop is awesome.

Cas :slight_smile:

So, I tried the game loops in this blog http://www.koonsolo.com/news/dewitters-gameloop/ and the loop that worked the best in my system was the variable time step(Game Speed dependent on Variable FPS). In the blog, it is said to avoid variable timestep, since my game doesn’t contain too much physics I think I’m safe to use variable timestep.

So, now, let me lay out my problems about the other game loops in the blog.

My problem with lockstep/fixed time step(FPS dependent on Constant Game Speed) is that, when my game is not 60fps I see a flickering trailing image in my moving object, I suspect the trailing image is the previous image in previous frame, I’m using bufferstrategy, so double buffering problem has been ruled out. Also, my moving objects movement get choppy, jittery and jerky. What’s causing this? In my knowledge, when fps is lower the game would just go slow. I suspect the problem is that the fps is not in sync with my monitor because when I put 60fps, I don’t feel the jitter,jerks and choppiness but the stutter will appear.

About the last game loop in the blog,When I use the interpolation mechanism, my moving object get a sudden slow motion effect in a couple of seconds then will go back to normal. I don’t know If I implemented it right, but I just followed the instruction in the blog.

I also tried to use the fuzziness fix in this blog(great read btw) https://medium.com/@tglaiel/how-to-make-your-game-run-at-60fps-24c61210fe75 and the stutter didn’t dissappear.

Any suggestion why I got jitter,jerks, choppiness and flickering trailing image in low fps and sudden slow motion when interpolation is implemented?

For now, I’m gonna use variable time step for my rendering and fixed timestep in my game physics.

There is one thing I’d say about variable time step, which is if your game is 2D, under no circumstances will variable time step feel nice. Lock it at 60, lock it at 30, whatever you do, make sure the logic is fixed and hope for vsync working.

Cas :slight_smile:

I really want to cap my fps. When I cap my fps to 60 i’m having a micro stutter, microstutters is fine with me, but I’m thinking “what if this game run in 75hz or 100+hz, will the stutter problem stay at microstutter or will it get worst?”. I tried to cap my game fps to 30 and when I ran it on my 60hz monitor, I was having a stutter(not microstutter) and when I tried different fps lower than 60 like 50 or 25 I got a choppy movement and my moving object(especially the player object) got pretty shaky, It seemed like the the previous frame didn’t completely cleared before the new frame drawn on the screen. This problem occurs even on a simpliest animation. Here is a sample code of two moving shape(circle and square)

http://pasted.co/993feeb5

I my system, the slow moving square has less shakes and the fast moving circle has more shakes, the stutter effect equivalently affects both objects at the same rate. I disable d3d and just use non-accelerated image(BufferedImage) in this example because I want my game to work(if possible) on a computers that don’t support Direct3D or openGL. I tried to switch d3d and openGL on and off, tried to use volatileimage and switch vsync on and off and the result is similarly the same.

I want to use a fixed timestep with interpolation mechanism but I don’t like the sudden slow motion effect that I get. Maybe my implementation of this loop was wrong that’s why I get that sudden slow motion effect.

So, If those loops don’t work on my system, then it might not work on other system too. Maybe the problem only lies on my system. I might release a demo version of my game to check if my game runs fine on various machine.

For what it is worth, I took your posted code and rewrote the game loop to be controlled by a util.Timer. I’d did a bit of pruning of unused variables in my copy, so the code isn’t exactly alike.

The jitter is quite similar, as far as I can tell.

The normal way of scheduling the TimerTask has even worse jitter than the “scheduleAtFixedRate” version. The main thing different between the two scheduling methods AFAIK is that the latter will attempt to “catch up” if it has fallen behind schedule. I assume this makes it more similar to the logic you have put in for your timing.

So, I think that this also confirms that the image rendering code is probably causing this, not the timing logic. But that puts this problem out of my expertise. When I render with Swing, I usually just use the double-buffering automatically provided by JPanel (when overriding paintComponent, and I don’t recall getting this sort of jitter.

Nowadays, I use JavaFX which provides AnimationTimer. The simple code in this tutorial, a bouncing ball, has a couple serious jitters when starting out, but after a few seconds, proceeds with what you might consider an adequate degree of smoothness?


import java.lang.reflect.InvocationTargetException;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.GraphicsDevice;
import java.awt.GraphicsConfiguration;
import java.awt.Color;
import java.awt.Toolkit;

import java.awt.image.BufferedImage;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

public class ScreenTest2
{
    private static ScreenTest2 st;
    
    private Graphics2D g2dbf;
    //
    private Graphics g;
    
    private BufferedImage bgImage;
    
    //JFrame size
    private int frameWidth,frameHeight;
    
    JFrame frame;
    
    //platform's graphics attributes...
	GraphicsEnvironment ge;
	GraphicsDevice gd;
	GraphicsConfiguration gc; 	
    
    public double posX, posY;
    public double posY2,velY2;
    private double velX, velY;
    public double recentPosY;
    
    int fps;
    
    Random rand = new Random();
    
    ScreenTest2()
    {
        // Get platform's graphics attributes...
        ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        gd = ge.getDefaultScreenDevice();
        gc = gd.getDefaultConfiguration();
        
        //JFrame properties
        frame = new JFrame(gc);
        frame.setTitle("Screen Test2");
        frame.setIgnoreRepaint(true);
        frame.setResizable(false);
        frame.setUndecorated(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        //Set transform to identity transform
        
        //Windowed Mode
        frameWidth = 640;
        frameHeight = 480;
        frame.setUndecorated(false);
                
        posX = frameWidth/2;
        posY = frameHeight/2;
        posY2 = posY;
 
        velX = 0;
        velY = -4;
        velY2 = -6;
        recentPosY = posY;
             
        frame.setSize(frameWidth,frameHeight);
        frame.setVisible(true);
                
        //back buffer image
        bgImage = gc.createCompatibleImage(frameWidth,frameHeight);
        
    }
    
    void update_Game()
    {
            updateImg(); 
    }
    
    void drawGraphics()
    {
        try
        {                
            g2dbf = bgImage.createGraphics();
            //set background
            g2dbf.setColor(Color.BLACK);
            g2dbf.fillRect(0,0,frameWidth,frameHeight);
                    
            g2dbf.setColor(Color.WHITE);
            g2dbf.fillRect((int)posX,(int)posY,50,50);
            g2dbf.fillOval((int)posX + 80,(int)posY2,50,50);
                
            //print some status information
            g2dbf.setColor(Color.WHITE);
            g2dbf.drawString("Image: " + Math.round(posX) + "," +
            		Math.round(posY) , 5, 40);
                
            g2dbf.drawString( String.format( "FPS: %s", fps ), 5, 60 );
                
            g = frame.getGraphics();
            g.drawImage(bgImage,0,0,null);
                
            Toolkit.getDefaultToolkit().sync();
        }
        finally
        {
                if(g != null) g.dispose();
                if(g2dbf != null) g2dbf.dispose();
        }
    }

    
    void updateImg()
    {        
        posX += velX;
        posY += velY;
        posY2 += velY2;
            
        if (posX < -70) posX = frameWidth + 10;
        else if (posX > frameWidth + 10) posX = -10;
                
        if (posY < -10) posY = frameHeight + 10;
        else if (posY > frameHeight + 10) posY = -10;
                
        if (posY2 < -10) posY2 = frameHeight + 10;
        else if (posY2 > frameHeight + 10) posY2 = -10; 
    }
    
    public static void main(String[]args) throws InterruptedException,InvocationTargetException
    {
        //System.setProperty("sun.java2d.opengl", "True");
        
        //System.setProperty("sun.java2d.d3d", "True");
        
        System.setProperty("sun.java2d.d3d", "false");
        
        //System.setProperty("sun.java2d.trace","count");
        
        SwingUtilities.invokeAndWait(new Runnable(){
            @Override
            public void run()
            {
           st = new ScreenTest2();
           st.start();
            }
        });                   
    }
    
    private void start()
    {
        Timer timer = new Timer();
        ScreenTestTimerTask timerTask = new ScreenTestTimerTask();
        
        timer.scheduleAtFixedRate(timerTask, 100, 20);
        // jitter even worse with the normal update
//        timer.schedule(timerTask, 100, 20);
    }
    
    class ScreenTestTimerTask extends TimerTask
    {
		@Override
		public void run() {
		     st.update_Game();
		     st.drawGraphics();
		}
    }
}