Selecting a sync strategy

Hi.
This is my first thread in this forum. First at all, sorry my bad english (read is easier than write, as can see).

Well, I’m developing a little fps 2d game (like CS2D but much simpler and very different themed).

For it, I use a MVC model and find to make a good object design.

I begin with the model development, and I finished this. Obviously this is the easiest part.

Now, I’m writing the JAVA2D presentation and my head begins to ache.

At this point is where a sync problem makes present.

I know that is one of the most common problems and there is a lot of threads in the forum about it. The alternatives I wrote are based in your help.

The only thing is there are three alternatives with similar performance but I think that where the game grow a lot, the difference will appear.

Then, I need you give me your opinions about what method y should use, and why:

  • sync1
  • sync2
  • sync3

In all the cases, dt is in milliseconds and the main loop is something like:


while (isPlaying) {
	boolean modelHasChanged = false;

	// get time to eat
	long currentTimestamp = Timer.getTimestamp();
	timeAccumulator += currentTimestamp - lastLoopTimestamp;

	// eat by dt bites
	while (timeAccumulator >= dt) {
		updateModel(dt / 1000);
		timeAccumulator -= dt;
		modelHasChanged = true;
	}

	// generate time...
	sync1(modelHasChanged, dt);
	// or: sync2(dt, currentTimestamp, ft);
	// or: sync3(dt);

	// update timers
	lastLoopTimestamp = currentTimestamp;
}

And, the view.update is something like:


	public void update(...) {
		// prepare the off-screen graphic sandbox
		Graphics2D g2d = offScreenGraphics.createGraphics();
		g2d.setColor(Color.black);
		g2d.fillRect(0, 0, width, height);

		// draw rectangles, text and things in g2d...
		// ...

		// to the buffer
		Graphics gr = bufferStrategy.getDrawGraphics();
		gr.drawImage(offScreenGraphics, 0, 0, null);

		// free resources
		gr.dispose();
		g2d.dispose();
	}

	public void show(...) {
		// BLT
		if (!bufferStrategy.contentsLost()) bufferStrategy.show();
	}

The three sync methods are:


	/**
	 * Omits update view if not was changed model. 
	 * + Very smooth
	 * - View has the same update rate that model (model updates with fps frequency).
	 */
	private void sync1(boolean modelHasChanged, double dt) {
		if (modelHasChanged) {
			view.update(this);
			Thread.yield();
			view.show(this);
		}
		else try { Thread.sleep(1); }
		catch (InterruptedException e1) {}
	}

	/**
	 * Independent frame rate and model update rate. 
	 * + Independent rates (example: 60fps and dt=30ms)
	 * - Not very smooth
	 */
	private void sync2(double dt, long currentTimestamp, long ft) {
		view.update(this);

		// wait up to the end frame time
		long desiredEnd = currentTimestamp + ft;
		while (Timer.getTimestamp() <= desiredEnd)
			try { Thread.sleep(1); }
			catch (InterruptedException e) {}

		view.show(this);
	}

	/**
	 * Independent frame rate and model update rate. 
	 * + The more smooth, the frame rate is determined by "sync"
	 * - I don't know.
	 */
	private void sync3(double dt) {
		view.update(this);
		Toolkit.getDefaultToolkit().sync();
		Thread.yield();
		view.show(this);
	}

Thanks!

Hi.
This question has 75 views vs 0 replies today.

It’s because is too hard the answer or too dummy the question?

No, I’m just too lazy! :stuck_out_tongue:
I guess I’m not quite sure what you’re asking… You’ve got a model which is updated as events happen, and a view which displays the model at the highest fps you can manage. why do they need to be synched?

The model bust be sync-ed because need run in any hardware at the same speed.
The view must be udpated periodically but not use too many resources, for it is needed a small delay between view updates (thread.sleep, toolkit.sync, …).

The three methods sync1, sync2 and sync3 do it, but these have pros and contras that I mention in the method header and another pros and contras that I don’t know.

Thanks for your post!

Are you just trying to make a simple game loop?

When the first version off the game was done, I try it and it worked.
Then, I search a method to improve it because sometimes the fps were too fluctuating.

And I write the 3 sync methods.

I need a method that ensures me (or make the best effort) that in two PC’s the model run at the same speed and the fps can be adjusted to a speed that run smooth.

[quote=“zoq,post:6,topic:36037”]
Make sure your model is updated in real time. Slow machines will have a slow game loop. Make sure your Model.update() function is based on something like System.nanoTime() and not on MyGame.framesDisplayed. If the model is based on real time the view would reflect this accurately however slow the machine.
Low FPS==bad graphics card

The tutorial might help

SimonH, my game is updated in real time: Timer.getTimestamp() in line 5, in the first code extract, only encapsulates the System.getCurrentMillis().
The inner loop ensures that the discrete step is always the desired dt.

In respect to:

I think that with an effort, the game can target bad graphics card (I’m sure the expression in english is not the correct, but you will understand that I wanted to say).

Thanks for your suggestion!

Gudradain, thanks for the link.
I see that the main loop showed in the tutorial is similar to my sync2 method.
The main difference is:


Tutorial -> Thread.sleep((desiredDeltaLoop - deltaLoop)/(1000*1000));
Sync2 -> while (Timer.getTimestamp() <= desiredEnd) Thread.sleep(1);

Maybe the multiple sleep I does causes an noticeable overhead.

Thanks, again!