Java 2D game "powered" by repaint(); lags in a strange way - java

I used my recent days to program a little 2D game in Java. I wanted to use nothing but the normal Java SDK. So far so good. I now finshed it, there's just one little problem:
I used the Thread.sleep method to create something like a gameloop/tick. Since I'm not too familiar with object oriented programming, I'm not quite sure whether I use the right expressions, so please ignore wrong ones.
The strange thing is, that if I switch my waiting-time (I called it "Takt") to 100 or above, everything works perfectly fine. I want to change it to 50, but as soon as I get it lower than 100, the game starts lagging extremly (the bouncing red ball which this easy ping-pong-game is about starts flickering heavily.
Here's a piece of code of my Display class, it includes the paint(); method. If you need other code parts, just let me know! And please pardon my variable names, I'm from germany. So here's the code:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
#SuppressWarnings("serial")
public class Output extends JFrame implements Runnable{
public static int W = 400;
public static int H = 700;
public static int Playerx;
public static int Playery = H-30;
public static int Punkte;
public static int Trash;
public static long Takt = 100;
public static boolean DrawGameOver;
public static boolean finished;
public static void main(String[] args) throws InterruptedException {
JOptionPane.showMessageDialog(null, "Das Spiel startet, sobald Sie auf OK drücken. Das Ziel ist es, möglichst viele Punkte zu erzielen.", "Ping-Pong-Solo", JOptionPane.NO_OPTION);
JOptionPane.showMessageDialog(null, "Mindstanforderungen: 1. Dual-Core Prozessor 2. Bildschirmauflösung mit mindestens 400*700p", "Systemanforderungen", JOptionPane.NO_OPTION);
Output Fenster = new Output();
Fenster.setSize(W, H);
Fenster.setResizable(false);
Fenster.setLocationRelativeTo(null);
Fenster.setVisible(true);
Fenster.setTitle("Ping Pong Release 1.0");
Fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Fenster.addKeyListener(new MyKeyListener());
new Physics();
new Thread(new Output()).start();
while(true){
if(DrawGameOver == false && finished){
Fenster.repaint();
}else{
GameOver();
}
try {
Thread.sleep(Takt);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(!DrawGameOver){
Physics.Bewegung();
}
}
}
public static void GameOver(){
JOptionPane.showMessageDialog(null, "Sie erreichten "+Punkte+" Punkte. ", "Spiel beendet.", JOptionPane.NO_OPTION);
JOptionPane.showMessageDialog(null, "(c) Joel Krimmel", "Der Boss", JOptionPane.NO_OPTION);
System.exit(0);
}
public void paint(Graphics g){
finished = false;
g.setColor(Color.BLACK);
g.fillRect(0, 0, W, H);
g.setColor(Color.BLUE);
g.fillRect(Playerx, Playery, 100, 20);
g.setColor(Color.RED);
g.fillRoundRect(Physics.x, Physics.y, Physics.W, Physics.H, 500, 500);
g.setColor(Color.YELLOW);
g.drawString("Punkte: "+Punkte, W-100, 50);
finished = true;
}
#Override
public void run() {
// TODO Auto-generated method stub
while(true){
MyKeyListener.Verarbeitung();
}
}
}

I've noticed that you're using JFrame, which means that each time you repaint, you're repainting the entire window. The solution is to use a JPanel, which is much faster, and to put that into your JFrame as to not have any more flickering.
Also, thread.sleep essentially freezes your entire program, so please use the swing timer.

So there could be multiple reasons why your game is flickering. I think the most likely one is that you are using no buffering. That means that you are drawing the screen while it's beeing displayed. So stange things like half drawn pictures will be displayed sometimes. Instead you can write the content to an image first and then draw the whole image at once.
In the code it would look something like this:
public void paint(Graphics g){
finished = false;
// the buffer image
BufferedImage bufferImage = new BufferedImage(getWidth(),getHeight(),BufferedImage.TYPE_INT_RGB);
// I used Graphics2D instead of Graphics here, because its more flexible and lets you do more things.
Graphics2D g2 = (Graphics2D)bufferImage.getGraphics();
g2.setColor(Color.BLACK);
g2.fillRect(0, 0, W, H);
// ...
g2.drawString("Punkte: "+Punkte, W-100, 50);
// now draw the buffer image on the screen.
g.drawImage(bufferImage, 0, 0, null);
finished = true;
}
(That code is not ideal, but it's a quick way to do it. If you want to know how to do it better look up "double buffering".)
Another (unlikely) reason could be that the rendering takes different amounts of time each rendering process. You could fix that by measuring the time the rendering takes with System.currentTimeMillis() and adjust the sleeping time.
And also: Don't name variables in german. I'm german too (Hallo aus Bremen) and I don't do it either. I's bad. :-)
But more importantly don't start variable name with an upper-case letter, they can easily be confused with clases otherwise.
You should take a look at the java naming conventions.

Related

Painting a group of objects in a JPanel

I'm pretty new to Java and the GUI world. Right now I'm trying to create a really basic space shooter. To create it I started creating a JFrame, in which I've later on put a personal extension of a JPanel called GamePanel, on which I'm now trying to display all my components. Until here it's all pretty clear, the problem comes now: I have my GamePanel in which I display my player, and on the KeyEvent of pressing S the player should shoot the Bullets. I've managed the bullets as an Array, called Shooter[], of Bullet Objects, created by myself this way:
public class Bullet implements ActionListener{
Timer Time = new Timer(20, this);
private int BulletY = 430;
public int PlayerX;
public Rectangle Bound = new Rectangle();
public Bullet(int playerx) {
this.PlayerX = playerx;
Time.start();
}
public void draw(Graphics g){
g.setColor(Color.RED);
g.fillRect(PlayerX + 2, BulletY, 3, 10);
g.dispose();
}
#Override
public void actionPerformed(ActionEvent e) {
if (Time.isRunning()) {
BulletY = BulletY - 5;
Bound = new Rectangle (PlayerX + 2, BulletY, 3, 10);
}
}
}
I thought that calling the draw method in the GamePanel's paint() method would have allowed me to display both all the bullets shot and the player. What actually happens is that at the start it seems allright, but when I press S the player disappears and just one bullet is shot. Can you explain me why? This is how my paint() method looks like:
public void paint(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, 500, 500);
for(int i = 0; i < BulletsCounter; i++) {
Shooter[i].draw(g);
}
g.setColor(Color.RED);
g.fillRect(PlayerX, PlayerY, 20, 20);
//System.out.println("Here I should have painted the player...");
g.dispose();
}
BulletsCounter is a counter I've created to avoid any NullPointerExceptions in painting the whole array, it increases when S is pressed and so another bullet of the array is initialized and shot.
Thank you for your patience, I'm new to the site, so warn me for any mistake.
You've several significant problems, the biggest given first:
You're disposing a Graphics object given to you by the JVM. Never do this as this will break the painting chain. Instead, only dispose of a Graphics object that you yourself have created.
You're drawing within paint which is not good for several reasons, but especially bad for animation since you don't have automatic double buffering of the image
You don't call the super painting method within your override and thus don't allow the JPanel to do house-keeping painting.
Recommendations:
Don't dispose of the Graphics object, not unless you, yourself, create it, for example if you extract one from a BufferedImage.
Override the JPanel's paintComponent method, not its paint method to give you double buffering and smoother animation.
And call super.paintComponent(g) first thing in your override to allow for housekeeping painting

How do I (properly) render at a high frame rate in pure Java

I've been trying to make a simple game in pure java and I've encountered a problem in drawing. I'm trying to keep a relatively high frame-rate but having issues with the fact that JFrame.repaint() cannot be 'forced' and is merely a request to have the frame redrawn at the next available opportunity. As a result, the below code's frame-rate is terrible. However, (and this is the strange part) it seems to only be terrible when my mouse isn't moving. If my mouse is moving and over-top of the window, the frame rate is fast and crisp.
I've tried various online suggestions and even compiled examples on how to do this and they all seem to have the same issue with the frame rate dropping dramatically when my mouse isn't moving over the window.
(I'm using Linux, if that matters)
Any and all help is much appreciated!
import java.awt.*;
import javax.swing.*;
public class Test extends JPanel {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(new Dimension(300, 300));
frame.setVisible(true);
frame.getContentPane().add(new Test());
for (int k = 0; k < 1_000_000; k++) {
frame.repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
System.exit(1);
}
}
frame.dispose();
System.exit(0);
}
private int k = 0;
public Test() {
super();
}
#Override public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.BLACK);
int height = (int) (((k * 0.01) % 1) * getHeight());
g.drawLine(
0, height,
getWidth(), height
);
k++;
}
}
After far too much research, it turns out that java does not sync / flush the display buffer automatically on many Linux systems. All the repaints and such were correct, however the display buffer was not flushing, thus creating the strange lagging effect.
The Solution:
Toolkit toolkit = Toolkit.getDefaultToolkit(); /* get AWT toolkit */
/* initialize things */
...
while (your_loop) {
/* run your logic */
...
/* paint everything */
...
toolkit.sync(); /* force display buffer to flush */
}
Thank you all for your input
The question is not simple. The code below has not been tested, then just to give you the idea... In the next lines, AWT is the underlying of Swing.
First, you have to keep your paintComponent() very fast (indeed!). This is the first requirement. Basically, for 60 fps, you must draw in less than 15 milliseconds. Forget transaparency and other stuff (works badly on Windows, I don't know for Linux). Try to save calculations when possible.
Second, Execute everything else in a different thread. This is the way I use for my own program. Note every call to AWT (included Swing, of course) must be encapsulated in a call to EventQueue.invokeLater() to ensure you are running stuff in the AWT thread because setting a label MUST NOT be done outside the AWT thread.
Do not forget to create a thread when you receive an input from AWT that takes time!
Third, replace your loop by a timer like
new Timer("Drawer", true).scheduleAtFixedRate( new TimerTak(){
public void run(){
frame.repaint();
}
},
100, // Start in 100 ms
(int)(1000 / 60)); // 60 is the frame rate.
Everything should work smoothly. For the frame count k, use the following:
// You should initialize just before you create the timer...!
static private long startedAt = System.currentTimeMillis();
#Override public void paintComponent(Graphics g) {
super.paintComponent(g);
// Microseconds since the game started.
long k = (System.currentTimeMillis() - startedAt);
// Increment only one by frame (60 fps)
k = (int)((double)k * 60 / 1000.0)
// Draw the game...!
}
That's all. Note some frames can be dropped if the computer is not enough powerful (or CPU intensive is required, or garbage collector...). But, when possible, your game will run at a maximum of 60 fps.
Bonus: if you increment a value each time you go through the paintComponent(), you can find the number of frames dropped or the average number of frames per second really displayed since the start of the game.

How to save a specific part of a JPanel?

I am working on a chess game and I would like to let the player choose the board's colors. Therefore I will use this method:
static void createBoard(Graphics g) {
Color bright = new Color(255, 225, 181); //player chooses color
Color dark = new Color(188, 141, 105); //player chooses color
boolean darkTile = false;
for (int y = spaceY; y < (spaceY + BOARDHEIGHT); y += TILESIZE) {
for (int x = spaceX; x < (spaceX + BOARDWIDTH); x += TILESIZE) {
if (darkTile) {
g.setColor(dark);
} else {
g.setColor(bright);
}
g.fillRect(x, y, TILESIZE, TILESIZE);
darkTile = !darkTile;
}
darkTile = !darkTile;
}
BufferedImage overlay;
try {
overlay = ImageIO.read(new File("overlay.png"));
JLabel label = new JLabel(new ImageIcon(overlay));
g.drawImage(overlay, spaceX, spaceY, BOARDWIDTH, BOARDHEIGHT, null);
} catch (IOException e) {}
}
This I would like to save as a BufferedImage, so I don't have to run this method all the time.
So how can I save just this part of my JPanel, without the stuff outside of the chess board? (there will be more painted)
This I would like to save as a BufferedImage,
Don't know that your need to save the BufferedImage to a file. You can just create a BufferedImage to be used by the application when the application starts. You can then recreate the BufferedImage if any of the user colors change.
You can paint directly to a BufferedImage:
BufferedImage image = new BufferedImage(boardSize, boardSize, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = image.createGraphics();
// draw the squares onto board
g2d.dispose();
Now your createBoard() method should probably return the BufferedImage so it can be used by your application.
You put in certain efforts to put up your question, so lets honor that with some thoughts to get you going.
First of all: you have an empty catch block {}. That is bad practice. This simply eats up any error messages you get. That is not helpful. Either allow that exception to bubble up and stop your application; or at least print its contents - so that you understand what happens.
And given your comment: you never now if there will be errors. Especially when doing IO, all sorts of things can go wrong. Please believe me: empty catch blocks are bad practice; and you should not train yourself to accept them.
Second thought: don't go for that yet. As convenient as it might sound; but saving a background picture doesn't add much value at this point.
You don't need to worry about this code; it is executed once when your application comes up.
So, the real answer here: focus on the features you want to implement; and don't get distracted with pre-mature optimizations.

Is this a good design for creating smooth animations in Java/Swing?

I have a JPanel subclass with custom paintComponent() implementation. It is being refreshed at 50fps. It is typically in the range of 500x300 pixels in size. I'm seeing some flickering (not too bad but noticeable) and I've inserted some debug code that indicates that Swing/EDT is skipping (presumably) redundant painting. I am guessing that's because the EDT is not giving enough time for paintComponent() to always finish or it is taking too much time on the EDT.
My thinking is that I need to take the code currently implementing paintComponent() (which is not very complex but not completely trivial either) and refactor it so it is executed on its own Thread (or at least not the EDT) and draws to an ImageBuffer. I then implement paintComponent on my custom JPanel and draw (render) from the ImageBuffer to the screen (actually to the buffer behind Swing components as my research into the solution led me some information about Swing being (by default) double-buffered, though I'm not completely clear on that). If it is true that the rendering from the ImageBuffer to the JPanel is faster than my implementation that constructs the ImageBuffer then I will be going in the right direction.
Is this the proper design direction for me to take?
UPDATE
I modified my implementation as discussed in reponses below:
1) Create a BufferedImage
BufferedImage myBufferedImage = new BufferedImage(mySize.width,mySize.height,BufferedImage.TYPE_INT_ARGB)
2) Create a Thread dedicated to peforming the processing to determine what is to be drawn.
3) Move the code previously in paintComponent() to another method that is executed by the dedicated Thread. At the end of this method, call repaint();
4) Create a new paintComponent() that simply calls g.drawImage(myBufferedImage,0,0,null);
5) Where I previously would call repaint(), trigger myThread to perform the drawing to myBufferedImage.
This was a disaster, as predicted. Much worse flickering and sluggishness, partial paints, etc. I believe this was due to contention reading/writing myBufferedImage (as mentioned below). So I then created a lock and lock myBufferedImage when I am writing to it (in the dedicated drawing Thread) and wait to get that lock in paintComponent() before calling Graphics2D.drawImage(); The flicker and partial paints go away - but performance is no better (maybe even worse) than when I was doing all the calculations for the drawing in paintComponent (and therefore in the EDT).
This has me stumped at this point.
If you're not updating the entire component (ie only small areas are changing), you could use JComponent#repaint(Rectangle r) indicating the areas that have changed. This will result in a repaint cycle that updates (potentially) a much smaller area.
I generated a "animated sequence" library some time ago to take a series of images and layer them ontop of each, given a "speed" of each layer, it would transpose them from right to left.
The whole sequence would cycle for 10 seconds, where a speed of 1 would take take 10 seconds to complete. Each layer is moving at difference speeds.
The original images where 1024x256, and the sequence was devised of 5 animated layers and 2 static layers...
I only wish I could show you how smooth this plays on my PC and Mac.
The only signification issue I had to over come was making sure that the images where compatible with the screen devices color model.
UPDATED
These are some utility classes I use when loading or creating BufferedImages, especially for animation. The make sure that the colour models are the same as those used by the screens, which will make them faster to update/repaint
public static BufferedImage loadCompatibleImage(URL resource) {
BufferedImage image = null;
try {
image = ImageIO.read(resource);
} catch (IOException ex) {
}
return image == null ? null : toCompatibleImage(image);
}
public static BufferedImage toCompatibleImage(BufferedImage image) {
if (image.getColorModel().equals(getGraphicsConfiguration().getColorModel())) {
return image;
}
BufferedImage compatibleImage =
getGraphicsConfiguration().createCompatibleImage(
image.getWidth(), image.getHeight(),
image.getTransparency());
Graphics g = compatibleImage.getGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return compatibleImage;
}
public static GraphicsConfiguration getGraphicsConfiguration() {
return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
}
// Check out java.awt.Transparency for valid values
public static BufferedImage createCompatibleImage(int width, int height, int transparency) {
BufferedImage image = getGraphicsConfiguration().createCompatibleImage(width, height, transparency);
image.coerceData(true);
return image;
}
I think this is what you're looking for on information about double buffering:
http://docs.oracle.com/javase/tutorial/extra/fullscreen/doublebuf.html
You could turn off double buffering with setDoubleBuffered(false) if you can't get access to the underlying buffer which I'm not entirely sure you can.
I don't think you can safely draw on an image from another thread because you'll get into the thread writing to the image while the EDT is reading that same image as it redraws. If you share an image between them you're going to have multi-threading issues that you'll have to synchronize. If you synchronize then you're performance isn't going to be very good. If you instantiate a new image every frame you're memory is going to skyrocket and GC will get you. You may be able to instantiate 10 frames and keep the writing away from the reading or something like that, but either way this is going to very tricky to make it performant and correct.
My suggestion is to do all drawing from EDT, and figure out a way to do the calculations (rendering) on another thread that doesn't involve ImageBuffer sharing.
Update While it is used for fullscreen. The suggestions in there apply to windowed mode as well: "Separate your drawing code from your rendering loop, so that you can operate fully under both full-screen exclusive and windowed modes." See this http://docs.oracle.com/javase/tutorial/extra/fullscreen/rendering.html
i've has similar problems trying to paint smoothly.
try running this and see how smooth it is (its smooth for me).
profiler says most of the time is in paint component. interestingly draw image is not mentioned.
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
class P extends JPanel {
void init(Dimension d) {
GraphicsConfiguration gc=getGraphicsConfiguration();
bi=gc.createCompatibleImage(d.width,d.height);
}
#Override public void paintComponent(Graphics g) {
//super.paintComponent(g);
if(bi!=null)
g.drawImage(bi,0,0,null);
}
BufferedImage bi;
}
public class So13424311 {
So13424311() {
p=new P();
}
void createAndShowGUI() {
Frame f=new JFrame("so13424311");
// f.setUndecorated(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.add(p);
p.init(d);
p.setSize(d);
p.setPreferredSize(d);
f.pack();
// if(moveToSecondaryDisplay)
// moveToSecondaryDisplay(f);
f.setVisible(true);
}
void run() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
Timer t=new Timer(20,new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
Graphics g=p.bi.getGraphics();
Color old=g.getColor();
g.fillRect(0,0,d.width,d.height);
g.setColor(Color.red);
g.fillRect(n%(d.width/2),n%(d.height/2),20,20);
g.setColor(Color.green);
g.fillRect(n%(d.width/2)+20,n%(d.height/2),20,20);
g.setColor(Color.blue);
g.fillRect(n%(d.width/2),n%(d.height/2)+20,20,20);
g.setColor(Color.yellow);
g.fillRect(n%(d.width/2)+20,n%(d.height/2)+20,20,20);
g.setColor(old);
g.dispose();
p.repaint();
n++;
}
int n;
});
t.start();
}
public static void main(String[] args) {
new So13424311().run();
}
final P p;
Dimension d=new Dimension(500,300);
}

Appropriate way to draw to a JPanel for 2D Game development?

I am wanting to make a 2D Game but I am having trouble finding the best and most efficient way to draw to a 2D Surface/Canvas using a BufferStrategy. I will be using a JFrame as the main window and want to draw to the surface of that. I would love to see some example code of how this is done (if this is a good way to do it) aswell as other examples. It would be great if someone could also explain some advantages and disadvantages of doing so.
I am currently adding my drawing class to my JFrame using 'frame.add(new Painter());' and then overriding the paintComponent method. The only problem I have found with this is it seems to only call this method once.
this is my Painter class:
public class Painter extends JPanel{
public static Player player;
public Painter() {
player = new Player(300, 300);
}
public void paint(Graphics g) {
player.x++;
g.setColor(Color.white);
g.fillRect(player.x, player.y, 32, 32);
}
}
In the simplest case, where your game needs to update the screen based on user actions only, you will need to call repaint() (on the JFrame for instance) when you update something.
In other cases, you need to construct a so called Game Loop, where you update the game state and render updated game state in a timely manner. A nice tutorial on a simple Game Loop with Java code can be found here: http://obviam.net/index.php/the-android-game-loop/
In case you develop a serious game, you should stick with a game engine for managing the game loop and other routine game development aspects. A good Java game engine can be found here: http://code.google.com/p/playn/
For a game loop and an efficient way to printing to the screen for game objects and others(images, explosions, etc), you need a timing mechanism and a JFrame to print to over and over again, while at the same time, getting updates from the player and the game state itself.
First, you need a main method, and im going to guess that you are pretty new to this type of field in java so I will break it down for you as fast and clearly as possible.
public static main(String[] args)
{
yourClassName game = new yourClassName();
game.run();
System.exit(0);
}
This main method is doing 2 things first, creating an object to your run method (because static references are not recommended for game loops) and then calling that method with your newly created object. When that run method is done, the system will exit the program.
Now im not going into full detail here but once you have the run method running you need an init method that will only run once. In this method, you are going to create your JFrame that you are rendering to. That is fairly simple to do so, so i will not go any farther in creating a JFrame class. However your Run method should look something like this...
void Run()
{
init();
while(isRunning)
{
update();
draw();
time = (1000 / fps) - (System.currentTimeMillis() - time);
if (time > 0)
{
try
{
Thread.sleep(time);
}
catch(Exception e){}
}
}
}
This method will slow the computing speed to a certain fps that you desire(in this case the fps variable is named fps for show).
Now in your update method, you will have your keyBinding and other stuff to look for changes with the keyboard or mouse(and in my case currently, a server). Most people dont know how to print or draw to the JFrame without taking in a paramitor that the Repaint method requires, so we are going to override that by adding double buffering.
BufferedImage backBuffer;
In the initialize method you will add
backBuffer = new BufferedImage(getWidth(),getHeight(),
BufferedImage.TYPE_INT_RGB)
In the draw method you will have...
Graphics g = getGraphics();
Graphics bbg = backBuffer.getGraphics();
And with those you have the ability to draw to the JFrame created by the init class(also, by doing this, you have the ability to draw from any class or thread to decrease the processing load).
To see if it works, go ahead and use the bbg.fillRect(updateX,updateY,5,5)
The updateX and updateY represent variables that you use to update the location of the rectangle. Save them as a global variable or a public variable saved in a character class.
And if all else fails, here is sample code that i have used for creating my own game engine...
import input.InputHandler;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
/**
* Main class for the game
*/
public class GameTutorial extends JFrame
{
boolean isRunning = true;
int fps = 30;
int windowWidth = 500;
int windowHeight = 500;
BufferedImage backBuffer;
Insets insets;
InputHandler input;
int x = 0;
public static void main(String[] args)
{
GameTutorial game = new GameTutorial();
game.run();
System.exit(0);
}
/**
* This method starts the game and runs it in a loop
*/
public void run()
{
initialize();
while(isRunning)
{
long time = System.currentTimeMillis();
update();
draw();
// delay for each frame - time it took for one frame
time = (1000 / fps) - (System.currentTimeMillis()- time);
if (time > 0)
{
try
{
Thread.sleep(time);
}
catch(Exception e){}
}
}
setVisible(false);
}
/**
* This method will set up everything need for the game to run
*/
void initialize()
{
setTitle("Game Tutorial");
setSize(windowWidth, windowHeight);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
insets = getInsets();
setSize(insets.left + windowWidth + insets.right,
insets.top + windowHeight + insets.bottom);
backBuffer = new BufferedImage(windowWidth, windowHeight, BufferedImage.TYPE_INT_RGB);
input = new InputHandler(this);
}
/**
* This method will check for input, move things
* around and check for win conditions, etc
*/
void update()
{
if (input.isKeyDown(KeyEvent.VK_RIGHT))
{
x += 5;
}
if (input.isKeyDown(KeyEvent.VK_LEFT))
{
x -= 5;
}
}
/**
* This method will draw everything
*/
void draw()
{
Graphics g = getGraphics();
Graphics bbg = backBuffer.getGraphics();
bbg.setColor(Color.WHITE);
bbg.fillRect(0, 0, windowWidth, windowHeight);
bbg.setColor(Color.BLACK);
bbg.drawOval(x, 10, 20, 20);
g.drawImage(backBuffer, insets.left, insets.top, this);
}
}
I hope this helps and I know this may be a VERY late answer but i have yet to see one decent java game engine that was simple to understand and use and fun to work with. Hope you stay with it and happy programming!!!

Categories

Resources