I'm working on a simple Java 2D game.
I wrote a certain game-loop for the game. Using this game-loop, the game sometimes runs in moderate (constant, I think) speed, and sometimes when I start it, it runs in slow (constant) speed.
I learned to implement this game-loop from the following article: Here
It's code:
(I changed it's code to Java. You can find this loop in the article under the title "FPS dependent on Constant Game Speed").
public void run(){
next_game_tick = System.currentTimeMillis();
while(true){
updateGame(); // This is actually a bunch of methods.
repaint();
next_game_tick = next_game_tick + skip_ticks;
sleep_time = next_game_tick - System.currentTimeMillis();
if(sleep_time<0)sleep_time=2;
try {
Thread.sleep(sleep_time);
} catch (InterruptedException e) {}
next_game_tick = System.currentTimeMillis();
}
}
As I said, this loop wasn't always running the game at an appropriate speed, so I looked at the other game-loop implementations suggested in the above article.
The following implementation, only based on it's description, seemed like the most suitable for my game:
int TICKS_PER_SECOND = 50;
int SKIP_TICKS = 1000 / TICKS_PER_SECOND;
int MAX_FRAMESKIP = 10;
long next_game_tick = System.currentTimeMillis();
int loops;
bool game_is_running = true;
while( game_is_running ) {
loops = 0;
while( System.currentTimeMillis() > next_game_tick && loops < MAX_FRAMESKIP) {
update_game();
next_game_tick += SKIP_TICKS;
loops++;
}
repaint();
}
(I changed it's code to Java. You can find this loop in the article under the title "Constant Game Speed with Maximum FPS").
My problem is, I don't fully understand it. I read it's description in the article, and understood that this game-loop might be the best for my game, but didn't understand fully how it works.
I would appreciate if someone explained this game-loop to me, so I would fully understand it before trying to implement it in my game.
(EDIT: I understand the concept of a game-loop and how it works, but not this game loop specifically and everything it does).
Thank you for your help
The game loop you found is actually way outdated. You might want to search for a more up-to-date tutorial. For your game try the following:
First define the game loop:
class GameLoop extends Runnable {
public void run() {
updateGame();
repaint();
}
}
And call it like this:
static final long TARGET_FPS = 60;
static final long TICK_RATE = 1000 / TARGET_FPS;
// ... in main:
final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(new GameLoop(), TICK_RATE, TimeUnit.MILLISECONDS);
Your GameLoop will now be called about as often as requested, while not wasting CPU time on waiting, you can find more information why in the documentation of scheduleAtFixedRate.
If you use the proper Java classes, coding usually becomes much easier.
As a side note: there is no need to update the game if the update is not then drawn to the screen. You should try to code your calculations to not require intermediate steps, because that's just a waste of CPU time.
next_game_tick stores the moment at which the next game tick is suppose to happen.
You have two different times. The real time that you can get with System.currentTimeMillis(), and the game time which is equal to SKIP_TICKS times the number of iterations of your loop plus the time at which the game started.
In the loop the update method is called until the game time has caught up with the real time. Each call of update_game advances the "clock" of the game by SKIP_TICKS ms.
Related
I'm working on a game where I move a car image based on keyboard input. Currently I'm using this game loop:
private void runGameLoop() {
window.setVisible();
isRunning = true;
final double FRAMES_PER_SECOND = 60;
double timePerUpdate = 1000000000 / FRAMES_PER_SECOND;
double timeFromLastUpdate = 0;
long now;
long last = System.nanoTime();
while (isRunning) {
now = System.nanoTime();
timeFromLastUpdate += (now - last) / timePerUpdate;
last = now;
if(timeFromLastUpdate >= 1) {
tick();
render();
timeFromLastUpdate--;
}
}
}
The tick method updates the car image location, and the render method will render the image(with the new location) on screen.
I want to have the calculations for the new image location on a separate thread, because at the moment the calculations are taking to long and causing a rendering lag. Is there a way to use multi threading while still implementing a game loop?
Thanks in advance.
Perhpas you can do something similar to what Android does. In Android there is the mainthread which would be like your game loop. It has a Handler for runnables that are posted from background/concurrent threads to the mainthread.
So at every loop cycle the mainthread executes any runnables posted feom background threads.
Note, that the calculations should not be done in the runnables (which are executed in mainthread), only passing the results/updating stuff should be done in the runnables.
I'm using Java within a Processing project. I'm trying to make a delay that doesn't stop the program, but stops only a given block of code. That "processing" block of code could for example add 1 to a variable, then wait one second and then add 1 again. The problem is that delay() (see reference) stops the whole program and Thread.sleep() doesn't work in a Processing project.
You should not use delay() or Thread.sleep() in Processing unless you're already using your own threads. Don't use it on the default Processing thread (so don't use it in any of the Processing functions).
Instead, use the frameCount variable or the millis() function to get the time that your event starts, and then check that against the current time to determine when to stop the event.
Here's an example that shows a circle for 5 seconds whenever the user clicks:
int clickTime = 0;
boolean showCircle = false;
void draw(){
background(64);
if(showCircle){
ellipse(width/2, height/2, width, height);
if(clickTime + 5*1000 < millis()){
showCircle = false;
}
}
}
void mousePressed(){
clickTime = millis();
showCircle = true;
}
Side note: please try to use proper punctuation when you type. Right now your question is just one long run-on sentence, which makes it very hard to read.
I've been tasked with creating a program which will lead a finch robot to move around somewhat randomly for the allotted amount of time, while counting the number of objects that it detects during the movement and returning this amount to then be displayed.
I can get the robot to move randomly, and I can get it to count objects that it detects - but not at the same time.
main:
int millsec = 5000;
int obstacleOccur = finchRandom(millsec);
System.out.println(obstacleOccur);
method:
static public int finchRandom(int x)
{
Finch myf = new Finch();
Random rand = new Random();
int obs = 0;
long time = System.currentTimeMillis()+x;
while(time - System.currentTimeMillis() > 0)
{
if (myf.isObstacle())
{
obs++; //this counts the obstacles
System.out.println("Obstacle");
} //below activates the wheels to move randomly,
//the function is setWheelVelocities(leftWheel,rightWheel,duration)
myf.setWheelVelocities(rand.nextInt(150)-75,rand.nextInt(150)-75,rand.nextInt(x/2));
}
return obs; //returns the count of obstacles
}
I believe it is because the if statement and incrementation for counting obstacles can't be ran while the finch robot is moving around. Are there any ways around this?
Thanks in advance.
The answer is multithreaded programming, your job is to figure out how to use THread or Runnable or a lambda expression to do so. Because any given thread can only do one thing at a time, and you need to be doing at least two things at a time.
I'm coding this in JavaFX using a FXMLController and the scene builder.
I'm currently creating an Instagram "liker" mostly just for practice as I'm a Computer Science major, and I just like coding.
My issue is, I have a for loop that "likes" 20 photos for each hashtag, I obviously need a delay or I'd get banned rather quickly. The user can choose the delay, then I randomize this delay so it's not too robotic.
The only way I've been able to use this delay is through the thread.sleep method, but since I'm coding on the FXMLController, it freezes the whole UI, and somehow stops other textareas from being updated. This is obviously not ideal.
I've looked everywhere trying to find an alternative to this, but I can't find anything that works in my program.
I'll give the whole method:
private void start() {
sleepWhen();
tagNumber++;
int delays = Integer.valueOf(delay.getText());
delays = delays * 1000;
if (loaded) {
runTime.clear();
runTime.appendText("Liking...");
for (int i = 0; i < 20; i++) {
webEngine.executeScript("document.getElementsByClassName('btn btn-default btn-xs likeButton')[" + i + "].click()");
try {
double random = Math.random() * 1000;
random = random + delays;
delays = (int) random;
System.out.println(delays);
likes++;
likesNumber.clear();
likesNumber.appendText(String.valueOf(likes));
System.out.println(String.valueOf(likes));
Thread.sleep(delays);
delays = Integer.valueOf(delay.getText());
delays = delays * 1000;
} catch (InterruptedException ex) {
//do nothing
}
System.out.println("tag number" + tagNumber + "numbertags" + numberTags);
if (!sleep) {
if (tagNumber < numberTags) {
System.out.println("Loading tag:" + tagNumber);
loadTag(tagNumber);
}
}
}
}
}
This likes 20 photos, then loads another hashtag, and repeats.
Any help with this would be great, thanks.
The freeze is because you are trying to do everything on the same thread, when you are using Thread.sleep(delays), you are actually putting your UI thread to sleep and hence the lag !
Try using different thread for your work, you can either use a worker thread, if whatever you are doing will not affect the UI
or you can use Platform.runLater(), if you want the changes to shown on the UI !
For more details :
concurrency in javafx !
Platform.runLater and Task in JavaFX
I'm trying to loop trough an array of Points with a delay, but nothing happens and I don't get errors.
Here's an example of what my code looks like:
public class Class {
private Point[] points;
private int start, delay;
public Class() {
points = new Point[] {
new Point(1, 1),
new Point(2, 1),
new Point(1, 2)
};
start = System.nanoTime();
delay = 500;
}
public void update() {
for(int i = 0; i < points.length; i++) {
long elapsed = (System.nanoTime() - startT) / 1000000;
if(elapsed > delay) {
System.out.println("x: " + points[i].x);
System.out.println("y: " + points[i].y);
start = System.nanoTime();
}
}
}
}
Everything inside the update function is working except for that for loop.
edit:
It's a java Swing application with only 1 thread.
One of your problems is that you're using an if block and not a while loop. An if block just checks once, sees that the condition is false, and skips over it. A while loop will loop until the condition is false.
For most delays you could use a general purpose Timer object such as a java.util.Timer together with a java.util.TimerTask object.
for delays in a Swing GUI you would use a javax.swing.Timer
Other options for general non-Swing computing including using a while loop that contains a Thread.sleep(...) call.
Also look into using a ScheduledThreadPoolExecutor for non-Swing delays.
Edit
Regarding your edit:
edit: It's a java Swing application with only 1 thread.
Then use a javax.swing.Timer. You can find the tutorial here: Swing Timer Tutorial
And here's the Swing Concurrency Tutorial
Also have a look at the Swing Tutorial for more on Swing development.
If you need more help, then as we've already mentioned, provide more detail in your question.
To sleep for an aproximate amount of time use Thread.sleep(millis);
Do not expect accuracy to be more than 30ms.