Flutter游戏手柄控制插件sdl_gamepad的使用

Flutter游戏手柄控制插件sdl_gamepad的使用

通过 SDL3 后端(感谢 package:sdl3)读取和控制游戏手柄。

特性

  • 通过设备ID或玩家索引打开游戏手柄。
  • 广泛支持震动,包括DualSense触发震动。
  • 查询游戏手柄当前状态及哪些按钮被按下。
  • 查询游戏手柄的其他USB信息、设备信息和电源信息。

开始使用

该包需要在您的系统上有一个编译好的动态链接的SDL3二进制文件。这意味着一个 .dll(Windows),.dylib(Mac),或者 .so(Linux)。更多详情请参阅构建SDL 3.0页面。当原生资产普遍可用时,此需求将由该包处理。

使用方法

if (!SdlLibrary.init()) {
  print("Could not open SDL");
  return;
};

final gamepad = SdlGamepad.fromPlayerIndex(0);
if (!gamepad.isConnected) {
  print("Gamepad is not connected");
  return;
}

final state = gamepad.getState();
print("Is A pressed? ${state.buttonA}");

SdlLibrary.dispose();

额外信息

该包仅仅是 sdl3 包 的一个包装,由 sansuido 提供,查看他的其他项目并支持他!

该包旨在仅作为sdl3包的一个薄层包装,以使API更符合Dart语言风格。如果缺少某些功能,请提交问题,但添加sdl3中不存在的功能不在本项目的范围内。

示例代码

以下是一个完整的示例代码,展示了如何使用 sdl_gamepad 插件来获取和控制连接的游戏手柄。

// ignore_for_file: avoid_print

import "package:sdl_gamepad/sdl_gamepad.dart";

Future<void> main(List<String> args) async {
  if (!SdlLibrary.init()) {
    final error = SdlLibrary.getError();
    print("Could not initialize SDL: $error");
    return SdlLibrary.dispose();
  }

  if (args.isEmpty) {
    final gamepads = SdlGamepad.getConnectedGamepadIds();
    if (gamepads.isEmpty) {
      print("There are no connected gamepads");
      return SdlLibrary.dispose();
    }
    print("Connected gamepads: ");
    for (final gamepadId in gamepads) {
      final info = SdlGamepad.getInfoForGamepadId(gamepadId);
      print("- Gamepad #$gamepadId");
      print("  Name: ${info.name}");
      print("  Gamepad type: ${info.type}");
      print("  Path: ${info.path}");
    }
    print("\nRun again with the ID, eg, dart example/sdl_gamepad.dart 1");
    return SdlLibrary.dispose();
  }

  final arg = int.tryParse(args.first);
  if (arg == null) {
    print("If you provide an argument, it must be a gamepad ID (integer)");
    return SdlLibrary.dispose();
  }

  final gamepad = SdlGamepad.fromGamepadIndex(arg);
  if (!gamepad.isConnected) {
    print("That gamepad is not connected");
    return SdlLibrary.dispose();
  }

  while (true) {
    final state = gamepad.getState();
    if (state.buttonStart) break;

    final left = 
      "Left stick: ${state.normalLeftJoystickX}/${state.normalLeftJoystickY}";
    final right = 
      "Right stick: ${state.normalRightJoystickX}/${state.normalRightJoystickY}";

    print("$left, $right");

    await Future<void>.delayed(const Duration(milliseconds: 100));
  }

  SdlLibrary.dispose();
}

代码解释

  1. 初始化SDL库

    if (!SdlLibrary.init()) {
      final error = SdlLibrary.getError();
      print("Could not initialize SDL: $error");
      return SdlLibrary.dispose();
    }
    

    这段代码检查是否成功初始化了SDL库,并打印错误信息。

  2. 获取连接的游戏手柄列表

    final gamepads = SdlGamepad.getConnectedGamepadIds();
    if (gamepads.isEmpty) {
      print("There are no connected gamepads");
      return SdlLibrary.dispose();
    }
    

    获取所有连接的游戏手柄ID,并检查是否有游戏手柄连接。

  3. 获取游戏手柄信息

    for (final gamepadId in gamepads) {
      final info = SdlGamepad.getInfoForGamepadId(gamepadId);
      print("- Gamepad #$gamepadId");
      print("  Name: ${info.name}");
      print("  Gamepad type: ${info.type}");
      print("  Path: ${info.path}");
    }
    

    遍历每个游戏手柄ID,并获取其详细信息。

  4. 根据提供的ID选择游戏手柄

    final arg = int.tryParse(args.first);
    if (arg == null) {
      print("If you provide an argument, it must be a gamepad ID (integer)");
      return SdlLibrary.dispose();
    }
    
    final gamepad = SdlGamepad.fromGamepadIndex(arg);
    if (!gamepad.isConnected) {
      print("That gamepad is not connected");
      return SdlLibrary.dispose();
    }
    

    如果提供了命令行参数,则解析为游戏手柄ID,并检查该游戏手柄是否已连接。

  5. 循环读取游戏手柄状态

    while (true) {
      final state = gamepad.getState();
      if (state.buttonStart) break;
    
      final left = 
        "Left stick: ${state.normalLeftJoystickX}/${state.normalLeftJoystickY}";
      final right = 
        "Right stick: ${state.normalRightJoystickX}/${state.normalRightJoystickY}";
    
      print("$left, $right");
    
      await Future<void>.delayed(const Duration(milliseconds: 100));
    }
    

    循环读取游戏手柄的状态,直到按下开始按钮为止。每100毫秒更新一次左右摇杆的状态。

  6. 清理资源

    SdlLibrary.dispose();
    

更多关于Flutter游戏手柄控制插件sdl_gamepad的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter游戏手柄控制插件sdl_gamepad的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中使用SDL游戏手柄控制插件(如sdl_gamepad)可以让你的应用支持游戏手柄输入。以下是一个基本的使用指南,帮助你集成和测试游戏手柄控制功能。

1. 添加依赖

首先,在pubspec.yaml文件中添加sdl_gamepad插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  sdl_gamepad: ^0.1.0  # 请确保使用最新版本

然后运行flutter pub get来获取依赖。

2. 初始化SDL

在你的Flutter应用中,首先需要初始化SDL库。通常,这会在main函数中完成。

import 'package:sdl_gamepad/sdl_gamepad.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // 初始化SDL
  Sdl.init();
  
  runApp(MyApp());
}

3. 监听游戏手柄事件

接下来,你可以创建一个GamepadListener来监听游戏手柄的输入事件。

import 'package:flutter/material.dart';
import 'package:sdl_gamepad/sdl_gamepad.dart';

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: GamepadScreen(),
    );
  }
}

class GamepadScreen extends StatefulWidget {
  [@override](/user/override)
  _GamepadScreenState createState() => _GamepadScreenState();
}

class _GamepadScreenState extends State<GamepadScreen> {
  String _gamepadStatus = 'No gamepad connected';

  [@override](/user/override)
  void initState() {
    super.initState();
    _initGamepad();
  }

  void _initGamepad() {
    SdlGamepad gamepad = SdlGamepad();

    gamepad.onConnect.listen((event) {
      setState(() {
        _gamepadStatus = 'Gamepad connected: ${event.deviceName}';
      });
    });

    gamepad.onDisconnect.listen((event) {
      setState(() {
        _gamepadStatus = 'Gamepad disconnected';
      });
    });

    gamepad.onButtonDown.listen((event) {
      setState(() {
        _gamepadStatus = 'Button ${event.button} pressed';
      });
    });

    gamepad.onButtonUp.listen((event) {
      setState(() {
        _gamepadStatus = 'Button ${event.button} released';
      });
    });

    gamepad.onAxisMove.listen((event) {
      setState(() {
        _gamepadStatus = 'Axis ${event.axis} moved to ${event.value}';
      });
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Gamepad Control'),
      ),
      body: Center(
        child: Text(_gamepadStatus),
      ),
    );
  }
}

4. 运行应用

现在你可以在设备或模拟器上运行应用,并连接一个游戏手柄。应用将显示游戏手柄的连接状态以及按钮和轴的输入。

5. 处理输入

gamepad.onButtonDowngamepad.onButtonUpgamepad.onAxisMove事件中,你可以根据游戏手柄的输入来更新应用的状态。例如,你可以根据按钮的按下或轴的移动来控制游戏中的角色或对象。

6. 清理资源

在应用关闭时,确保释放SDL资源。

[@override](/user/override)
void dispose() {
  Sdl.quit();
  super.dispose();
}
回到顶部