使用SDL2进行平滑(惯性)滚动?

时间:2017-04-11 01:26:16

标签: c++ scroll sdl sdl-2

我正在使用C ++为 macOS 构建 SDL2 应用程序。我需要一些"基本"滚动应用程序(如Web浏览器)。我使用 SDL_MouseWheel事件来实现这一点,这为我提供了一个功能齐全的"类似Windows的"滚动。我正在使用Macbook Pro,我想将触控板的功能带入。

简单地说,我要求更好的滚动算法( Macbook&#39触控板滚动,惯性滚动

我知道 SDL_MultiGesture事件,但我真的不知道如何把事情放在一起以达到我想要的效果。

3 个答案:

答案 0 :(得分:4)

我遇到了同样的问题,并且通过关闭用户默认系统中的AppleMomentumScrollSupported默认值来证明SDL opts out of momentum scroll events

您可以使用以下位Objective-C ++在您的应用程序中重新启用此功能,您的SDL_MouseWheel事件将变得平滑。

NSDictionary *appDefaults = [[NSDictionary alloc] initWithObjectsAndKeys:
                            [NSNumber numberWithBool:YES], @"AppleMomentumScrollSupported",
                            nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
[appDefaults release];

答案 1 :(得分:1)

好的,这就是问题的答案。

首先,您必须手动完成。 我还假设您了解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(将其放入"更新"功能):

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 ++已经足够好了,所以我相信您能够理解实现。 另外,我知道这个解决方案可以变得更好,所以如果您有任何需要添加/更改的内容,请说出来!

祝你有愉快的一天!

答案 2 :(得分:1)

由于某种原因,@ Aleski的答案不再起作用。重新破解此功能的新方法是:

[[NSUserDefaults standardUserDefaults] setBool: YES
                                       forKey: @"AppleMomentumScrollSupported"];