Hi,
I’m developing a 2d racing game (top-down mode) using cocos2d 3.17, box2d, ndk r16b, etc.
I’ll try to be brief. This is my problem:
The car accelerates in different velocities depending of the device. For example, in iPhone 6s Plus the car accelerates faster than iPhone 7.
After a research, maybe I discovered the problem: box2d works in a different ways depending of the phone resolutions:
For example, in iPhone 7 the game works equal than iPhone 8, because the resolutions are the same. But in iPhone 6s Plus works different. I’ve tested it in real devices.
How could I fix it?
Here I share some things for understand how my game works:
- Box2d logic is based on this public project:
Explanation: Top-down car physics - Box2D tutorials - iforce2d
Code: https://www.iforce2d.net/src/iforce2d_TopdownCar.h
So, I’m using ApplyForce
to each body-tire, each 1/60 secs.
- My game runs in 60 FPS, so in my
update
function i’m updating the world step in this way:
int velocityIterations = 8; int positionIterations = 3; world->Step(dt, velocityIterations, positionIterations);
- The
PTMRATIO
that i’m using is 32.
I’ve tested the following modifications:
- Use a fixed
dt
:
world->Step(1.0/60.0f, velocityIterations, positionIterations);
I’ve read that it could help to improve the fluency, and it’s true: it improved the fluency movement of the car, but the velocity problem still happens. So, it didn’t fix the problem.
-
Update to cocos 3.17.2 (my current version is 3.17):
Maybe some bug related to cocos framework. But not. I updated to cocos 3.17.2 and I tested in iOS and the problem still happens. -
“Play” interpolating
dt
values… something like this:
void WorldNode::update(float dt) { const auto maximumStep = 1 / 120.f; auto progress = 0.0f; while (progress < dt) { const auto step = std::min((dt - progress), maximumStep); progress += step; //stepping b2d world based on incoming delta world->Step(progress, velocityIterations, positionIterations); } ... }
Same results.
- “Play” with
PTMRATIO
:
Instead of this line:
#define PTMRATIO 32
I’ve tested some variations, for example a PTMRATIO that depends of the screen resolution:
#define PTMRATIO (64 / Director::getInstance()->getContentScaleFactor())
And:
world->Step(dt, velocityIterations, positionIterations);
It depends of the screen resolution, because in AppDelegate i’m configuring the ContentScaleFactor depending of the screen:
// set FPS. the default value is 1.0/60 if you don't call this
director->setAnimationInterval(1.0f / 60);
// Set the design resolution
glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::NO_BORDER);
auto frameSize = glview->getFrameSize();
// if the frame's height is larger than the height of medium size.
if (frameSize.height > mediumResolutionSize.height)
{
director->setContentScaleFactor(MIN(largeResolutionSize.height/designResolutionSize.height, largeResolutionSize.width/designResolutionSize.width));
}
// if the frame's height is larger than the height of small size.
else if (frameSize.height > smallResolutionSize.height)
{
director->setContentScaleFactor(MIN(mediumResolutionSize.height/designResolutionSize.height, mediumResolutionSize.width/designResolutionSize.width));
}
// if the frame's height is smaller than the height of medium size.
else
{
director->setContentScaleFactor(MIN(smallResolutionSize.height/designResolutionSize.height, smallResolutionSize.width/designResolutionSize.width));
}
Maybe it’s the correct way: find the “perfect” PTMRATIO
. But… how to know if this value is the perfect value? The tiled map is scaled, so the current view in all devices should be similar. But… what about the velocity? How to find the perfect value for all devices?
Suggestions?