I have a weird issue that every other guide and answer seems to contradict, but the issue seems to be deeper. OS-level deep.
System details:
Ubuntu 18.04, Unity window manager, nVidia graphics (proprietary driver)
Tried with the following Java VMs:
-OpenJDK 11 & 17,
-Temurin 11 & 17,
-JBR-17
I have an application where I draw an image on a canvas, zoomed (so it's pixelated), and I can pan around and edit with the mouse (sort of like photoshop). I do this by defining a small rectangle in the image and drawing that to the entire panel (at 4K resolution):
g.drawImage(image,
x, // dst
y,
x + visibleImageWidth * blockSize,
y + visibleImageHeight * blockSize,
ul.x, // src
ul.y,
ul.x + visibleImageWidth,
ul.y + visibleImageHeight,
this);
This works fine statically, but when I start working it with the mouse, it progressively slows down to a crawl.
I analyzed this, and it seems that the mouse fires events at 1000Hz. Then paintComponent() somehow manages to finish within that same 1ms. The OS however chokes on the amount of visual data thrown at it, and every (visual) update takes longer than the last. As long as I keep dragging the mouse, the OS crawls to a complete stop. (It seems everything non-graphical still works at normal speed, e.g. my program keeps processing input) Also visual updates of other programs stop, so it's like the graphics card or driver chokes on the data and can't process/discard it fast enough. When I let go of the mouse it stays frozen until next visual update. Then all programs instantly update their visuals and everything is back to normal.
The (heavyweight) JPanel that I have doesn't collate repaint() calls where I expect it should. Every time I call it, it immediately (from my perspective) calls paintComponent(), which finishes within 1ms, before the next call to repaint().
* Why is Java so insistent on sending graphics data to the OS at such a ridiculous speed? My monitor runs at 60Hz, not 1000Hz.
I found a very dirty workaround that at least lets me use the program in any reasonable way at all: Adding
try {
Thread.sleep(10);
} catch (InterruptedException ignored) {
}
at the end of the paintComponent() method. The program now works super smooth, without visible tearing or microstuttering (even though 10ms != 60Hz).
Why do I need this delay to, of all things, speed up graphics? How can I make Java respect the monitor's refresh rate in a 'neater' way?
[Edit] MSSCC
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class Temp extends JPanel {
public static void main(String... args) {
System.out.println(LocalDate.now());
SwingUtilities.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.setContentPane(new Temp());
f.setExtendedState(Frame.MAXIMIZED_BOTH);
f.setVisible(true);
});
}
private final BufferedImage image = new BufferedImage(10000, 10000, BufferedImage.TYPE_INT_RGB);
public Temp() {
super(null);
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
int x = e.getX() / 5;
int y = e.getY() / 5;
int rgb = ThreadLocalRandom.current().nextInt(0xFFFFFF);
int[] pixels = new int[100];
Arrays.fill(pixels, rgb);
image.getRaster().setDataElements(x, y, 8, 8, pixels);
repaint();
((Frame)getTopLevelAncestor()).setTitle(" (" + x + ", " + y + ')');
}
});
}
#Override
public void paintComponent(Graphics g) {
g.drawImage(image,
0, 0, getWidth(), getHeight(),
0, 0, getWidth() / 5, getHeight() / 5,
null);
}
}
Back in the day I created a Paint widget to draw like you'd do in MS Paint - and I definitely did not experience mouse move events firing at the rate you are reporting. As #GilbertLeBlanc commented, it seems like you are probably in an infinite paint loop.
Nevertheless, if this isn't the issue, you can throttle event firing like this
public class Throttle extends MouseMotionAdapter {
public static final long THRESHHOLD = 30; //ms
private lastEvTime = 0;
public void mouseMoved(MouseEvent me) {
long time = System.currentTimeMillis();
if (time > (lastEvTime + THRESHHOLD)) {
lastEvTime = time;
//do graphical update
}
// else do nothing
}
}
Related
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.
I am trying to make a digital clock in this way:
As shown in the image 1 i want the clock to be reflected.
What i have tried:
I tried using java (Graphics2D)g by rotating the string and the using substring but i got this problem:
My code for this:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Calendar;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class DigitalClock extends JPanel {
JLabel label = new JLabel();
int c = 0;
Font font = null;
JFrame frame = new JFrame();
//Constructor
public DigitalClock(){
frame.setSize(700,500);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(this);
frame.setVisible(true);
DigitalThread();
}
//Paint Method
public void paintComponent(Graphics g){
Graphics2D g2d = (Graphics2D)g;
//The background
g2d.setColor(Color.BLACK);
g2d.fillRect(0,0,500,100);
//Show Time
g2d.setColor(Color.WHITE);
g2d.setFont(new Font(g.getFont().toString(),10,15));
g2d.drawString(timeNow(),100, 25);
//Show time Reflected
g2d.rotate(Math.PI,100,25);
g2d.drawString(timeNowRot(timeNow()),45, 20);
}
//Change time Value with this Thread
public void DigitalThread(){
new Thread(new Runnable(){
public void run(){
boolean flag=true;
while(flag==true){
try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}
repaint();
}
}}).start();
}
//Return time
public String timeNow(){
return zero(Calendar.getInstance().get(Calendar.HOUR_OF_DAY))+":"+
zero(Calendar.getInstance().get(Calendar.MINUTE))+":"+zero(Calendar.getInstance().get(Calendar.SECOND));
}
//Return time reflected
public String timeNowRot(String time){
return time.substring(time.length()-1,time.length())+time.substring(time.length()-2,time.length()-1)+":";
}
//Add Zero if value<10
public String zero(int num){
if(num<10) return "0"+num;
else return ""+num;
}
}
I can achieve this by using java 2d? is there a method to rotate a string again vertically so i have not this problem thanks..
Use scale(x, y) which multiplies the x and y coordinates.
g2d.scale(1.0, -1.0);
g2.drawString(....);
g2d.scale(1.0, -1.0); // Undo
This does a transformation where the y axis is reversed.
You could also use shear for a paralellogram look.
A g2d.scale(-1.0, 1.0); would draw the string backwards. Can be used in combination with the rotation.
It allt depends on the usage of any rotation and the order, how to scale. Without rotation: scale y by -1:
good
ƃooq
Actually i found the answer based n your answers thanks all:
It is and irony but the next day after the question i had a lesson at university about that...
Info about scaling:
g2d.scale(1,-1); /*scale by y axes(Flipping vertical
|
flip here (scale(-1,1) ) | here it was
_ _ _ _ _|_ _ _ _ _
|
flip here (scale(-1,-1) ) | fliped here( scale(1,-1) )
|
*/
g2d.drawString(timeNow(),10,-27);
I also added some more effect so the clock be more realistic like:
g2d.setPaint(new GradientPaint(0,-15,color,0,-50,Color.BLACK));
Your link shows a clock face AND its reflection. If that's what you want to do then this is the way.
Draw the clock face into an Image, instead of direct to the Component. Then you render the resulting image into the component twice using drawImage - once the normal way, and once transformed so it looks reflected.
This uses slightly more memory, but only temporarily, and it saves you having to do the paint twice.
If you only want to draw the reflected clock face, then set the image transformation properties in the Graphics to get the reflection.
I'll leave the details as an exercise to the reader.
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.
I have an application where I want to draw an image that grows in width over time. Specifically, the application listens to the microphone and computes a spectrogram every 6 milliseconds, and I want to draw the updated spectrogram when it comes in. I've been using java.awt.image.BufferedImage to draw the spectrograms, but only for pre-recorded files, so I have a fixed width for the image. What's the best way to do this for a streaming application, where I don't know a priori the width of the image?
One possibility is to just create a new BufferedImage with one extra pixel on the right and copy the data over, but that seems inefficient to do hundreds of times per second. Or I could start with a relatively large width and keep the right side blank until it fills up, and double the width when it does, similar to how an ArrayList amortizes its size - I would only have to copy the data a few times per second, or once every few seconds, or so. Is there a better option?
I would use a combination of what you suggest and an overriding component that only paints a subimage of the total image and returns an appropriate preferred size.
Here is a demo code which shows what I mean:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class TestRecording {
public static class MyPanel extends JPanel {
private BufferedImage buffer = new BufferedImage(3000, 100, BufferedImage.TYPE_INT_RGB);
private int width = 0;
private int lastY = 50;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (width > 0) {
BufferedImage sub = buffer.getSubimage(0, 0, width, buffer.getHeight());
g.drawImage(sub, 0, Math.max(0, (getHeight() - buffer.getHeight()) / 2), this);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(width, 100);
}
protected void drawSomething() {
// Here need to handle growing image
Graphics g = buffer.getGraphics();
g.setColor(Color.GREEN);
int y = new Random().nextInt(buffer.getHeight());
g.drawLine(width, lastY, width + 1, y);
lastY = y;
width += 1;
Rectangle r = new Rectangle();
r.x = getWidth();
// Lame hack to auto-scroll to the end
scrollRectToVisible(r);
revalidate();
repaint();
}
}
protected void initUI() {
JFrame frame = new JFrame(TestRecording.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final MyPanel p = new MyPanel();
JScrollPane scrollpane = new JScrollPane(p);
frame.add(scrollpane);
frame.setSize(400, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Timer t = new Timer(20, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
p.drawSomething();
}
});
t.start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestRecording().initUI();
}
});
}
}
And here is the result:
May be just scale the original image to get desired size.
Image has getScaledInstance(int width, int height, int hints) method
Do you have 1) gui where you draw it, or 2) do you need to realy output image file (or stream)?
if 1)
Draw only what is seen. Extend JComponent, I usually use JPanel and override paintComponent and paint what is visible.
To make it more efficient, create "tiles" - list of eg. BufferedImage of constant width and create them from incoming data and draw to gui only them.
2) Something similar, but you can use one image with relatively low width and draw new data to it. When full, "append" it to so far created "left" image (initially empty). This way you frequently modify small image and big not so frequently.
If end comes before filling whole right image, join only filled part with left.
You could try to gradually increase size of right image (*X, eg *1.5 or *2) to reduce number of joining images at cost of using more memory.
You could store those "images" as byte(or int) array (1D array representing 2D, but store it by columns, not by rows for more efficient modifications), this way you can store it bit more efficiently if you know that you need some unusual ammount of bits per pixels, because some colors will never be in result image.
If image gets too big, save it to disk and clear your left image and later join them together or use them separately.
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!!!