Sync Gravity and FPS
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 |
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 '18 at 21:13
So, I need to separate repaint and ontick, establishing a default time to update them?
– Superzinho
Nov 21 '18 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 '18 at 21:26
add a comment |
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 '18 at 21:00
SuperzinhoSuperzinho
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 '18 at 21:13
So, I need to separate repaint and ontick, establishing a default time to update them?
– Superzinho
Nov 21 '18 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 '18 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 '18 at 21:13
So, I need to separate repaint and ontick, establishing a default time to update them?
– Superzinho
Nov 21 '18 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 '18 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 '18 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 '18 at 21:13
So, I need to separate repaint and ontick, establishing a default time to update them?
– Superzinho
Nov 21 '18 at 21:26
So, I need to separate repaint and ontick, establishing a default time to update them?
– Superzinho
Nov 21 '18 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 '18 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 '18 at 21:26
add a comment |
1 Answer
1
active
oldest
votes
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 '18 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 '18 at 21:58
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
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
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
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 '18 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 '18 at 21:58
add a comment |
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 '18 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 '18 at 21:58
add a comment |
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 '18 at 21:35
answered Nov 21 '18 at 21:29
msg45fmsg45f
333613
333613
1
I think I will do it separated, It's easier.
– Superzinho
Nov 21 '18 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 '18 at 21:58
add a comment |
1
I think I will do it separated, It's easier.
– Superzinho
Nov 21 '18 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 '18 at 21:58
1
1
I think I will do it separated, It's easier.
– Superzinho
Nov 21 '18 at 21:42
I think I will do it separated, It's easier.
– Superzinho
Nov 21 '18 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 '18 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 '18 at 21:58
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
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 '18 at 21:13
So, I need to separate repaint and ontick, establishing a default time to update them?
– Superzinho
Nov 21 '18 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 '18 at 21:26