Jump to content
  • Advertisement
Sign in to follow this  
Agrelahar

Timing in Java

This topic is 5108 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

This dumb thing has been driving me crazy for the last several days:
//Make a bouncing ball!

import java.awt.*;
import java.applet.*;

public class pong extends Applet
{

//applet size
public static final short xBoard = 320;
public static final short yBoard = 320;

//position of circle
public static short circleY = 0, circleX = 0;

//size of circle
public static final short circleSize = 10;

//how far circle moves
public static short xMove = 1, yMove = 1;
	
public void paint(Graphics g)
{
	//for ending the applet
	boolean dontStop = true;

	//timer for moving circle slowly
	long timer;

	//fill the applet with white
	g.setColor(Color.white);
	g.fillRect(0, 0, xBoard, yBoard);

	//while dontStop == true, add next frame time to timer
	for (timer = 0; dontStop == true;)
	{

		timer += System.currentTimeMillis ();

		if (timer >= 1000)
		{
			//reset timer
			timer = 0;

			//draw circle
			g.setColor(Color.black);
			g.fillOval(circleX, circleY, circleSize, circleSize);

			//change where circle will be drawn next time so it "moves"
			circleX += xMove;
			circleY += yMove;

			//function handles collision of sides
//			//dontStop = circle.collide(circleSize, circleX, circleY, xMove, yMove, xBoard, yBoard);
		}
	}
}//end of main
};//end of Applet
In this state, a black streak is made accross the applet. When the white rectangle lines are moved into the timer section and before the black circle, the circle just gets covered up. I believe the culprit is my method of timing, am I doing it incorrectly?

Share this post


Link to post
Share on other sites
Advertisement
Yes. You're getting the current time each frame, which is always going to be greater than 1000. What you probably intended to do is keep the last time around and check the difference. In pseudocode,


t1 = current time
do
t2 = current time
if t2-t1 > threshold
t1 = t2
// do your thing



Busy-waiting isn't really a great thing to do, however; you may find that things run more smoothly if you insert something like ... ah, what's the Java way? Thread.sleep()?

Share this post


Link to post
Share on other sites
It's much worse than that, your whole design is seriously wrong.

You most assuredly do not want your "game loop" inside paint(). In fact, as a general rule, never change any game state or do serious calculation inside paint(). The paint() method is only supposed to describe how to animate one frame. It is a callback function; the GUI will call it (and create a Graphics object and hand it to you) when needed. This can happen for several reasons, not all of which are even under your control.

You should have a separate game loop implemented using a Thread subclass (or Runnable implementation), something like the following:


private static final int FPS = 30;
// Or however fast you want to run it; but note that you don't
// necessarily get faster performance just because you want it ;)

public void run() {
while (running) {
// "running" is some instance variable, or static class
// variable, which can be set false when you want to quit
// the program - by another thread.
long t = System.currentTimeMillis();
updateGameState(); // do your funky stuff
repaint(); // if you are doing this by implementing Runnable
// with your Applet class. Otherwise, you will have to
// provide a reference to the Applet to the thread's object,
// and call repaint() on that.
// In J2ME, there is also a defined call "serviceRepaints()",
// which causes the thread to stop here, do the repaint right
// away, and resume once the repaint is done. The library
// does that internally by some thread synchronization magic.
// I don't know exactly what is involved in making it work
// for applets; try it with just the repaint() first.
t -= System.currentTimeMillis(); // now t is some negative
// number - the negative of the elapsed time.
try { Thread.sleep(1000/FPS + t); }
catch (Exception e) {}
// could be either NegativeSleepTimeException, or
// InterruptedException. Either of these is basically
// harmless.
}
}



The repaint() method is defined for you, and basically makes a request to the library that the Applet would like to be painted. The library (GUI framework) responds by creating a Graphics object representing the area of the screen taken up by the Applet, and calling the Applet's paint() method with that Graphics. Hence "callback".

Share this post


Link to post
Share on other sites
So what you're saying, Zahl, is that when I use the repaint() method, it essentially calls the paint() method in my class/applet?

When I try putting repaint(); in my code, the debugger says I'm trying to use it as a static. How would I use it as an object?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Try this tutorial.

Share this post


Link to post
Share on other sites
Umm... where are you trying to call the repaint() from? If it's inside the Applet, it *should* work (try this.repaint()?) Otherwise, you need to let the other class know about the pong Applet... you *cannot* say "pong.repaint()", because 'pong' is not an object; it's the class.

Say you have some external GameLoop which extends Thread; give it its own constructor which accepts an Applet reference (so it knows what to repaint):


class GameLoop extends Thread {
private Applet paintTarget;
public GameLoop(Applet a) {
paintTarget = a;
}
public void run() {
// the rest of the loop
paintTarget.repaint();
// the rest of the loop
}
}

class pong extends Applet {
private GameLoop target;
public pong() {
// Create the GameLoop and set it running.
// We have to remember a reference to the GameLoop so that
// we can stop it later.
// It should be ok to pass "this" at this point; it might
// not work in C++ though... :\
target = new GameLoop(this);
target.start();
}
}



Something like that.

Share this post


Link to post
Share on other sites
I've spent pretty much my whole day on this and can't figure out what's going awry:
//Make a bouncing ball!

import java.awt.*;
import java.applet.*;

public class pong extends Applet {
//applet size
public static final short xBoard = 320,
yBoard = 220,
//size of circle
circleSize = 10;

//position of circle
public static short circleY = 0,
circleX = 0,
//how far circle moves
xMove = 1,
yMove = 1;

//width of border around applet
short borderW = 1;

public void main() {
short getCollision;

//timer for moving circle slowly
final long timer = 10;

do {
try {
Thread.sleep(timer);
} catch (InterruptedException e) {}

repaint();

//change circle position
circleX += xMove;
circleY += yMove;

//function handles collision of sides
//0 is no collision, 1 is collision, 2 is lose/end game
getCollision = circle.collide(circleSize, circleX, circleY, xBoard, yBoard);

switch (getCollision) {
case 1:
xMove *= -1;
break;

case 2:
yMove *= -1;
break;

case 3:
//LOSE MAN
break;

default:
break;
}//end of switch
} while (getCollision != 3);
}//end of main

public void paint(Graphics g) {

final short doOnce = 0;

do {
//fill the applet with white
g.setColor(Color.green);
g.fillRect(0, 0, xBoard, yBoard);
} while (doOnce == 1);

//draw circle
g.setColor(Color.black);
g.fillOval(circleX, circleY, circleSize, circleSize);
}//end of paint
};//end of class

It just paints the first (one) frame. Not only that, but repaint would seem to be doing nothing due to the fact that it does the same when I comment repaint() out. I'm pretty sure I'm implementing repaint() wrong since I was able to get it to work the wrong way (everything in a paint method).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!