How to set JFrame in fullscreen using users native resolution? - java

I am trying to create a little game for a project in university. Since I need to update the screen permanently I am looking for a good render loop implementation. It should be full screen. I found this on gamedev.net - Java Games: Active Rendering:
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.JFrame;
public class SimpleFullScreenGame {
static boolean running;
public static void main( String[] args ) {
// Create game window...
JFrame app = new JFrame();
app.setIgnoreRepaint( true );
app.setUndecorated( true );
// Add ESC listener to quit...
app.addKeyListener( new KeyAdapter() {
public void keyPressed( KeyEvent e ) {
if( e.getKeyCode() == KeyEvent.VK_ESCAPE )
running = false;
}
});
// Get graphics configuration...
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gd.getDefaultConfiguration();
// Change to full screen
gd.setFullScreenWindow( app );
if( gd.isDisplayChangeSupported() ) {
gd.setDisplayMode(
new DisplayMode( 640, 480, 32, DisplayMode.REFRESH_RATE_UNKNOWN )
);
}
// Create BackBuffer...
app.createBufferStrategy( 2 );
BufferStrategy buffer = app.getBufferStrategy();
// Create off-screen drawing surface
BufferedImage bi = gc.createCompatibleImage( 640, 480 );
// Objects needed for rendering...
Graphics graphics = null;
Graphics2D g2d = null;
Color background = Color.BLACK;
Random rand = new Random();
// Variables for counting frames per seconds
int fps = 0;
int frames = 0;
long totalTime = 0;
long curTime = System.currentTimeMillis();
long lastTime = curTime;
running = true;
while( running ) {
try {
// count Frames per second...
lastTime = curTime;
curTime = System.currentTimeMillis();
totalTime += curTime - lastTime;
if( totalTime > 1000 ) {
totalTime -= 1000;
fps = frames;
frames = 0;
}
++frames;
// clear back buffer...
g2d = bi.createGraphics();
g2d.setColor( background );
g2d.fillRect( 0, 0, 639, 479 );
// draw some rectangles...
for( int i = 0; i < 20; ++i ) {
int r = rand.nextInt(256);
int g = rand.nextInt(256);
int b = rand.nextInt(256);
g2d.setColor( new Color(r,g,b) );
int x = rand.nextInt( 640/2 );
int y = rand.nextInt( 480/2 );
int w = rand.nextInt( 640/2 );
int h = rand.nextInt( 480/2 );
g2d.fillRect( x, y, w, h );
}
// display frames per second...
g2d.setFont( new Font( "Courier New", Font.PLAIN, 12 ) );
g2d.setColor( Color.GREEN );
g2d.drawString( String.format( "FPS: %s", fps ), 20, 20 );
// Blit image and flip...
graphics = buffer.getDrawGraphics();
graphics.drawImage( bi, 0, 0, null );
if( !buffer.contentsLost() )
buffer.show();
} finally {
// release resources
if( graphics != null )
graphics.dispose();
if( g2d != null )
g2d.dispose();
}
}
gd.setFullScreenWindow( null );
System.exit(0);
}
}
I executed the code and there are two things I am wondering about:
My display resolution is 1920x1080. The code is using 640x480. Therefore the rendered rectangles look like a 640x480 picture upscaled to 1920x1080 meaning you have huge pixels and the code doesn't take avantage of the higher posible resolution of the display. How can I adapt the code to actually use the native display resolution of the user?
Second, usually what you see when you take a look on games code is a rendering loop living in its own thread to not block the main thread. However thats not the case here. Why? I assume because the JFrame already lives in its own thread created by swing?
Thanks for the help.

There are lots of issues with this code.
First of all, when you are checking (polling) a flag variable in the main thread, that will be updated by a key listener, which will be called in the event dispatch thread, the minimum you have to do, is to declare that variable volatile.
Then, there is no point in using JFrame when you don’t use the Swing framework at all. Further, it’s nonsensical to request double buffering from the AWT and then, use a BufferedImage for another buffering atop the already buffered operation.
Using the native resolution is as easy as removing the setDisplayMode(…) call. After turning the window to full screen, you can simply use getWidth() and getHeight() on it to get the actual dimensions for the operations (it’s not needed for the buffered image, as that was obsolete anyway).
public class SimpleFullScreenGame {
static volatile boolean running = true;
public static void main(String[] args) {
// Create game window...
Frame app = new Frame();
app.setIgnoreRepaint(true);
app.setUndecorated(true);
// Add ESC listener to quit...
app.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ESCAPE) running = false;
}
});
GraphicsDevice dev = app.getGraphicsConfiguration().getDevice();
// Change to full screen
dev.setFullScreenWindow(app);
int width = app.getWidth(), height = app.getHeight();
// Create BackBuffer...
app.createBufferStrategy(2);
BufferStrategy buffer = app.getBufferStrategy();
// Objects needed for rendering...
Color background = Color.BLACK, textColor = Color.GREEN;
Font font = new Font("Courier New", Font.PLAIN, 12);
ThreadLocalRandom rand = ThreadLocalRandom.current();
// Variables for counting frames per seconds
int fps = 0, frames = 0, totalTime = 0;
long currTime = System.nanoTime(), lastTime;
while(running) {
// count Frames per second...
lastTime = currTime;
currTime = System.nanoTime();
totalTime += currTime - lastTime;
if(totalTime > 1_000_000_000) {
totalTime -= 1_000_000_000;
fps = frames;
frames = 0;
}
frames++;
Graphics gfx = buffer.getDrawGraphics();
gfx.setColor(background);
gfx.fillRect(0, 0, width, height);
// draw some rectangles...
for(int i = 0; i < 20; ++i) {
gfx.setColor(new Color(rand.nextInt(0x1000000)));
int x = rand.nextInt(width/2), y = rand.nextInt(height/2);
int w = rand.nextInt(width/2), h = rand.nextInt(height/2);
gfx.fillRect(x, y, w, h);
}
// display frames per second...
gfx.setFont(font);
gfx.setColor(textColor);
gfx.drawString("FPS: " + fps, 20, 20);
gfx.dispose();
if(!buffer.contentsLost()) buffer.show();
}
dev.setFullScreenWindow(null);
System.exit(0);
}
}
I made some other small improvements.

Related

Changing brightness depending on sound (Processing)

I am learning processing right now and I am trying to make a sketch that could change colour when the sound changes.
(When Amplitude + ,
Then Brightness+ )
Because changing colour does not need to change as rapid as the draw() function. So how could I build a clock so that the color would not change in every draw?
This is the code I am using right now:
import ddf.minim.*;
import ddf.minim.signals.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
Minim minim;
AudioPlayer song;
FFT fft;
BeatDetect beat;
color start=color(0,0,0);
color finish;
float amt = 0.0;
void setup()
{
frameRate(50);
size(600,600,P3D);
minim = new Minim(this);
song = minim.loadFile("song2.mp3", 512);
song.loop();
fft = new FFT(song.bufferSize(), song.sampleRate());
beat = new BeatDetect(song.bufferSize(), song.sampleRate());
}
// draw is run many times
void draw()
{
float brightness = map( 0, 0, song.bufferSize(), 0, 255 );
background( brightness );
// println(song.bufferSize());
stroke(100);
// draw the waveforms
for( int i = 0; i < song.bufferSize() - 1; i++ )
{
// find the x position of each buffer value
float x1 = map( i, 0, song.bufferSize(), 0, width );
float x2 = map( i+1, 0, song.bufferSize(), 0, width );
// draw a line from one buffer position to the next for both channels
line( x1, 50 + song.left.get(i)*50, x2, 50 + song.left.get(i+1)*50);
line( x1, 150 + song.right.get(i)*50, x2, 150 + song.right.get(i+1)*50);
println(x1);
}
}
When you call frameRate(50); you are telling Processing to (try to) update the draw() 50 times a second. You can tell how many frames have passed since the start of the sketch by checking the built-in variable frameCount.
This can then be divided by a number which represents how many frames you want to draw before doing something special - I would use modulus for this, it will divide the numbers and return the remainder. If it equals 0, then that number of frames have passed.
int updateTriggerCount = 10;
void setup() {
...
}
void draw()
{
if((frameCount % updateTriggerCount) == 0)
{
// Another 10 frames have passed! Do something special
}
....
}
Trusting in frameRate to control timing is ok, but is, of course, frameRate dependent. Meaning that if your frameRate drops the timimg will drop together.
To avoid that, you may use millis() and attach your timing to, well time :)
Here a very simple timer example:
PFont font;
String time = "000";
int initialTime;
int interval = 1000;//one second
color bg = color (255);
void setup()
{
size(300, 300);
font = createFont("Arial", 30);
background(255);
fill(0);
initialTime = millis();
frameRate(30);// changed framerate to exemplify
}
void draw()
{
background(bg);
if (millis() - initialTime > interval)
{
time = nf(int(millis()/1000), 3);
initialTime = millis();
bg = color (random(255), random(100), random(255));
}
text(time, width/2, height/2);
}

Jittery movement with Graphics2D and double buffer

I´m having some problems with a small game I´m developing. although I´m using double buffer and was able to get rid of flickering, the movement still looks somewhat jittery and not fluid.
I know it can be caused by increasing the movement in big steps and/or low framerate, but I still have the same problem using increments of 1 and 50+ fps. It´s somewhat difficult to explain, but the sprites move strangely (correctly, but not in a fluid motion)
I would appreciate if someone could point me in the right direction.
public class Gameplay extends javax.swing.JPanel {
GUI gui;
Canvas canvas = new Canvas();
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gd.getDefaultConfiguration();
BufferedImage bi;
BufferStrategy buffer;
public Gameplay(GUI gui) {
this.gui = gui;
initComponents();
}
// Used to start the gameplay. Called by GUI
public void start() {
new RefreshScreen().start();
}
// ==============================================================================================
// DOUBLE BUFFER AND PAINTING ===================================================================
// ==============================================================================================
Date date = new Date(); // time
int lastSecond = 0; // seconds controll - for FPS calculation
int fpsCount = 0; // Count frames rendered
int showFps = 0; // The total FPS text that will appear on screen
int MAX_FPS = 30; // targeted Max FPS
int MIN_FPS = 24; // targeted Min FPS
int sleepTimeBetweenRefresh = 20; // Delay before new refresh
Color fpsColor = Color.yellow; // color of the FPS information on screen
String fpsInfo = ""; // Aditional info on FPS (increasing, decreasing, etc)
class RefreshScreen extends Thread {
public void run() {
Graphics graphics = null;
Graphics2D bufferGraphics = null;
add(canvas, BorderLayout.CENTER);
canvas.setIgnoreRepaint(true);
canvas.setVisible(true);
canvas.setSize(gui.getWidth(), gui.getHeight());
canvas.createBufferStrategy(2);
buffer = canvas.getBufferStrategy();
bi = gc.createCompatibleImage(gui.getWidth(), gui.getHeight());
bufferGraphics = bi.createGraphics();
while (true) {
try {
//FrameRate count
date = null;
date = new Date();
if (lastSecond != date.getSeconds()) {
lastSecond = date.getSeconds();
showFps = fpsCount;
fpsCount = 0;
if (showFps > MAX_FPS) {
sleepTimeBetweenRefresh++;
fpsInfo = "(--)";
fpsColor = Color.blue;
}
if ((showFps < MIN_FPS) && (sleepTimeBetweenRefresh > 5)) {
sleepTimeBetweenRefresh--;
fpsInfo = "(++)";
}
if (showFps < MIN_FPS) {
fpsColor = Color.red;
}
if ((showFps > MIN_FPS) && (showFps <= MAX_FPS)) {
fpsColor = Color.green;
fpsInfo = "(ok)";
}
}
fpsCount++;
//Clear canvas =============================
bufferGraphics.setColor(Color.black);
bufferGraphics.clearRect(0, 0, gui.getWidth(), gui.getHeight());
//FPS =============================
bufferGraphics.setColor(fpsColor);
bufferGraphics.drawString("FPS: " + showFps, 3, 15);
bufferGraphics.setColor(Color.black);
//SPRITES =============================
try {
for (int count = 0; count < Sprites.getSprites().size(); count++) {
bufferGraphics.drawImage(Sprites.getSprite(count).getImage(), Sprites.getSprite(count).getX(), Sprites.getSprite(count).getY(), null);
}
} catch (Exception e) { }
//HERO =============================
try {
bufferGraphics.drawImage(Sprites.getHero().getImage(), Sprites.getHero().getX(), Sprites.getHero().getY(), null);
} catch (Exception e) { }
// PAINT BUFFER =================================
try {
graphics = buffer.getDrawGraphics();
graphics.drawImage(bi, 0, 0, null);
if (!buffer.contentsLost()) {
buffer.show();
}
} catch (Exception e) { }
// SLEEP =================================
sleep(sleepTimeBetweenRefresh);
} catch (Exception e) { }
}//while
}//run
}//inner class
I would also like to point out that the X and Y of the sprite are being handled so that it doesn´t go right and then down - for instance - when it is supposed to go diagonally. I don´t suppose that´s the problem anyways since the problems occurs even on a straight line.
You might try timing how long it takes to draw everything then subtracting that from your sleep time.
long beforeTime = System.currentTimeMillis();
// do all drawing
sleepTimeBetweenRefresh -= System.currentTimeMillis() - beforeTime;
if(sleepTimeBetweenRefresh < 0) sleepTimeBetweenRefresh = 0;
This helps ensure that your thread is firing every 50ms (or whatever sleepTimeBetweenRefresh is). Say you want it to fire ever 50ms, your drawing takes 10ms. Without the code above after the code ran one time you would actually be painting 60ms after the last paint because you painted for 10 and slept for 50. By subtracting the time it took to paint the components you can keep your FPS stable.

High speed, between-frame, graphics architecture for java

I need to plot animated frames in which each pixel is calculated on the fly as the result of an algorithm. Full screen animations may thus require many millions of operations per frame. I would like to achieve the highest refresh rate possible, preferably 20 to 30+ frames per second, if possible.
Can someone show me how to design/write a highly optimized architecture for extremely fast frame refreshment in java?
This needs to be platform independent, so I cannot take advantage of hardware acceleration. The code will be executed on each individual user's computer, NOT on a central server. Of course, I am separately approaching this from the standpoint of simplifying the algorithms for generating the pixel values within-each-frame, but this question is about architecture for high speed frame-by-frame refreshment between-frames, independent of the algorithm used to generate pixel values within each frame. For example, in answers to this posting, I am looking for methods such as using: BufferedImage, double-buffering, multi-threading, accelerated off-screen images, other between-frames methods, etc.
I wrote some sample code below to simulate the problem. At full screen on my notebook computer, the code below individually refreshes 1,300,000+ pixels per frame with unique values. This takes 500 milliseconds per frame on a machine with four processors and 8 gigabytes of memory. I suspect that I am not using BufferedImage correctly below, and I would really like to learn about other between-frame, architecture-level techniques for optimizing the code below, independent of the algorithms I will end up using to calculate pixel values within-each-frame. Your code samples and links to articles would be much appreciated.
How can I improve the code below, from an frame-by-frame (between-frames) architecture standpoint, not from a within-frame standpoint?
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class TestBuffer {
private static void createAndShowUI() {
TestPanel fastGraphicsPanel = new TestPanel();
JFrame frame = new JFrame("This Needs A Faster Architecture!");
frame.getContentPane().add(fastGraphicsPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(800,600));
frame.setResizable(true);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {createAndShowUI();}});}
}
#SuppressWarnings("serial")
class TestPanel extends JPanel {
int w, h;
private static int WIDTH = 700;
private static int HEIGHT = 500;
private static final Color BACKGROUND_COLOR = Color.white;
private BufferedImage bImg;
private Color color = Color.black;
public TestPanel() {
bImg = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
Graphics g = bImg.getGraphics();
g.setColor(BACKGROUND_COLOR);
g.fillRect(0, 0, WIDTH, HEIGHT);
Timer myTimer = new Timer(10, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(w!=0&&h!=0){
if(WIDTH!=w&&HEIGHT!=h){
WIDTH = w; HEIGHT = h;
bImg = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
}
}
repaint();
}
});
myTimer.setInitialDelay(0);
myTimer.setRepeats(true);
myTimer.setCoalesce(true);
myTimer.start();
g.dispose();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
w = getWidth();
h = getHeight();
// System.out.println("w, h are: "+w+", "+h);
long startTime = System.currentTimeMillis();
g.drawImage(bImg, 0, 0, null);
long endDrawImageTime = System.currentTimeMillis();
Graphics2D g2 = (Graphics2D) g;
drawRandomScreen(g2);
long endDrawScreenTime = System.currentTimeMillis();
long stopTime = System.currentTimeMillis();
long drawImageTime = endDrawImageTime - startTime;
long drawScreenTime = endDrawScreenTime - endDrawImageTime;
long elapsedTime = stopTime - startTime;
System.out.println(drawImageTime+", "+drawScreenTime+", "+elapsedTime);
}
private void drawRandomScreen(Graphics2D g2) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for(int i=0;i<WIDTH;i++){
for(int j=0;j<HEIGHT;j++){
color = new Color((int) (Math.random() * 255),(int) (Math.random() * 255),(int) (Math.random() * 255));
g2.setColor(color);
g2.drawLine(i, j, i, j);
}
}
}
}
In the example given, drawRandomScreen() executes on the event dispatch thread. As an alternative, let the model evolve on a separate thread (or threads) and sample the resulting image at a sustainable rate, say 25 Hz, using the observer pattern. Synchronize access to the shared image buffer. A complete example is examined here. Profile to verify ongoing optimization efforts.
instead of interacting through Graphics2D you should interact direct with image data. This is my code, with my laptop can run with 20 frame/second (fullscreen)
#SuppressWarnings("serial")
class TestPanel extends JPanel {
int w, h;
private static int WIDTH = 700;
private static int HEIGHT = 500;
private static final Color BACKGROUND_COLOR = Color.white;
private BufferedImage bImg;
private Color color = Color.black;
public TestPanel() {
bImg = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
Graphics g = bImg.getGraphics();
g.setColor(BACKGROUND_COLOR);
g.fillRect(0, 0, WIDTH, HEIGHT);
Timer myTimer = new Timer(10, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(w!=0&&h!=0){
if(WIDTH!=w&&HEIGHT!=h){
WIDTH = w; HEIGHT = h;
System.out.println("create");
bImg = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
}
}
repaint();
}
});
myTimer.setInitialDelay(0);
myTimer.setRepeats(true);
myTimer.setCoalesce(true);
myTimer.start();
g.dispose();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
w = getWidth();
h = getHeight();
// System.out.println("w, h are: "+w+", "+h);
long startTime = System.currentTimeMillis();
long endDrawImageTime = System.currentTimeMillis();
// Graphics2D g2 = (Graphics2D) g;
drawRandomScreen(bImg);
g.drawImage(bImg, 0, 0, null);
long endDrawScreenTime = System.currentTimeMillis();
long stopTime = System.currentTimeMillis();
long drawImageTime = endDrawImageTime - startTime;
long drawScreenTime = endDrawScreenTime - endDrawImageTime;
long elapsedTime = stopTime - startTime;
System.out.println(drawImageTime+", "+drawScreenTime+", "+elapsedTime);
}
private void drawRandomScreen(BufferedImage image) {
final int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
final int width = image.getWidth();
final int height = image.getHeight();
long startTime = System.currentTimeMillis();
// g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
// RenderingHints.VALUE_ANTIALIAS_ON);
Random r = new Random();
for(int i=0;i<width;i++){
for(int j=0;j<height;j++){
color = new Color(r.nextInt(255),r.nextInt(255),r.nextInt(255));
int pos = j*width+i;
pixels[pos] = color.hashCode();
}
}
long stopTime = System.currentTimeMillis();
System.out.println("time "+(stopTime-startTime));
}
}
This is your new code. In my laptop, fullscreen can run at 150 frames/ second. At you can see, time execution of function drawRandomScreen only 1/2 time of drawImageTime.
private void drawRandomScreen(BufferedImage image) {
final int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
final int width = image.getWidth();
final int height = image.getHeight();
long startTime = System.currentTimeMillis();
Random r = new Random();
int size = pixels.length;
//swap 100 times
int maxPixelsSwap = 1000;
size-=maxPixelsSwap;
for (int i = 0; i < 100; i++) {
int src = r.nextInt(size);
int des = src+r.nextInt(size-src);
int swapsize = r.nextInt(maxPixelsSwap); //maximium
int[] temp = new int[swapsize];
System.arraycopy(pixels, des, temp, 0, swapsize);
System.arraycopy(pixels, src, pixels, des, swapsize);
System.arraycopy(temp, 0, pixels, src, swapsize);
}
size = pixels.length;
int randomTimes = size/10; //only change 10% of pixels
size--;
for (int i = 0; i < randomTimes; i++) {
pixels[r.nextInt(size)]=r.nextInt();
}
long stopTime = System.currentTimeMillis();
System.out.println("time "+(stopTime-startTime));
}

Attempting to create progress bars

This is just an exercise in mechanics. I am attempting to create three custom panels that control their own progress bar. It’s part of a time management program I am writing for myself to learn more about Java. The larger program uses dates input by the user to create the framework for the min/max of the progress bar. Both this program and the larger one exhibit the same behavior with multiple bars racing the clock.
The issue I am having is that if I have just one bar everything seems to work just fine, but when I have more than one everything seems to go bust. So I wrote this little program to test some things out. It’s very simple, takes three custom panels, gives them a label and uses a timer event to change the label and the position of the progress bar. My question is If the math lines up (System output shows the calculation) and I’m counting events every second (1000 milliseconds) why is everything beating the count down.
Please forgive my lack of form with my code. I’m more concerned with the logic than the form.
(Most of the below is cut from my larger program, so if you see extraneous bits they really do have a home)
Thank you in advance.
import javax.swing.*;
import javax.swing.Timer;
import java.awt.*;
import java.awt.Color;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
public class plaything extends JFrame implements ActionListener
{
myPanel[] mp = new myPanel[3];
JLabel[] jl = new JLabel[3];
short[] tim = new short[3];
short x = 0;
short t = 0; //used to stagger the clocks
short dateSaver; //holds temp dates
public plaything()
{
setSize(400, 350);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new GridLayout(3, 1) );
for(short x = 0; x < 3; x++)
{
mp[x] = new myPanel();
//sets all three bars to different 'times'
dateSaver = (short)(10 + t) ;
tim[x] = dateSaver;
mp[x].setMax( dateSaver );
jl[x] = new JLabel("Expires: " + dateSaver);
this.add(mp[x]);
mp[x].add( jl[x] );
t += 15; // 15 seconds
}
Timer time = new Timer(1000, this);
time.start();
}
public void actionPerformed(ActionEvent e)
{
if ( x < 60 )
{
x++;
}
else
{
x = 1;
}
for(myPanel m : mp)
{
m.tock();
}
for(short x = 0; x < 3; x++ )
{
mp[x].tock();
jl[x].setText( "" + --tim[x] );
}
}
private class myPanel extends JPanel
{
//Fields
private boolean finished = false;
//(x,y) Coords
private short x = 15;
private short y = 50;
//Size and shape
private short width = 200;
private short height = 10;
private short arcSize = 10;
//Bar essentials
private double max; //highest range of bar
private double fill = width; //sets filled in portion
private double tick; //calculates movement per event
private Color urgent = Color.BLUE; // Changes the color depending on the Urgency
//Constructors
public myPanel()
{
this.setBackground( Color.WHITE );
repaint();
}
//Mutators ( tick manipulation )
public void setMax( double maxIn )
{
this.max = maxIn;
System.out.println("Max: " + this.max );
this.tick = (double)width / this.max;
System.out.println("tick: " + this.tick );
}
//Methods
//Tick Manipulation
public void tock()
{
//Ends when zero
if( fill < 1 )
{
fill = width;
finished = true;
tick = 0;
urgent = Color.BLUE;
repaint();
}
else
{
fill -= tick ;
System.out.println("fill is " + fill );
repaint();
}
}
//Paint method
public void paint( Graphics g)
{
super.paint(g);
Graphics2D g2 = (Graphics2D)g;
g2.setColor( urgent );
g2.draw(new RoundRectangle2D.Double(x,y + 40, width, height, arcSize, arcSize) );
g2.fill(new RoundRectangle2D.Double(x,y + 40, fill , height, arcSize, arcSize) );
}
}
public static void main(String[] args)
{
plaything pt = new plaything();
pt.setVisible(true);
}
}
My real only concern is where is my logic flawed concerning the progression of the bars and the labels. I hope to find how to make both reach zero together. (two days of research and work on just the bars alone)
Again thank you for your time.
You're calling tock() twice every iteration of your Timer:
for(myPanel m : mp)
{
m.tock(); // ONCE
}
for(short x = 0; x < 3; x++ )
{
mp[x].tock(); // TWICE
jl[x].setText( "" + --tim[x] );
}
You should remove one call, or the other.

Drawing performance in Java 6 updates 19,20 versus Java 6 update 3?

I'm getting twice the frame rate with the earlier Java 6 u 3, than with the new ones. Very weird. Can anyone give some explanation?
On Core 2 Duo 1.83ghz, integrated video (only one core is used) - 1500 (older java) vs 700 fps
On Athlon 64 3500+, discrete video - 120 (older java) vs 55 fps
The app is a simple game with a moving rectangle. I'm using Graphics2D to draw from a loop.
Edit: Some code. The whole thing is big, this are some important parts only.
public class SimpleRenderer extends JFrame{
SimpleGameEngine sge;
Canvas canvas; // Our drawing component
static final int WIDTH = 640;
static final int HEIGHT = 480;
Graphics2D g2d = null;
Graphics graphics = null;
Color background = Color.BLACK;
BufferedImage bi;
BufferStrategy buffer;
public SimpleRenderer(KeyboardInput keyboard, SimpleGameEngine sge) throws HeadlessException {
this.sge = sge;
setIgnoreRepaint( true );
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
canvas = new Canvas();
canvas.setIgnoreRepaint( true );
canvas.setSize( WIDTH, HEIGHT );
add( canvas );
pack();
// Hookup keyboard polling
addKeyListener( keyboard );
canvas.addKeyListener( keyboard );
canvas.createBufferStrategy( 2 );
buffer = canvas.getBufferStrategy();
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gd.getDefaultConfiguration();
bi = gc.createCompatibleImage( WIDTH, HEIGHT );
this.setVisible(true);
}
public void draw(int fps) {
g2d = bi.createGraphics();
g2d.setColor( background );
g2d.fillRect( 0, 0, WIDTH, HEIGHT );
g2d.setColor( Color.GREEN );
g2d.drawString( "Use arrow keys to move rect", 100, 20 );
g2d.drawString( "Press esc to exit", 100, 32 );
g2d.setColor( Color.GREEN );
g2d.drawString( "FPS: "+fps, 20, 20 );
g2d.drawRect( sge.bob.x, sge.bob.y, sge.bob.w, sge.bob.h );
graphics = buffer.getDrawGraphics();
graphics.drawImage( bi, 0, 0, null );
if( !buffer.contentsLost() )
buffer.show();
}
...
The game loop:
...
long loop =0;
long update = 0;
long start = System.currentTimeMillis();
long lastIterationTime = System.nanoTime();
long nanoseccount=0;
int cyclec = 0;
int fps=0;
System.out.println("start");
while(run) {
long now = System.nanoTime();
loop++;
while(lastIterationTime + StepSize*1000000 <= now && run ==true) {
Update(StepSize);
update++;
lastIterationTime += StepSize*1000000;
}
Draw(fps);
nanoseccount += System.nanoTime()-now;
cyclec++;
if (nanoseccount >= 1000*1000000 ) {
fps = (int)Math.round((double)cyclec/(nanoseccount/1000000000));
nanoseccount = 0;
cyclec = 0;
continue;
}
}
System.out.println("loop "+ loop +" # update "+ update+ " # u/l " + ((double)update/loop)*100);
long runtime = (System.currentTimeMillis()-start);
System.out.println("run time "+ (double)runtime/1000 +"s # loop/s "+ ((double)loop/((double)runtime/1000)));
System.out.println("updates/s "+ ((double)update/((double)runtime/1000)));
...
Java 6 versions 19,20 and the first versions published by Oracle instead of Sun. They have a gazillion problems in many areas. Web start functionality is almost broken for example.
Here is one issue like this. Google for more if you want.
For the time being, I would suggest that you stick to the older versions, and wait for the next releases.

Categories