Different behaviour function applyLinearVelocity in windows (120 fps) and android (60 fps)
What happened?
When I was testing my game on multiple platforms, I noticed that once the applyLinearImpulse(Vector2(3000, 0)) gives different results on the windows platform (120fps) and on my Android (60fps). In Windows, the distance the object traveled was noticeably greater than on the phone.
The code is written in such a way as to guarantee acceleration once and compare different platforms
What do you expect?
I expect the distance to be the same for all platforms
How can we reproduce this?
class OrthoPlayer extends SpriteAnimationComponent with KeyboardHandler
{
Body? groundBody;
bool isNeedImpulse = true;
@override
Future<void> onLoad() async
{
position = Vector2(100,100);
FixtureDef fix = FixtureDef(PolygonShape()..set([Vector2(-10,-10),Vector2(-10,10),Vector2(10,10),Vector2(10,-10)]), friction:
0.1, density: 0.1);
groundBody = BodyDef(type: BodyType.dynamic, position: position, fixedRotation: true),
gameRef.world.physicsWorld);
@override
bool onKeyEvent(KeyEvent event, Set<LogicalKeyboardKey> keysPressed)
{
if(keysPressed.contains(LogicalKeyboardKey.keyE) && isNeedImpulse ){
isNeedImpulse = false;
groundBody?.applyLinearImpulse(Vector2(3000, 0));
}
}
@override
void update(double dt)
{
super.update(dt);
position = groundRigidBody?.position ?? position;
//after the body stops, the distance is different
}
}
What steps should take to fix this?
No response
Do have an example of where the bug occurs?
No response
Relevant log output
No response
Execute in a terminal and put output into the code block below
Output of: flutter doctor -v
PS C:\kyrgyz_epos_game> flutter doctor -v [√] Flutter (Channel beta, 3.22.0-0.3.pre, on Microsoft Windows [Version 10.0.22631.3593], locale ru-RU) • Flutter version 3.22.0-0.3.pre on channel beta at c:\flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 87b652410d (3 weeks ago), 2024-04-23 21:41:18 -0500 • Engine revision b4bfd45986 • Dart version 3.4.0 (build 3.4.0-282.3.beta) • DevTools version 2.34.3
[√] Windows Version (Installed version of Windows is version 10 or higher)
[√] Android toolchain - develop for Android devices (Android SDK version 34.0.0) • Android SDK at C:\Users\gagin\AppData\Local\Android\sdk • Platform android-34, build-tools 34.0.0 • Java binary at: C:\Program Files\Android\Android Studio\jbr\bin\java • Java version OpenJDK Runtime Environment (build 17.0.9+0--11185874) • All Android licenses accepted.
[√] Chrome - develop for the web • Chrome at C:\Users\gagin\AppData\Local\Google\Chrome\Application\chrome.exe
[√] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.7.5) • Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Community • Visual Studio Community 2022 version 17.7.34202.233 • Windows 10 SDK version 10.0.22621.0
[√] Android Studio (version 2023.2) • Android Studio at C:\Program Files\Android\Android Studio • Flutter plugin can be installed from: https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 17.0.9+0--11185874)
[√] VS Code (version 1.82.3) • VS Code at C:\Users\gagin\AppData\Local\Programs\Microsoft VS Code • Flutter extension can be installed from: https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
[√] Connected device (3 available) • Windows (desktop) • windows • windows-x64 • Microsoft Windows [Version 10.0.22631.3593] • Chrome (web) • chrome • web-javascript • Google Chrome 124.0.6367.208 • Edge (web) • edge • web-javascript • Microsoft Edge 124.0.2478.97
[√] Network resources • All expected network resources are available.
Affected platforms
Android, Windows
Other information
Version of my libraries:
flame-1.17.0 flame_forge2d-0.18.0 forge2d-0.13.0
Are you interested in working on a PR for this?
- [X] I want to work on this
First - on windows Second - on Android.
In this example I once for all time call function applyLinearImpulse(Vector2(0, -5000));
But еhe player does not move up the same level
I'm guessing that you're hitting the max force per tick. What is your zoom level, have you kept the default 10?
Yes, but on the contrary I multiply the rigid body position by 10, because I learned about Forge2d much later than I made the game. I tried it with completely different values, and the speed is always completely different on the computer and on the phone. I have a sprint in the game, when I run without it, the speed on the computer and on the phone is also completely different. Although when I press sprint, the player on both devices starts running faster, i.e. this is not the maximum speed
https://github.com/flame-engine/flame/assets/90832165/54f1a32a-0b60-45ce-9f86-3939fc80d5e4
If you try a simpler example like https://examples.flame-engine.org/#/flame_forge2d_Tappable_Body, do you get the same behavior?
Absolutly yes. I just copied this example (https://github.com/flame-engine/flame/blob/main/packages/flame_forge2d/example/lib/main.dart) into clean new project and replace body.applyLinearImpulse(Vector2.random() * 5000);
on body.applyLinearImpulse(Vector2(3000,0));
And on the phone the speed of the ball is half as much. Maybe the DPI of the device matters?
DevKage had a look at it too and he found this from Box2D:
So I'm guessing the dt for forge2d should be set to a constant (or close to constant) and then that the rendering should interpolate between the results for this to be able to work more deterministically between different framerates.
So, I must override update() in my root game element about like this:
double currentDeltaTime = 0;
const double tickLimit = 1.0 / 30;
@override
void update(double dt)
{
if(dt > tickLimit){ //to skip lags frame
return;
}
currentDeltaTime += dt;
if(currentDeltaTime >= tickLimit){
super.update(currentDeltaTime);
currentDeltaTime = 0;
}
}
That would probably work, but if I were you I would only set the physics engine to a fixed dt meanwhile the rest runs with a variable dt, so then you'd need to override update in the Forge2DWorld instead:
https://github.com/flame-engine/flame/blob/main/packages/flame_forge2d/lib/forge2d_world.dart#L22-L24
Yes, I tested several accelerations using a simple example and indeed - the speed is now the same on the phone and on the computer. Thank you!
So, most staibility with this code:
static const double tickLimit = 1.0 / 45;
double currentDt = 0;
void update(double dt)
{
currentDt += dt;
int cycles = currentDt ~/ tickLimit;
for(int i = 0; i < cycles; i++){
physicsWorld.stepDt(tickLimit);
}
currentDt -= cycles * tickLimit;
}