flutter游戏开发flame(二)状态、登录、主场景

接着教程一,不讲废话,开始创建游戏主体功能,本来想分功能来讲像手柄什么的,想想还是按项目模块来讲,按顺序用到了什么就讲什么:

bloc状态

在main中声明了一个全局状态GlobalCubit globalCubit = GlobalCubit();,让我们看下这个状态应该怎么写:

  1. global_cubit.dart
js 复制代码
class GlobalCubit extends Cubit<GlobalState> {
  GlobalCubit() : super(GlobalInitial(0));

  increment() {
    emit(GlobalInitial(state.count + 1));
  }
}

这里要注意的是emit传一个新的state,直接改state上的状态是不生效的。

  1. global_state.dart
js 复制代码
@immutable
abstract class GlobalState {
  int count = 0;
}

class GlobalInitial extends GlobalState {
  GlobalInitial(int count) {
    this.count = count;
  }
}

这里只是意思下只定义了一个count,登录信息等等都可以放在这。

登录

先上代码:

js 复制代码
class LoginWidget extends StatefulWidget {
  const LoginWidget({super.key});

  @override
  State<StatefulWidget> createState() {
    return LoginWidgetState();
  }
}

class LoginWidgetState extends State<LoginWidget> {
  @override
  Widget build(BuildContext context) {
    return BlocProvider.value(
      value: app.globalCubit,
      child: BlocBuilder<GlobalCubit, GlobalState>(
        builder: (context, state) => Material(
          child: Container(
            width: double.infinity,
            height: double.infinity,
            decoration: const BoxDecoration(
              image: DecorationImage(
                image: AssetImage("assets/images/login_bg.png"),
                fit: BoxFit.cover,
              ),
            ),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Text(
                  '游戏名${state.count}',
                  textAlign: TextAlign.center,
                  style: const TextStyle(color: Colors.red, fontSize: 24),
                ),
                Container(
                  margin: const EdgeInsets.only(top: 10),
                  width: 200,
                  color: Colors.white,
                  child: TextField(
                    maxLines: 1,
                    controller: TextEditingController(),
                    decoration: const InputDecoration(
                      hintText: '用户名',
                      contentPadding: EdgeInsets.fromLTRB(10, 0, 10, 0),
                    ),
                  ),
                ),
                Container(
                  width: 200,
                  margin: const EdgeInsets.only(top: 10, bottom: 10),
                  color: Colors.white,
                  child: TextField(
                    maxLines: 1,
                    controller: TextEditingController(),
                    decoration: const InputDecoration(
                      hintText: '密码',
                      contentPadding: EdgeInsets.fromLTRB(10, 0, 10, 0),
                    ),
                  ),
                ),
                ElevatedButton(
                  onPressed: () {
                    // context.read<GlobalCubit>().increment();
                    app.globalCubit.increment();
                    Navigator.pushReplacementNamed(context, "game");
                  },
                  style: const ButtonStyle(
                      // backgroundColor: MaterialStateProperty.all(Colors.red),
                      ),
                  child: const SizedBox(
                    width: 170,
                    child: Text(
                      '登 录',
                      textAlign: TextAlign.center,
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

内容很简单,就是一个背景、两个输入框、一个登录按钮。这里要格外注意的一点是:因为是全局的原因,必须是BlocProvider.value这种形式,如果是builder形式在跳转后,页面销毁,state会被close掉,后续使用就状态异常了。

主场景

老规矩,先上代码再讲:

js 复制代码
class MyGame extends ContextGame {
  late TiledComponent mapComponent;
  late final CameraComponent cameraComponent;

  MyGame(super.context);

  @override
  Future<void> onLoad() async {
    var joystick = MyJoystickComponent();
    add(joystick);
    var player = PlayerComponent(joystick);
    var skillJoystick = SkillJoystickComponent(
      size: Vector2(200, 200),
      position: Vector2(canvasSize.x - 200, canvasSize.y - 200),
      player: player,
    );
    add(skillJoystick);
    final world = CollisionDetectionWorld();
    final CameraComponent cameraComponent = CameraComponent(world: world);
    // final CameraComponent cameraComponent = CameraComponent.withFixedResolution(
    //   world: world,
    //   width: 16 * 280,
    //   height: 16 * 140,
    // );
    mapComponent = await TiledComponent.load('map1.tmx', Vector2(32.0, 32.0));
    world.add(mapComponent);
    world.add(player);
    // world.add(RectangleCollidable(canvasSize));
    cameraComponent.follow(player);
    //获取硬币的占位,然后动态添加
    final objectGroup = mapComponent.tileMap.getLayer<ObjectGroup>('AnimatedCoins');
    for (final object in objectGroup!.objects) {
      world.add(CoinComponent(position: Vector2(object.x, object.y)));
    }

    addAll([cameraComponent]);
    await add(FlameMultiBlocProvider(
      providers: [FlameBlocProvider<GlobalCubit, GlobalState>.value(value: app.globalCubit)],
      children: [world],
    ));
  }
}

这里我把经常用的的组件基本都上了:

  1. joystick 手柄:这个框架自带了一个基本可以直接使用。
  2. player 游戏主角
  3. skillJoystick:自定义的一个技能盘
  4. world:1.8.2以前没有world这个概念,其实就是在Game增加了个layer,相当于安卓activity中放了个fragment,切换场景功能的增强。
  5. cameraComponent:1.8.2以前Game自带了一个camera对象,1.8.2以后就开始废弃了。cameraComponent.follow(player);让视口跟着主角。
  6. mapComponent:背景地图。这里直接加载tmx资源。地图中有一些比如金币什么的需要动态创建,因为还有吃掉硬币的碰撞检查。
  7. FlameMultiBlocProvider:全局状态绑定

至此app运行后可能是这个样子的:

相关推荐
黑客说27 分钟前
AI驱动剧情,解锁无限可能——AI游戏发展解析
人工智能·游戏
亚历克斯神1 小时前
Flutter for OpenHarmony: Flutter 三方库 mutex 为鸿蒙异步任务提供可靠的临界资源互斥锁(并发安全基石)
android·数据库·安全·flutter·华为·harmonyos
钛态1 小时前
Flutter 三方库 smartstruct 鸿蒙化字段映射适配指南:介入静态预编译引擎扫除视图及数据模型双向强转类型错乱隐患,筑稳如磐石的企业级模型治理防线-适配鸿蒙 HarmonyOS ohos
flutter·华为·harmonyos
键盘鼓手苏苏1 小时前
Flutter 组件 csv2json 适配鸿蒙 HarmonyOS 实战:高性能异构数据转换,构建 CSV 流式解析与全栈式数据映射架构
flutter·harmonyos·鸿蒙·openharmony
左手厨刀右手茼蒿1 小时前
Flutter 组件 http_requests 适配鸿蒙 HarmonyOS 实战:极简网络请求,构建边缘端轻量级 RESTful 通讯架构
网络·flutter·http
雷帝木木1 小时前
Flutter 三方库 hrk_logging 的鸿蒙化适配指南 - 实现标准化分层日志记录、支持多目的地输出与日志分级过滤
flutter·harmonyos·鸿蒙·openharmony·hrk_logging
左手厨刀右手茼蒿1 小时前
Flutter 三方库 dio_compatibility_layer 的鸿蒙化适配指南 - 实现 Dio 跨主版本的平滑迁移、支持遗留拦截器兼容与网络请求架构稳定升级
flutter·harmonyos·鸿蒙·openharmony·dio_compatibility_layer
雷帝木木1 小时前
Flutter 三方库 hashids2 基于鸿蒙安全内核的深度隐匿映射适配:数字指纹泄露防御层、生成短小精悍唯一不可逆加盐哈希,护航全链路请求 URL 隐私-适配鸿蒙 HarmonyOS ohos
安全·flutter·harmonyos
智算菩萨2 小时前
【OpenGL】10 完整游戏开发实战:基于OpenGL的2D/3D游戏框架、物理引擎集成与AI辅助编程指南
人工智能·python·游戏·3d·矩阵·pygame·opengl
王码码20354 小时前
Flutter 组件 inappwebview_cookie_manager 适配 鸿蒙Harmony 实战 - 驾驭核心大 Web 容器缓存隧道、构建金融级政企应用绝对防串号跨域大隔离基座
flutter·harmonyos·鸿蒙·openharmony·inappwebview_cookie_manager