Sync Gravity and FPS
up vote
0
down vote
favorite
I'm developing a simple game, but I have a problem with FPS and gravity.
So I need to sync FPS and gravity, because the higher FPS is the player fall faster. How can I sync them?
My code to update player:
while (true) {
try {
Thread.sleep(1000 / GameMain.maxFPS); //Max Fps Limiter
GameMain.activeEntities.forEach((ent) -> { //Revalidade All Entities and Positions
ent.onTick();
});
gamePanel.repaint(); //Repaint Frame, Update Positions
} catch (InterruptedException e) {
e.printStackTrace();
}
}
My code to update gravity:
@Override
public void onTick() {
this.velocity = this.velocity.add(0, gravityForce()/*<- I'm using 9.807 divided by 60*/);
if (this.velocity.y > maxSpeed)
{
this.velocity.y = maxSpeed;
}
this.getPosition().y = this.getPosition().y + (this.velocity.y);
}
java 2d-games gravity
add a comment |
up vote
0
down vote
favorite
I'm developing a simple game, but I have a problem with FPS and gravity.
So I need to sync FPS and gravity, because the higher FPS is the player fall faster. How can I sync them?
My code to update player:
while (true) {
try {
Thread.sleep(1000 / GameMain.maxFPS); //Max Fps Limiter
GameMain.activeEntities.forEach((ent) -> { //Revalidade All Entities and Positions
ent.onTick();
});
gamePanel.repaint(); //Repaint Frame, Update Positions
} catch (InterruptedException e) {
e.printStackTrace();
}
}
My code to update gravity:
@Override
public void onTick() {
this.velocity = this.velocity.add(0, gravityForce()/*<- I'm using 9.807 divided by 60*/);
if (this.velocity.y > maxSpeed)
{
this.velocity.y = maxSpeed;
}
this.getPosition().y = this.getPosition().y + (this.velocity.y);
}
java 2d-games gravity
1
You could support partial ticks (and multiple ticks if your machine has been slow) - say a tick takes one second, and you're now .3 second since the last tick, then you callonTick(0.3)
where 0.3 is the tickFraction, and you dothis.getPosition().y = this.getPosition().y + (this.velocity.y * tickFraction);
– Erwin Bolwidt
Nov 21 at 21:13
So, I need to separate repaint and ontick, establishing a default time to update them?
– Superzinho
Nov 21 at 21:26
1
Or at least remember the time of the last update so you can find out how much time has elapsed.
– Erwin Bolwidt
Nov 21 at 21:26
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I'm developing a simple game, but I have a problem with FPS and gravity.
So I need to sync FPS and gravity, because the higher FPS is the player fall faster. How can I sync them?
My code to update player:
while (true) {
try {
Thread.sleep(1000 / GameMain.maxFPS); //Max Fps Limiter
GameMain.activeEntities.forEach((ent) -> { //Revalidade All Entities and Positions
ent.onTick();
});
gamePanel.repaint(); //Repaint Frame, Update Positions
} catch (InterruptedException e) {
e.printStackTrace();
}
}
My code to update gravity:
@Override
public void onTick() {
this.velocity = this.velocity.add(0, gravityForce()/*<- I'm using 9.807 divided by 60*/);
if (this.velocity.y > maxSpeed)
{
this.velocity.y = maxSpeed;
}
this.getPosition().y = this.getPosition().y + (this.velocity.y);
}
java 2d-games gravity
I'm developing a simple game, but I have a problem with FPS and gravity.
So I need to sync FPS and gravity, because the higher FPS is the player fall faster. How can I sync them?
My code to update player:
while (true) {
try {
Thread.sleep(1000 / GameMain.maxFPS); //Max Fps Limiter
GameMain.activeEntities.forEach((ent) -> { //Revalidade All Entities and Positions
ent.onTick();
});
gamePanel.repaint(); //Repaint Frame, Update Positions
} catch (InterruptedException e) {
e.printStackTrace();
}
}
My code to update gravity:
@Override
public void onTick() {
this.velocity = this.velocity.add(0, gravityForce()/*<- I'm using 9.807 divided by 60*/);
if (this.velocity.y > maxSpeed)
{
this.velocity.y = maxSpeed;
}
this.getPosition().y = this.getPosition().y + (this.velocity.y);
}
java 2d-games gravity
java 2d-games gravity
asked Nov 21 at 21:00
Superzinho
34
34
1
You could support partial ticks (and multiple ticks if your machine has been slow) - say a tick takes one second, and you're now .3 second since the last tick, then you callonTick(0.3)
where 0.3 is the tickFraction, and you dothis.getPosition().y = this.getPosition().y + (this.velocity.y * tickFraction);
– Erwin Bolwidt
Nov 21 at 21:13
So, I need to separate repaint and ontick, establishing a default time to update them?
– Superzinho
Nov 21 at 21:26
1
Or at least remember the time of the last update so you can find out how much time has elapsed.
– Erwin Bolwidt
Nov 21 at 21:26
add a comment |
1
You could support partial ticks (and multiple ticks if your machine has been slow) - say a tick takes one second, and you're now .3 second since the last tick, then you callonTick(0.3)
where 0.3 is the tickFraction, and you dothis.getPosition().y = this.getPosition().y + (this.velocity.y * tickFraction);
– Erwin Bolwidt
Nov 21 at 21:13
So, I need to separate repaint and ontick, establishing a default time to update them?
– Superzinho
Nov 21 at 21:26
1
Or at least remember the time of the last update so you can find out how much time has elapsed.
– Erwin Bolwidt
Nov 21 at 21:26
1
1
You could support partial ticks (and multiple ticks if your machine has been slow) - say a tick takes one second, and you're now .3 second since the last tick, then you call
onTick(0.3)
where 0.3 is the tickFraction, and you do this.getPosition().y = this.getPosition().y + (this.velocity.y * tickFraction);
– Erwin Bolwidt
Nov 21 at 21:13
You could support partial ticks (and multiple ticks if your machine has been slow) - say a tick takes one second, and you're now .3 second since the last tick, then you call
onTick(0.3)
where 0.3 is the tickFraction, and you do this.getPosition().y = this.getPosition().y + (this.velocity.y * tickFraction);
– Erwin Bolwidt
Nov 21 at 21:13
So, I need to separate repaint and ontick, establishing a default time to update them?
– Superzinho
Nov 21 at 21:26
So, I need to separate repaint and ontick, establishing a default time to update them?
– Superzinho
Nov 21 at 21:26
1
1
Or at least remember the time of the last update so you can find out how much time has elapsed.
– Erwin Bolwidt
Nov 21 at 21:26
Or at least remember the time of the last update so you can find out how much time has elapsed.
– Erwin Bolwidt
Nov 21 at 21:26
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
accepted
Using Thread.sleep is going to be problematic as Thread.sleep will not guarantee that the Thread sleeps for exactly 1000ms, but rather than the Thread will sleep for at least 1000ms. Further, whenever it comes to working with threads there will be differences in behavior dependent upon the actually system, as thread scheduling logic is not a function of your application or the JVM, but rather the underlying hardware.
My recommendation: Either decouple draw logic from recalculation logic or let it run free without blocking the Thread with Thread.sleep. From there, to get good motion we should recall that change in position is not just a factor of speed, but also time. Therefore, we need to calculate the time passing between different draw frames by some mechanism such as System.currentTimeMillis()
or System.nanoTime()
.
From there, you can recalculate positions by multiplying their velocity times the amount of time passing since recalculating.
Rough implementation:
double c = 1 / 60; // Some constant factor to bound motion over time
long previousCycleTime = System.currentTimeMillis();
while(somePredicate()) { // Logical cycle
long t = System.currentTimeMillis() - previousCycleTime;
gameObjects.forEach( o -> {
// t -> time passage
// dx -> change on the x axis
// c -> some constant factor to bound movement to the 'virtual space'
o.x += o.dx * t * c;
o.y += o.dy * t * c;
}
redraw();
}
Alternatively, you could redraw in a separate thread to decouple the two processes. This should not be taken lightly though, as transitioning from a single threaded application to multithreaded application introduces a great deal of additional complexity.
1
I think I will do it separated, It's easier.
– Superzinho
Nov 21 at 21:42
That's probably the better approach long term. In this situation, I would introduce Thread.sleep again, as sleeping the drawing thread will not block other important activities - just ensure that your recalculations are still leveraging time.
– msg45f
Nov 21 at 21:58
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
accepted
Using Thread.sleep is going to be problematic as Thread.sleep will not guarantee that the Thread sleeps for exactly 1000ms, but rather than the Thread will sleep for at least 1000ms. Further, whenever it comes to working with threads there will be differences in behavior dependent upon the actually system, as thread scheduling logic is not a function of your application or the JVM, but rather the underlying hardware.
My recommendation: Either decouple draw logic from recalculation logic or let it run free without blocking the Thread with Thread.sleep. From there, to get good motion we should recall that change in position is not just a factor of speed, but also time. Therefore, we need to calculate the time passing between different draw frames by some mechanism such as System.currentTimeMillis()
or System.nanoTime()
.
From there, you can recalculate positions by multiplying their velocity times the amount of time passing since recalculating.
Rough implementation:
double c = 1 / 60; // Some constant factor to bound motion over time
long previousCycleTime = System.currentTimeMillis();
while(somePredicate()) { // Logical cycle
long t = System.currentTimeMillis() - previousCycleTime;
gameObjects.forEach( o -> {
// t -> time passage
// dx -> change on the x axis
// c -> some constant factor to bound movement to the 'virtual space'
o.x += o.dx * t * c;
o.y += o.dy * t * c;
}
redraw();
}
Alternatively, you could redraw in a separate thread to decouple the two processes. This should not be taken lightly though, as transitioning from a single threaded application to multithreaded application introduces a great deal of additional complexity.
1
I think I will do it separated, It's easier.
– Superzinho
Nov 21 at 21:42
That's probably the better approach long term. In this situation, I would introduce Thread.sleep again, as sleeping the drawing thread will not block other important activities - just ensure that your recalculations are still leveraging time.
– msg45f
Nov 21 at 21:58
add a comment |
up vote
0
down vote
accepted
Using Thread.sleep is going to be problematic as Thread.sleep will not guarantee that the Thread sleeps for exactly 1000ms, but rather than the Thread will sleep for at least 1000ms. Further, whenever it comes to working with threads there will be differences in behavior dependent upon the actually system, as thread scheduling logic is not a function of your application or the JVM, but rather the underlying hardware.
My recommendation: Either decouple draw logic from recalculation logic or let it run free without blocking the Thread with Thread.sleep. From there, to get good motion we should recall that change in position is not just a factor of speed, but also time. Therefore, we need to calculate the time passing between different draw frames by some mechanism such as System.currentTimeMillis()
or System.nanoTime()
.
From there, you can recalculate positions by multiplying their velocity times the amount of time passing since recalculating.
Rough implementation:
double c = 1 / 60; // Some constant factor to bound motion over time
long previousCycleTime = System.currentTimeMillis();
while(somePredicate()) { // Logical cycle
long t = System.currentTimeMillis() - previousCycleTime;
gameObjects.forEach( o -> {
// t -> time passage
// dx -> change on the x axis
// c -> some constant factor to bound movement to the 'virtual space'
o.x += o.dx * t * c;
o.y += o.dy * t * c;
}
redraw();
}
Alternatively, you could redraw in a separate thread to decouple the two processes. This should not be taken lightly though, as transitioning from a single threaded application to multithreaded application introduces a great deal of additional complexity.
1
I think I will do it separated, It's easier.
– Superzinho
Nov 21 at 21:42
That's probably the better approach long term. In this situation, I would introduce Thread.sleep again, as sleeping the drawing thread will not block other important activities - just ensure that your recalculations are still leveraging time.
– msg45f
Nov 21 at 21:58
add a comment |
up vote
0
down vote
accepted
up vote
0
down vote
accepted
Using Thread.sleep is going to be problematic as Thread.sleep will not guarantee that the Thread sleeps for exactly 1000ms, but rather than the Thread will sleep for at least 1000ms. Further, whenever it comes to working with threads there will be differences in behavior dependent upon the actually system, as thread scheduling logic is not a function of your application or the JVM, but rather the underlying hardware.
My recommendation: Either decouple draw logic from recalculation logic or let it run free without blocking the Thread with Thread.sleep. From there, to get good motion we should recall that change in position is not just a factor of speed, but also time. Therefore, we need to calculate the time passing between different draw frames by some mechanism such as System.currentTimeMillis()
or System.nanoTime()
.
From there, you can recalculate positions by multiplying their velocity times the amount of time passing since recalculating.
Rough implementation:
double c = 1 / 60; // Some constant factor to bound motion over time
long previousCycleTime = System.currentTimeMillis();
while(somePredicate()) { // Logical cycle
long t = System.currentTimeMillis() - previousCycleTime;
gameObjects.forEach( o -> {
// t -> time passage
// dx -> change on the x axis
// c -> some constant factor to bound movement to the 'virtual space'
o.x += o.dx * t * c;
o.y += o.dy * t * c;
}
redraw();
}
Alternatively, you could redraw in a separate thread to decouple the two processes. This should not be taken lightly though, as transitioning from a single threaded application to multithreaded application introduces a great deal of additional complexity.
Using Thread.sleep is going to be problematic as Thread.sleep will not guarantee that the Thread sleeps for exactly 1000ms, but rather than the Thread will sleep for at least 1000ms. Further, whenever it comes to working with threads there will be differences in behavior dependent upon the actually system, as thread scheduling logic is not a function of your application or the JVM, but rather the underlying hardware.
My recommendation: Either decouple draw logic from recalculation logic or let it run free without blocking the Thread with Thread.sleep. From there, to get good motion we should recall that change in position is not just a factor of speed, but also time. Therefore, we need to calculate the time passing between different draw frames by some mechanism such as System.currentTimeMillis()
or System.nanoTime()
.
From there, you can recalculate positions by multiplying their velocity times the amount of time passing since recalculating.
Rough implementation:
double c = 1 / 60; // Some constant factor to bound motion over time
long previousCycleTime = System.currentTimeMillis();
while(somePredicate()) { // Logical cycle
long t = System.currentTimeMillis() - previousCycleTime;
gameObjects.forEach( o -> {
// t -> time passage
// dx -> change on the x axis
// c -> some constant factor to bound movement to the 'virtual space'
o.x += o.dx * t * c;
o.y += o.dy * t * c;
}
redraw();
}
Alternatively, you could redraw in a separate thread to decouple the two processes. This should not be taken lightly though, as transitioning from a single threaded application to multithreaded application introduces a great deal of additional complexity.
edited Nov 21 at 21:35
answered Nov 21 at 21:29
msg45f
333613
333613
1
I think I will do it separated, It's easier.
– Superzinho
Nov 21 at 21:42
That's probably the better approach long term. In this situation, I would introduce Thread.sleep again, as sleeping the drawing thread will not block other important activities - just ensure that your recalculations are still leveraging time.
– msg45f
Nov 21 at 21:58
add a comment |
1
I think I will do it separated, It's easier.
– Superzinho
Nov 21 at 21:42
That's probably the better approach long term. In this situation, I would introduce Thread.sleep again, as sleeping the drawing thread will not block other important activities - just ensure that your recalculations are still leveraging time.
– msg45f
Nov 21 at 21:58
1
1
I think I will do it separated, It's easier.
– Superzinho
Nov 21 at 21:42
I think I will do it separated, It's easier.
– Superzinho
Nov 21 at 21:42
That's probably the better approach long term. In this situation, I would introduce Thread.sleep again, as sleeping the drawing thread will not block other important activities - just ensure that your recalculations are still leveraging time.
– msg45f
Nov 21 at 21:58
That's probably the better approach long term. In this situation, I would introduce Thread.sleep again, as sleeping the drawing thread will not block other important activities - just ensure that your recalculations are still leveraging time.
– msg45f
Nov 21 at 21:58
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53420415%2fsync-gravity-and-fps%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
You could support partial ticks (and multiple ticks if your machine has been slow) - say a tick takes one second, and you're now .3 second since the last tick, then you call
onTick(0.3)
where 0.3 is the tickFraction, and you dothis.getPosition().y = this.getPosition().y + (this.velocity.y * tickFraction);
– Erwin Bolwidt
Nov 21 at 21:13
So, I need to separate repaint and ontick, establishing a default time to update them?
– Superzinho
Nov 21 at 21:26
1
Or at least remember the time of the last update so you can find out how much time has elapsed.
– Erwin Bolwidt
Nov 21 at 21:26