使用 SDL2 平滑(惯性)滚动?
Smooth (Inertial) Scrolling with SDL2?
我正在使用 C++ 为 macOS 构建 SDL2 应用程序。我需要一些 "basic" 的应用程序滚动(例如网络浏览器)。我使用 SDL_MouseWheel 事件 实现了这一点,这为我提供了一个功能齐全的 "windows-like" 滚动。我使用的是 Macbook Pro,我想加入触控板的功能。
简单的求一个更好的滚动算法(Macbook的触控板滚动,惯性滚动)
我知道 SDL_MultiGesture 事件,但我真的不知道如何将它们组合起来才能达到我想要的结果。
好的,这就是问题的答案。
首先,您必须手动完成。
我还假定您了解 SDL2 和 C++。
*注意:我只为 Y 轴做滚动(如果你愿意,你可以为两个轴做滚动)。
首先我们需要一些变量:
int scrolling; // flag (scrolling or not)
int scroll_sensitivity = 40; // how fast we want to scroll
double scroll_Y = 0; // current scrolling amount (on Y-Axis)
double scroll_acceleration; // scrolling speed
double scroll_friction = 0.001; // how fast we decelerate
double scroll_prev_pos; // previous event's position
之后您将需要处理 SDL_MultiGesture 事件:
case SDL_MULTIGESTURE:{
if(event.mgesture.numFingers == 2){
if(scrolling == 0){
scrolling = 1;
scroll_prev_pos = event.mgesture.y;
} else{
double dy = event.mgesture.y - scroll_prev_pos;
scroll_acceleration = dy * 40;
scroll_prev_pos = event.mgesture.y;
scrolling = 1;
}
}
break;
}
此外,我们需要在 SDL_FingerDown 事件上停止滚动:
case SDL_FINGERDOWN:{
scrolling = 0;
break;
}
接下来,我们要更新 scroll_Y(将其放入您的 "update" 函数):
if(scrolling){
if(scroll_acceleration > 0) scroll_acceleration -= scroll_friction;
if(scroll_acceleration < 0) scroll_acceleration += scroll_friction;
if(abs(scroll_acceleration) < 0.0005) scroll_acceleration = 0;
scroll_Y += scroll_sensitivity * scroll_acceleration;
// Here you have to set your scrolling bounds i.e. if(scroll_Y < 0) scroll_Y = 0;
}
最后,我们要根据滚动值进行渲染:
SDL_Rect rect = {some_x, some_y + scroll_Y, some_w, some_h};
SDL_RenderCopy(renderer, some_texture, NULL, &rect);
就是这个!
我有一个使用上述代码的完全可用的应用程序,所以我 100% 确定它会按预期工作。如果您有任何问题(因为它不是实际代码,它更像是一种算法)请与我联系。正如我之前提到的,我假设您已经足够了解 SDL 和 C++,因此我相信您能够理解实现。
另外,我知道这个解决方案可以变得更好,所以如果您有任何要添加/更改的内容,请尽管说出来!
祝你有个愉快的一天!
我 运行 遇到了同样的问题,结果是 SDL opts out of momentum scroll events 通过关闭用户默认系统中的 AppleMomentumScrollSupported
默认设置。
您可以使用以下 Objective-C++ 在您的应用程序中重新启用此功能,您的 SDL_MouseWheel
事件将变得平滑。
NSDictionary *appDefaults = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithBool:YES], @"AppleMomentumScrollSupported",
nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
[appDefaults release];
出于某种原因,@Aleski 的回答不再有效。重新启用此功能的新方法是:
[[NSUserDefaults standardUserDefaults] setBool: YES
forKey: @"AppleMomentumScrollSupported"];
我正在使用 C++ 为 macOS 构建 SDL2 应用程序。我需要一些 "basic" 的应用程序滚动(例如网络浏览器)。我使用 SDL_MouseWheel 事件 实现了这一点,这为我提供了一个功能齐全的 "windows-like" 滚动。我使用的是 Macbook Pro,我想加入触控板的功能。
简单的求一个更好的滚动算法(Macbook的触控板滚动,惯性滚动)
我知道 SDL_MultiGesture 事件,但我真的不知道如何将它们组合起来才能达到我想要的结果。
好的,这就是问题的答案。
首先,您必须手动完成。
我还假定您了解 SDL2 和 C++。
*注意:我只为 Y 轴做滚动(如果你愿意,你可以为两个轴做滚动)。
首先我们需要一些变量:
int scrolling; // flag (scrolling or not)
int scroll_sensitivity = 40; // how fast we want to scroll
double scroll_Y = 0; // current scrolling amount (on Y-Axis)
double scroll_acceleration; // scrolling speed
double scroll_friction = 0.001; // how fast we decelerate
double scroll_prev_pos; // previous event's position
之后您将需要处理 SDL_MultiGesture 事件:
case SDL_MULTIGESTURE:{
if(event.mgesture.numFingers == 2){
if(scrolling == 0){
scrolling = 1;
scroll_prev_pos = event.mgesture.y;
} else{
double dy = event.mgesture.y - scroll_prev_pos;
scroll_acceleration = dy * 40;
scroll_prev_pos = event.mgesture.y;
scrolling = 1;
}
}
break;
}
此外,我们需要在 SDL_FingerDown 事件上停止滚动:
case SDL_FINGERDOWN:{
scrolling = 0;
break;
}
接下来,我们要更新 scroll_Y(将其放入您的 "update" 函数):
if(scrolling){
if(scroll_acceleration > 0) scroll_acceleration -= scroll_friction;
if(scroll_acceleration < 0) scroll_acceleration += scroll_friction;
if(abs(scroll_acceleration) < 0.0005) scroll_acceleration = 0;
scroll_Y += scroll_sensitivity * scroll_acceleration;
// Here you have to set your scrolling bounds i.e. if(scroll_Y < 0) scroll_Y = 0;
}
最后,我们要根据滚动值进行渲染:
SDL_Rect rect = {some_x, some_y + scroll_Y, some_w, some_h};
SDL_RenderCopy(renderer, some_texture, NULL, &rect);
就是这个!
我有一个使用上述代码的完全可用的应用程序,所以我 100% 确定它会按预期工作。如果您有任何问题(因为它不是实际代码,它更像是一种算法)请与我联系。正如我之前提到的,我假设您已经足够了解 SDL 和 C++,因此我相信您能够理解实现。
另外,我知道这个解决方案可以变得更好,所以如果您有任何要添加/更改的内容,请尽管说出来!
祝你有个愉快的一天!
我 运行 遇到了同样的问题,结果是 SDL opts out of momentum scroll events 通过关闭用户默认系统中的 AppleMomentumScrollSupported
默认设置。
您可以使用以下 Objective-C++ 在您的应用程序中重新启用此功能,您的 SDL_MouseWheel
事件将变得平滑。
NSDictionary *appDefaults = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithBool:YES], @"AppleMomentumScrollSupported",
nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
[appDefaults release];
出于某种原因,@Aleski 的回答不再有效。重新启用此功能的新方法是:
[[NSUserDefaults standardUserDefaults] setBool: YES
forKey: @"AppleMomentumScrollSupported"];