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);
}









share|improve this question


















  • 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










  • 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















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);
}









share|improve this question


















  • 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










  • 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













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);
}









share|improve this question













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






share|improve this question













share|improve this question











share|improve this question




share|improve this question










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 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








  • 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




    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








  • 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












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.






share|improve this answer



















  • 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











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',
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
});


}
});














 

draft saved


draft discarded


















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








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.






share|improve this answer



















  • 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















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.






share|improve this answer



















  • 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













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.






share|improve this answer














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.







share|improve this answer














share|improve this answer



share|improve this answer








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














  • 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


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














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





















































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







Popular posts from this blog

What visual should I use to simply compare current year value vs last year in Power BI desktop

How to ignore python UserWarning in pytest?

Alexandru Averescu