SDL3_API分类参考_触觉反馈(CategoryHaptic)

2026-3-6 / 0 评论 / 2 阅读

触觉反馈子系统(CategoryHaptic)

SDL 触觉反馈(Haptic)子系统用于管理力反馈(force feedback)设备,如带震动功能的游戏手柄、方向盘、力反馈鼠标等,可实现震动、力反馈等触觉效果。

基础使用流程

  1. 初始化子系统(传入 SDL_INIT_HAPTIC 标志);
  2. 打开触觉反馈设备:
    • 通过索引打开:SDL_OpenHaptic()
    • 从已打开的游戏手柄打开:SDL_OpenHapticFromJoystick()
  3. 创建触觉效果(定义 SDL_HapticEffect 结构体);
  4. 上传效果:SDL_CreateHapticEffect()
  5. 运行效果:SDL_RunHapticEffect()
  6. (可选)释放效果:SDL_DestroyHapticEffect()
  7. 关闭设备:SDL_CloseHaptic()

简单震动示例(C语言)

   SDL_Haptic *haptic = NULL;

   // 打开设备
   SDL_HapticID *haptics = SDL_GetHaptics(NULL);
   if (haptics) {
       haptic = SDL_OpenHaptic(haptics[0]);
       SDL_free(haptics);
   }
   if (haptic == NULL)
      return;

   // 初始化简易震动
   if (!SDL_InitHapticRumble(haptic))
      return;

   // 以50%强度播放震动效果,持续2秒
   if (!SDL_PlayHapticRumble(haptic, 0.5, 2000))
      return;
   SDL_Delay(2000);

   // 清理资源
   SDL_CloseHaptic(haptic);

完整效果示例(C语言)

bool test_haptic(SDL_Joystick *joystick)
{
   SDL_Haptic *haptic;
   SDL_HapticEffect effect;
   SDL_HapticEffectID effect_id;

   // 从游戏手柄打开触觉设备
   haptic = SDL_OpenHapticFromJoystick(joystick);
   if (haptic == NULL) return false; // 大概率手柄不支持触觉反馈

   // 检查是否支持正弦波效果
   if ((SDL_GetHapticFeatures(haptic) & SDL_HAPTIC_SINE)==0) {
      SDL_CloseHaptic(haptic); // 不支持正弦效果
      return false;
   }

   // 创建效果
   SDL_memset(&effect, 0, sizeof(SDL_HapticEffect)); // 0为安全默认值
   effect.type = SDL_HAPTIC_SINE;
   effect.periodic.direction.type = SDL_HAPTIC_POLAR; // 极坐标
   effect.periodic.direction.dir[0] = 18000; // 力来自南方(180度)
   effect.periodic.period = 1000; // 周期1000毫秒
   effect.periodic.magnitude = 20000; // 强度 20000/32767
   effect.periodic.length = 5000; // 持续5秒
   effect.periodic.attack_length = 1000; // 1秒达到最大强度
   effect.periodic.fade_length = 1000; // 1秒渐弱至消失

   // 上传效果
   effect_id = SDL_CreateHapticEffect(haptic, &effect);

   // 测试效果
   SDL_RunHapticEffect(haptic, effect_id, 1);
   SDL_Delay(5000); // 等待效果结束

   // 销毁效果(关闭设备时也会自动销毁)
   SDL_DestroyHapticEffect(haptic, effect_id);

   // 关闭设备
   SDL_CloseHaptic(haptic);

   return true; // 成功
}

注意:SDL 触觉反馈子系统非线程安全,需确保所有操作在同一线程执行。


函数

  • SDL_CloseHaptic:关闭已打开的触觉反馈设备(释放设备资源,终止力反馈效果)
  • SDL_CreateHapticEffect:上传触觉效果到设备(将定义的效果参数写入硬件,返回效果ID)
  • SDL_DestroyHapticEffect:销毁已上传的触觉效果(释放设备中该效果的资源)
  • SDL_GetHapticEffectStatus:获取触觉效果的运行状态(如是否正在播放、暂停)
  • SDL_GetHapticFeatures:获取触觉设备支持的功能特性(返回位掩码,如是否支持正弦波、震动等)
  • SDL_GetHapticFromID:通过触觉设备ID获取对应的 SDL_Haptic 指针
  • SDL_GetHapticID:获取已打开触觉设备的唯一标识ID
  • SDL_GetHapticName:获取已打开触觉设备的名称
  • SDL_GetHapticNameForID:通过触觉设备ID获取设备名称
  • SDL_GetHaptics:枚举系统中所有触觉设备(返回设备ID列表及数量)
  • SDL_GetMaxHapticEffects:获取设备支持的最大效果数量(硬件可存储的效果总数)
  • SDL_GetMaxHapticEffectsPlaying:获取设备可同时播放的最大效果数量
  • SDL_GetNumHapticAxes:获取触觉设备的轴数量(如X/Y/Z轴)
  • SDL_HapticEffectSupported:检查设备是否支持指定类型的触觉效果
  • SDL_HapticRumbleSupported:检查设备是否支持简易震动(Rumble)功能
  • SDL_InitHapticRumble:初始化设备的简易震动功能(启用基础震动模式)
  • SDL_IsJoystickHaptic:检查指定游戏手柄是否支持触觉反馈
  • SDL_IsMouseHaptic:检查指定鼠标是否支持触觉反馈
  • SDL_OpenHaptic:通过设备索引打开触觉反馈设备
  • SDL_OpenHapticFromJoystick:从已打开的游戏手柄打开触觉反馈设备
  • SDL_OpenHapticFromMouse:从已打开的鼠标打开触觉反馈设备
  • SDL_PauseHaptic:暂停设备上所有正在播放的触觉效果
  • SDL_PlayHapticRumble:播放简易震动效果(指定强度和持续时间)
  • SDL_ResumeHaptic:恢复暂停的触觉效果
  • SDL_RunHapticEffect:运行指定的触觉效果(可指定循环次数)
  • SDL_SetHapticAutocenter:设置触觉设备的自动居中强度(如方向盘自动回中)
  • SDL_SetHapticGain:设置触觉设备的增益(整体强度缩放,0~100%)
  • SDL_StopHapticEffect:停止指定的触觉效果
  • SDL_StopHapticEffects:停止设备上所有正在播放的触觉效果
  • SDL_StopHapticRumble:停止正在播放的简易震动效果
  • SDL_UpdateHapticEffect:更新已上传的触觉效果参数(修改效果属性)

数据类型

  • SDL_Haptic:触觉反馈设备句柄类型(标识已打开的触觉设备)
  • SDL_HapticDirectionType:触觉效果方向类型(如笛卡尔坐标、极坐标、球坐标)
  • SDL_HapticEffectID:触觉效果ID类型(标识设备中已上传的具体效果)
  • SDL_HapticEffectType:触觉效果类型(如正弦波、方波、震动、常量力等)
  • SDL_HapticID:触觉设备ID类型(区分系统中的不同触觉设备)

结构体

  • SDL_HapticCondition:条件触觉效果结构体(如弹簧、阻尼、惯性等效果参数)
  • SDL_HapticConstant:常量力触觉效果结构体(持续恒定的力反馈)
  • SDL_HapticCustom:自定义触觉效果结构体(用户定义的波形数据)
  • SDL_HapticDirection:触觉效果方向结构体(定义力的方向)
  • SDL_HapticEffect:通用触觉效果结构体(包含所有类型效果的参数)
  • SDL_HapticLeftRight:左右声道震动效果结构体(手柄左右电机独立控制)
  • SDL_HapticPeriodic:周期性触觉效果结构体(正弦波、方波、三角波等)
  • SDL_HapticRamp:渐变力触觉效果结构体(力从初始值线性变化到目标值)

枚举

  • (无)

  • SDL_HAPTIC_AUTOCENTER:自动居中功能标识(用于 SDL_GetHapticFeatures)
  • SDL_HAPTIC_CARTESIAN:笛卡尔坐标方向类型(X/Y/Z轴)
  • SDL_HAPTIC_CONSTANT:常量力效果类型
  • SDL_HAPTIC_CUSTOM:自定义效果类型
  • SDL_HAPTIC_DAMPER:阻尼效果类型(阻力随速度增加)
  • SDL_HAPTIC_FRICTION:摩擦力效果类型(恒定阻力)
  • SDL_HAPTIC_GAIN:增益功能标识
  • SDL_HAPTIC_INERTIA:惯性效果类型(阻力随加速度增加)
  • SDL_HAPTIC_INFINITY:无限循环标识(效果持续播放直到停止)
  • SDL_HAPTIC_LEFTRIGHT:左右震动效果类型(手柄双电机)
  • SDL_HAPTIC_PAUSE:暂停状态标识
  • SDL_HAPTIC_POLAR:极坐标方向类型(角度/半径)
  • SDL_HAPTIC_RAMP:渐变力效果类型
  • SDL_HAPTIC_RESERVED1/2/3:预留标识
  • SDL_HAPTIC_SAWTOOTHDOWN:锯齿波(下降)效果类型
  • SDL_HAPTIC_SAWTOOTHUP:锯齿波(上升)效果类型
  • SDL_HAPTIC_SINE:正弦波效果类型
  • SDL_HAPTIC_SPHERICAL:球坐标方向类型(方位角/仰角)
  • SDL_HAPTIC_SPRING:弹簧效果类型(力随位移增加)
  • SDL_HAPTIC_SQUARE:方波效果类型
  • SDL_HAPTIC_STATUS:状态查询标识
  • SDL_HAPTIC_STEERING_AXIS:方向盘轴标识
  • SDL_HAPTIC_TRIANGLE:三角波效果类型

FreeBASIC 示例代码

' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库)
#Include "SDL.bi"

' 简易震动效果示例
Sub TestSimpleRumble()
    SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "==== 测试简易震动效果 ====")

    ' 1. 枚举触觉设备
    Dim As Integer hapticCount = SDL_GetHaptics(NULL, 0)
    If (hapticCount = 0) Then
        SDL_LogError(SDL_LOG_CATEGORY_INPUT, "未检测到触觉反馈设备:%s", SDL_GetError())
        Return
    End If

    ' 分配内存存储设备ID
    Dim As SDL_HapticID Ptr hapticIDs = Callocate(hapticCount * SizeOf(SDL_HapticID))
    If (hapticIDs = NULL) Then
        SDL_LogError(SDL_LOG_CATEGORY_INPUT, "分配内存失败")
        Return
    End If

    ' 获取设备ID列表
    hapticCount = SDL_GetHaptics(hapticIDs, hapticCount)
    SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "检测到 %d 个触觉设备", hapticCount)

    ' 2. 打开第一个触觉设备
    Dim As SDL_Haptic Ptr haptic = SDL_OpenHaptic(hapticIDs[0])
    If (haptic = NULL) Then
        SDL_LogError(SDL_LOG_CATEGORY_INPUT, "打开触觉设备失败:%s", SDL_GetError())
        Deallocate(hapticIDs)
        Return
    End If

    ' 获取设备信息
    Dim As ZString Ptr hapticName = SDL_GetHapticName(haptic)
    SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "已打开设备:%s", hapticName)

    ' 3. 检查是否支持震动
    If (Not SDL_HapticRumbleSupported(haptic)) Then
        SDL_LogError(SDL_LOG_CATEGORY_INPUT, "该设备不支持简易震动功能")
        SDL_CloseHaptic(haptic)
        Deallocate(hapticIDs)
        If (hapticName <> NULL) Then SDL_free(hapticName)
        Return
    End If

    ' 4. 初始化震动功能
    If (Not SDL_InitHapticRumble(haptic)) Then
        SDL_LogError(SDL_LOG_CATEGORY_INPUT, "初始化震动功能失败:%s", SDL_GetError())
        SDL_CloseHaptic(haptic)
        Deallocate(hapticIDs)
        If (hapticName <> NULL) Then SDL_free(hapticName)
        Return
    End If

    ' 5. 播放不同强度的震动
    SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "播放 25% 强度震动(1秒)")
    SDL_PlayHapticRumble(haptic, 0.25, 1000)
    SDL_Delay(1000)

    SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "播放 75% 强度震动(2秒)")
    SDL_PlayHapticRumble(haptic, 0.75, 2000)
    SDL_Delay(2000)

    SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "播放 100% 强度震动(0.5秒)")
    SDL_PlayHapticRumble(haptic, 1.0, 500)
    SDL_Delay(500)

    ' 6. 停止震动
    SDL_StopHapticRumble(haptic)
    SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "已停止震动")

    ' 7. 清理资源
    SDL_CloseHaptic(haptic)
    Deallocate(hapticIDs)
    If (hapticName <> NULL) Then SDL_free(hapticName)

    SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "简易震动测试完成")
End Sub

' 复杂正弦波效果示例
Sub TestSineEffect()
    SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, vbCrLf & "==== 测试正弦波触觉效果 ====")

    ' 1. 枚举并打开第一个触觉设备
    Dim As SDL_HapticID Ptr hapticIDs = SDL_GetHaptics(NULL)
    If (hapticIDs = NULL) Then
        SDL_LogError(SDL_LOG_CATEGORY_INPUT, "未检测到触觉设备:%s", SDL_GetError())
        Return
    End If

    Dim As SDL_Haptic Ptr haptic = SDL_OpenHaptic(hapticIDs[0])
    SDL_free(hapticIDs)

    If (haptic = NULL) Then
        SDL_LogError(SDL_LOG_CATEGORY_INPUT, "打开触觉设备失败:%s", SDL_GetError())
        Return
    End If

    ' 2. 检查是否支持正弦波效果
    Dim As Uint32 features = SDL_GetHapticFeatures(haptic)
    If ((features And SDL_HAPTIC_SINE) = 0) Then
        SDL_LogError(SDL_LOG_CATEGORY_INPUT, "该设备不支持正弦波触觉效果")
        SDL_CloseHaptic(haptic)
        Return
    End If

    SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "设备支持正弦波效果")

    ' 3. 定义正弦波效果
    Dim As SDL_HapticEffect effect
    SDL_memset(@effect, 0, SizeOf(SDL_HapticEffect))

    ' 设置效果类型为正弦波
    effect.type = SDL_HAPTIC_SINE

    ' 设置方向(极坐标,180度=南方)
    effect.periodic.direction.type = SDL_HAPTIC_POLAR
    effect.periodic.direction.dir[0] = 18000 ' 角度(0~35999)
    effect.periodic.direction.dir[1] = 0     ' 半径(仅球坐标使用)

    ' 正弦波参数
    effect.periodic.period = 500    ' 周期(毫秒)
    effect.periodic.magnitude = 16383 ' 幅度(0~32767,50%强度)
    effect.periodic.offset = 0      ' 偏移量
    effect.periodic.phase = 0       ' 相位(0~35999)

    ' 效果时长
    effect.periodic.length = 3000   ' 总时长(毫秒)
    effect.periodic.attack_length = 500 ' 攻击时长(渐强,毫秒)
    effect.periodic.fade_length = 500   ' 衰减时长(渐弱,毫秒)
    effect.periodic.attack_level = 0    ' 攻击起始强度
    effect.periodic.fade_level = 0      ' 衰减结束强度

    ' 4. 上传效果
    Dim As SDL_HapticEffectID effectID = SDL_CreateHapticEffect(haptic, @effect)
    If (effectID < 0) Then
        SDL_LogError(SDL_LOG_CATEGORY_INPUT, "上传效果失败:%s", SDL_GetError())
        SDL_CloseHaptic(haptic)
        Return
    End If

    SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "成功上传正弦波效果(ID:%d)", effectID)

    ' 5. 运行效果(播放1次)
    SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "播放正弦波效果(3秒)")
    If (SDL_RunHapticEffect(haptic, effectID, 1) < 0) Then
        SDL_LogError(SDL_LOG_CATEGORY_INPUT, "运行效果失败:%s", SDL_GetError())
    Else
        SDL_Delay(3000) ' 等待效果结束
    End If

    ' 6. 销毁效果
    SDL_DestroyHapticEffect(haptic, effectID)
    SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "已销毁正弦波效果")

    ' 7. 清理资源
    SDL_CloseHaptic(haptic)
    SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "复杂效果测试完成")
End Sub

' 从游戏手柄打开触觉设备示例
Sub TestJoystickHaptic()
    SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, vbCrLf & "==== 测试游戏手柄触觉反馈 ====")

    ' 1. 枚举游戏手柄
    Dim As Integer joystickCount = SDL_GetJoysticks(NULL, 0)
    If (joystickCount = 0) Then
        SDL_LogError(SDL_LOG_CATEGORY_INPUT, "未检测到游戏手柄:%s", SDL_GetError())
        Return
    End If

    ' 2. 打开第一个游戏手柄
    Dim As SDL_JoystickID Ptr joystickIDs = SDL_GetJoysticks(NULL)
    Dim As SDL_Joystick Ptr joystick = SDL_OpenJoystick(joystickIDs[0])
    SDL_free(joystickIDs)

    If (joystick = NULL) Then
        SDL_LogError(SDL_LOG_CATEGORY_INPUT, "打开游戏手柄失败:%s", SDL_GetError())
        Return
    End If

    ' 3. 检查手柄是否支持触觉反馈
    If (Not SDL_IsJoystickHaptic(joystick)) Then
        SDL_LogError(SDL_LOG_CATEGORY_INPUT, "该游戏手柄不支持触觉反馈")
        SDL_CloseJoystick(joystick)
        Return
    End If

    ' 4. 从手柄打开触觉设备
    Dim As SDL_Haptic Ptr haptic = SDL_OpenHapticFromJoystick(joystick)
    If (haptic = NULL) Then
        SDL_LogError(SDL_LOG_CATEGORY_INPUT, "从手柄打开触觉设备失败:%s", SDL_GetError())
        SDL_CloseJoystick(joystick)
        Return
    End If

    SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "成功从游戏手柄打开触觉设备")

    ' 5. 测试简易震动
    If (SDL_HapticRumbleSupported(haptic)) Then
        SDL_InitHapticRumble(haptic)
        SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "手柄震动测试(1.5秒)")
        SDL_PlayHapticRumble(haptic, 0.6, 1500)
        SDL_Delay(1500)
        SDL_StopHapticRumble(haptic)
    End If

    ' 6. 清理资源
    SDL_CloseHaptic(haptic)
    SDL_CloseJoystick(joystick)
    SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "游戏手柄触觉测试完成")
End Sub

' 主程序
Sub Main()
    ' 初始化 SDL(包含触觉和游戏手柄子系统)
    If (SDL_Init(SDL_INIT_HAPTIC Or SDL_INIT_JOYSTICK) < 0) Then
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError())
        Exit Sub
    End If

    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "=== SDL 触觉反馈示例程序 ===")

    ' 测试简易震动
    TestSimpleRumble()

    ' 测试复杂正弦波效果
    TestSineEffect()

    ' 测试游戏手柄触觉反馈
    TestJoystickHaptic()

    ' 退出 SDL
    SDL_Quit()

    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "程序结束")
End Sub

' 运行主程序
Main()

核心知识点补充

  1. 触觉效果类型说明 效果类型 特点 适用场景
    简易震动(Rumble) 双电机独立控制强度 游戏中的碰撞、爆炸
    正弦波(Sine) 平滑的周期性震动 发动机震动、心跳
    方波(Square) 强烈的脉冲式震动 枪声、撞击
    常量力(Constant) 持续的恒定力 方向盘力反馈、阻力
    渐变力(Ramp) 线性变化的力 加速/减速感
    弹簧/阻尼 物理模拟的力反馈 赛车游戏方向盘
  2. 开发注意事项

    • 强度范围:触觉效果的强度值范围为 0~32767(16位有符号整数),0 为无效果,32767 为最大强度;
    • 方向设置:极坐标的角度范围为 0~35999(对应 0~360 度),18000 对应 180 度(南方);
    • 跨平台兼容:Windows 平台对触觉效果支持最好,Linux/macOS 次之,移动平台仅部分手柄支持;
    • 线程安全:所有触觉操作必须在同一线程执行,避免多线程同时访问 SDL_Haptic 句柄。
  3. 调试技巧

    • 使用 SDL_GetHapticFeatures 检查设备支持的效果类型,避免创建不支持的效果;
    • 通过 SDL_SetHapticGain 调整整体强度,适配不同设备的震动灵敏度;
    • 复杂效果建议先测试简易震动功能,确认设备可正常工作后再开发。

总结

  1. 核心优势
    • SDL 统一封装了不同平台的触觉反馈接口,无需关注硬件驱动差异;
    • 支持从游戏手柄/鼠标直接打开触觉设备,简化设备管理;
    • 提供简易震动和复杂力反馈两套API,兼顾易用性和灵活性;
  2. 使用建议
    • 优先使用简易震动(Rumble)实现基础震动效果,兼容性最好;
    • 复杂力反馈效果需先检查设备支持性,避免运行时错误;
    • 效果播放完成后及时销毁,避免占用设备资源;
  3. 关键接口
    • 设备管理:SDL_GetHaptics/SDL_OpenHaptic/SDL_CloseHaptic
    • 简易震动:SDL_HapticRumbleSupported/SDL_InitHapticRumble/SDL_PlayHapticRumble
    • 复杂效果:SDL_CreateHapticEffect/SDL_RunHapticEffect/SDL_DestroyHapticEffect

评论一下?

OωO
取消