Flutter for OpenHarmony:打造令人惊艳的《冰火人》双人合作闯关游戏主菜单

在移动应用和游戏中,第一印象至关重要。一个平庸的主菜单可能会让用户瞬间失去兴趣,而一个精心设计、充满活力的主菜单则能立刻抓住眼球,为整个游戏体验定下高水准的基调。本文将深入剖析一段来自《冰火人闯关》游戏的
高度优化版主菜单 代码,揭示如何利用 Flutter 的动画、渐变和自定义绘制能力,将一个简单的入口页面转变为一场视觉盛宴。

完整效果展示
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

一、从静态到动态:赋予菜单生命力

对比基础版本,优化后的 MainMenu 最显著的升级在于其 动态感。它不再是静止的图标和按钮,而是一个拥有呼吸和脉动的生命体。

核心机制:AnimationController 与循环动画

late AnimationController _animationController;

void initState() {
  super.initState();
  _animationController = AnimationController(
    duration: const Duration(milliseconds: 2000),
    vsync: this,
  )..repeat(reverse: true); // 关键:无限循环往复
}

在这里插入图片描述

  • repeat(reverse: true) 是魔法所在。它让动画在正向播放结束后自动反向播放,形成一个无缝的“呼吸”或“心跳”效果,持续时间为4秒(2秒正向 + 2秒反向)。
  • vsync: this 确保了动画与屏幕刷新率同步,避免了不必要的性能消耗。

多重动画协同

代码并非只使用了一个动画,而是通过 Tween 创建了三个相互关联的动画:

  1. _scaleAnimation: 控制游戏图标的缩放(1.0x 到 1.08x),制造出轻微的“膨胀”感。
  2. _opacityAnimation: 控制游戏标题的透明度(0.5 到 1.0),使其产生淡入淡出的效果。
  3. _glowAnimation: 控制图标周围发光 (boxShadow) 的模糊半径(10 到 30),模拟光源强度的变化。

这些动画被 AnimatedBuilder 监听,并实时更新 UI,共同营造出丰富而和谐的动态效果。

二、视觉冲击力:高级图形与色彩运用

1. 背景:戏剧性的对角线渐变

gradient: LinearGradient(
  begin: Alignment.topLeft,
  end: Alignment.bottomRight,
  colors: [Colors.red.shade900, Colors.orange.shade800, Colors.blue.shade800, Colors.blue.shade900],
  stops: [0.0, 0.33, 0.66, 1.0],
)

在这里插入图片描述

  • 这个四色渐变从左上角的深红,经过橙色,过渡到右下角的深蓝,完美呼应了“冰火”主题。
  • stops 参数精确控制了每种颜色的分布区域,使得色彩过渡更加自然和富有层次感,远超简单的双色渐变。

2. 动态粒子背景

Positioned.fill(child: CustomPaint(painter: ParticlePainter()))
  • ParticlePainter 是一个自定义的 CustomPainter,它在画布上随机绘制了80个微小的白色圆点。
  • 虽然粒子本身是静态的,但作为深色渐变背景上的点缀,极大地增加了画面的细节和深度,营造出一种宇宙星空或微观世界的氛围,让背景不再单调。

3. 游戏图标:融合光效与质感

图标被包裹在一个圆形容器中,该容器同时应用了:

  • 前景渐变 (LinearGradient): 从橙色到红色,强化火焰意象。
  • 双重发光阴影 (BoxShadow): 一个明亮的橙色外发光和一个稍暗的蓝色内发光(通过调整 spreadRadius 实现),创造出强烈的立体感和能量感。这个发光效果正是由 _glowAnimation 驱动的。

4. 游戏标题:炫彩的金属文字

ShaderMask(
  shaderCallback: (bounds) => LinearGradient(colors: [Colors.yellow, Colors.orange, ...]).createShader(bounds),
  child: Text('冰火人闯关', ...),
)

在这里插入图片描述

  • ShaderMask 是实现高级文字效果的关键。它用一个从黄到紫的线性渐变着色器 (Shader) 来“切割”白色的文字,最终呈现出彩虹般的金属光泽。
  • 配合 shadows 属性添加的黑色模糊阴影,文字仿佛悬浮于背景之上,极具视觉冲击力。

三、交互体验:精致的按钮设计

主菜单的四个功能按钮(开始游戏、游戏说明、设置、关于)也经过了精心打磨:

1. 悬浮感与深度

每个按钮都拥有一个精心调校的 BoxShadow

BoxShadow(
  color: color.withOpacity(0.4), // 使用按钮主色的半透明版本
  blurRadius: 20,
  offset: Offset(0, 10),
  spreadRadius: -5, // 负值使阴影更集中,增强悬浮感
)

在这里插入图片描述

这种阴影设计让按钮看起来像是漂浮在背景之上,点击时的反馈会更加明显。

2. 统一而有辨识度的风格

  • 所有按钮采用统一的圆角矩形 (borderRadius: 16) 和内边距。
  • 每个按钮左侧都有一个与功能匹配的图标(如 play_arrowmenu_book),并使用对应的主题色(绿色、蓝色、灰色、紫色),在保持整体一致性的同时,提供了清晰的功能指引。

3. 弹性导航与对话框

  • 页面切换:使用 PageRouteBuilder 自定义了从主菜单到关卡选择的过渡动画,结合了淡入 (FadeTransition) 和从底部滑入 (SlideTransition) 的效果,流畅且富有动感。
  • 信息展示:游戏说明、设置和关于页面均以 全屏模态对话框 (Dialog) 的形式弹出。这些对话框自身也带有深灰色渐变背景、圆角和半透明白色边框,风格与主菜单完全统一,提供了一致的沉浸式体验。

四、代码结构:优雅与高效

  • _buildMenuButton 方法:将重复的按钮 UI 逻辑抽象成一个私有方法,遵循了 DRY (Don’t Repeat Yourself) 原则,使 build 方法极其简洁易读。
  • _buildInstructionItem / _buildSettingItem 方法:同样地,将对话框内部的列表项进行了组件化,极大地提升了代码的可维护性和扩展性。

总结

这段优化后的主菜单代码,充分展示了 Flutter 在构建高端 UI 方面的强大实力。它不仅仅是一个功能入口,更是一个集 动态美学、品牌传达和用户体验 于一体的微型艺术品。

🌐 加入社区

欢迎加入 开源鸿蒙跨平台开发者社区,获取最新资源与技术支持:
👉 开源鸿蒙跨平台开发者社区
完整代码展示

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

void main() {
  runApp(const FireboyWatergirlGame());
}

class FireboyWatergirlGame extends StatelessWidget {
  const FireboyWatergirlGame({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '冰火人闯关',
      theme: ThemeData(
        primarySwatch: Colors.orange,
        useMaterial3: true,
        brightness: Brightness.dark,
      ),
      home: const MainMenu(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class MainMenu extends StatefulWidget {
  const MainMenu({super.key});

  @override
  State<MainMenu> createState() => _MainMenuState();
}

class _MainMenuState extends State<MainMenu> with SingleTickerProviderStateMixin {
  late AnimationController _animationController;
  late Animation<double> _scaleAnimation;
  late Animation<double> _opacityAnimation;
  late Animation<double> _glowAnimation;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      duration: const Duration(milliseconds: 2000),
      vsync: this,
    )..repeat(reverse: true);

    _scaleAnimation = Tween<double>(begin: 1.0, end: 1.08).animate(
      CurvedAnimation(parent: _animationController, curve: Curves.easeInOut),
    );

    _opacityAnimation = Tween<double>(begin: 0.5, end: 1.0).animate(
      CurvedAnimation(parent: _animationController, curve: Curves.easeInOut),
    );

    _glowAnimation = Tween<double>(begin: 10, end: 30).animate(
      CurvedAnimation(parent: _animationController, curve: Curves.easeInOut),
    );
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final screenHeight = MediaQuery.of(context).size.height;
    final screenWidth = MediaQuery.of(context).size.width;

    return Scaffold(
      body: Container(
        decoration: BoxDecoration(
          gradient: LinearGradient(
            begin: Alignment.topLeft,
            end: Alignment.bottomRight,
            colors: [
              Colors.red.shade900,
              Colors.orange.shade800,
              Colors.blue.shade800,
              Colors.blue.shade900,
            ],
            stops: const [0.0, 0.33, 0.66, 1.0],
          ),
        ),
        child: Stack(
          children: [
            // 动态背景粒子
            Positioned.fill(
              child: CustomPaint(
                painter: ParticlePainter(),
              ),
            ),
            // 主内容
            Center(
              child: SingleChildScrollView(
                child: Padding(
                  padding: EdgeInsets.symmetric(
                    horizontal: screenWidth * 0.08,
                    vertical: screenHeight * 0.05,
                  ),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      // 游戏图标 - 带动画
                      AnimatedBuilder(
                        animation: Listenable.merge([_scaleAnimation, _glowAnimation]),
                        builder: (context, child) {
                          return Transform.scale(
                            scale: _scaleAnimation.value,
                            child: Container(
                              padding: const EdgeInsets.all(20),
                              decoration: BoxDecoration(
                                gradient: const LinearGradient(
                                  colors: [Colors.orange, Colors.red],
                                  begin: Alignment.topLeft,
                                  end: Alignment.bottomRight,
                                ),
                                shape: BoxShape.circle,
                                boxShadow: [
                                  BoxShadow(
                                    color: Colors.orange.withOpacity(0.4),
                                    blurRadius: _glowAnimation.value,
                                    spreadRadius: 8,
                                  ),
                                  BoxShadow(
                                    color: Colors.blue.withOpacity(0.3),
                                    blurRadius: _glowAnimation.value * 0.8,
                                    spreadRadius: 5,
                                  ),
                                ],
                              ),
                              child: const Icon(
                                Icons.extension,
                                size: 100,
                                color: Colors.white,
                              ),
                            ),
                          );
                        },
                      ),
                      SizedBox(height: screenHeight * 0.03),
                      // 游戏标题 - 渐变文字
                      AnimatedBuilder(
                        animation: _opacityAnimation,
                        builder: (context, child) {
                          return Opacity(
                            opacity: _opacityAnimation.value,
                            child: ShaderMask(
                              shaderCallback: (bounds) => const LinearGradient(
                                colors: [
                                  Colors.yellow,
                                  Colors.orange,
                                  Colors.red,
                                  Colors.purple,
                                ],
                                tileMode: TileMode.mirror,
                                begin: Alignment.topLeft,
                                end: Alignment.bottomRight,
                              ).createShader(bounds),
                              child: const Text(
                                '冰火人闯关',
                                style: TextStyle(
                                  fontSize: 56,
                                  fontWeight: FontWeight.bold,
                                  color: Colors.white,
                                  letterSpacing: 4,
                                  shadows: [
                                    Shadow(
                                      color: Colors.black54,
                                      blurRadius: 20,
                                      offset: Offset(0, 8),
                                    ),
                                  ],
                                ),
                                textAlign: TextAlign.center,
                                maxLines: 1,
                                overflow: TextOverflow.ellipsis,
                              ),
                            ),
                          );
                        },
                      ),
                      SizedBox(height: screenHeight * 0.015),
                      // 副标题
                      Text(
                        'Fireboy & Watergirl Adventure',
                        style: TextStyle(
                          fontSize: 18,
                          color: Colors.white.withOpacity(0.8),
                          letterSpacing: 6,
                          fontWeight: FontWeight.w300,
                        ),
                        textAlign: TextAlign.center,
                        maxLines: 1,
                        overflow: TextOverflow.ellipsis,
                      ),
                      SizedBox(height: screenHeight * 0.08),
                      // 开始游戏按钮
                      _buildMenuButton(
                        icon: Icons.play_arrow_rounded,
                        label: '开始游戏',
                        color: Colors.green,
                        onPressed: () {
                          Navigator.push(
                            context,
                            PageRouteBuilder(
                              pageBuilder: (context, animation, secondaryAnimation) =>
                                  const LevelSelectScreen(),
                              transitionsBuilder: (context, animation, secondaryAnimation, child) {
                                return FadeTransition(
                                  opacity: animation,
                                  child: SlideTransition(
                                    position: Tween<Offset>(
                                      begin: const Offset(0, 1),
                                      end: Offset.zero,
                                    ).animate(CurvedAnimation(
                                      parent: animation,
                                      curve: Curves.easeOut,
                                    )),
                                    child: child,
                                  ),
                                );
                              },
                              transitionDuration: const Duration(milliseconds: 400),
                            ),
                          );
                        },
                      ),
                      SizedBox(height: screenHeight * 0.025),
                      // 游戏说明按钮
                      _buildMenuButton(
                        icon: Icons.menu_book_rounded,
                        label: '游戏说明',
                        color: Colors.blue,
                        onPressed: () => _showInstructions(context),
                      ),
                      SizedBox(height: screenHeight * 0.025),
                      // 设置按钮
                      _buildMenuButton(
                        icon: Icons.settings_rounded,
                        label: '设置',
                        color: Colors.grey.shade700,
                        onPressed: () => _showSettings(context),
                      ),
                      SizedBox(height: screenHeight * 0.025),
                      // 关于按钮
                      _buildMenuButton(
                        icon: Icons.info_outline_rounded,
                        label: '关于',
                        color: Colors.purple.shade600,
                        onPressed: () => _showAbout(context),
                      ),
                      SizedBox(height: screenHeight * 0.04),
                      // 版本信息
                      Text(
                        'Version 1.0.0',
                        style: TextStyle(
                          fontSize: 14,
                          color: Colors.white.withOpacity(0.5),
                          letterSpacing: 1,
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildMenuButton({
    required IconData icon,
    required String label,
    required Color color,
    required VoidCallback onPressed,
  }) {
    return Container(
      width: double.infinity,
      height: 68,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(16),
        boxShadow: [
          BoxShadow(
            color: color.withOpacity(0.4),
            blurRadius: 20,
            offset: const Offset(0, 10),
            spreadRadius: -5,
          ),
        ],
      ),
      child: ElevatedButton(
        style: ElevatedButton.styleFrom(
          backgroundColor: color,
          foregroundColor: Colors.white,
          elevation: 0,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(16),
          ),
          padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 16),
        ),
        onPressed: onPressed,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(icon, size: 28),
            const SizedBox(width: 12),
            Flexible(
              child: Text(
                label,
                style: const TextStyle(
                  fontSize: 20,
                  fontWeight: FontWeight.bold,
                  letterSpacing: 2,
                ),
                textAlign: TextAlign.center,
                maxLines: 1,
                overflow: TextOverflow.ellipsis,
              ),
            ),
          ],
        ),
      ),
    );
  }

  void _showInstructions(BuildContext context) {
    showDialog(
      context: context,
      builder: (context) => Dialog(
        backgroundColor: Colors.transparent,
        child: ConstrainedBox(
          constraints: BoxConstraints(
            maxHeight: MediaQuery.of(context).size.height * 0.85,
          ),
          child: Container(
            padding: const EdgeInsets.all(28),
            decoration: BoxDecoration(
              gradient: LinearGradient(
                colors: [Colors.grey.shade900, Colors.grey.shade800],
              ),
              borderRadius: BorderRadius.circular(24),
              border: Border.all(color: Colors.white.withOpacity(0.2)),
            ),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  children: [
                    Container(
                      padding: const EdgeInsets.all(12),
                      decoration: BoxDecoration(
                        color: Colors.blue.withOpacity(0.2),
                        borderRadius: BorderRadius.circular(12),
                      ),
                      child: const Icon(Icons.info_outline, color: Colors.blue, size: 32),
                    ),
                    const SizedBox(width: 16),
                    const Flexible(
                      child: Text(
                        '游戏说明',
                        style: TextStyle(
                          fontSize: 28,
                          fontWeight: FontWeight.bold,
                          color: Colors.white,
                        ),
                        maxLines: 1,
                        overflow: TextOverflow.ellipsis,
                      ),
                    ),
                    const Spacer(),
                    IconButton(
                      onPressed: () => Navigator.pop(context),
                      icon: const Icon(Icons.close, color: Colors.white),
                    ),
                  ],
                ),
                const Divider(height: 32, color: Colors.white24),
                Expanded(
                  child: SingleChildScrollView(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        _buildInstructionItem(
                          icon: Icons.local_fire_department,
                          iconColor: Colors.orange,
                          title: '火焰人操作',
                          items: ['A/D 或 ←/→: 左右移动', 'W 或 ↑: 跳跃'],
                        ),
                        const SizedBox(height: 20),
                        _buildInstructionItem(
                          icon: Icons.ac_unit,
                          iconColor: Colors.blue,
                          title: '冰人操作',
                          items: ['J/L: 左右移动', 'I: 跳跃'],
                        ),
                        const SizedBox(height: 20),
                        _buildInstructionItem(
                          icon: Icons.flag,
                          iconColor: Colors.yellow,
                          title: '游戏目标',
                          items: [
                            '火焰人到达红色门',
                            '冰人到达蓝色门',
                            '两人必须同时到达才能过关',
                          ],
                        ),
                        const SizedBox(height: 20),
                        _buildInstructionItem(
                          icon: Icons.warning,
                          iconColor: Colors.red,
                          title: '注意事项',
                          items: [
                            '火焰人碰到水会死亡',
                            '冰人碰到岩浆会死亡',
                            '收集宝石可提高评分',
                          ],
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildInstructionItem({
    required IconData icon,
    required Color iconColor,
    required String title,
    required List<String> items,
  }) {
    return Container(
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        color: Colors.white.withOpacity(0.1),
        borderRadius: BorderRadius.circular(16),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              Container(
                padding: const EdgeInsets.all(8),
                decoration: BoxDecoration(
                  color: iconColor.withOpacity(0.2),
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Icon(icon, color: iconColor, size: 24),
              ),
              const SizedBox(width: 12),
              Expanded(
                child: Text(
                  title,
                  style: const TextStyle(
                    fontSize: 18,
                    fontWeight: FontWeight.bold,
                    color: Colors.white,
                  ),
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                ),
              ),
            ],
          ),
          const SizedBox(height: 16),
          ...items.map((item) => Padding(
                padding: const EdgeInsets.only(left: 16, bottom: 8),
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Container(
                      margin: const EdgeInsets.only(top: 6),
                      width: 6,
                      height: 6,
                      decoration: BoxDecoration(
                        color: Colors.white.withOpacity(0.6),
                        shape: BoxShape.circle,
                      ),
                    ),
                    const SizedBox(width: 12),
                    Expanded(
                      child: Text(
                        item,
                        style: const TextStyle(
                          fontSize: 14,
                          color: Colors.white70,
                          height: 1.6,
                        ),
                        maxLines: 3,
                        overflow: TextOverflow.ellipsis,
                      ),
                    ),
                  ],
                ),
              )),
        ],
      ),
    );
  }

  void _showSettings(BuildContext context) {
    showDialog(
      context: context,
      builder: (context) => Dialog(
        backgroundColor: Colors.transparent,
        child: ConstrainedBox(
          constraints: BoxConstraints(
            maxHeight: MediaQuery.of(context).size.height * 0.7,
          ),
          child: Container(
            padding: const EdgeInsets.all(28),
            decoration: BoxDecoration(
              gradient: LinearGradient(
                colors: [Colors.grey.shade900, Colors.grey.shade800],
              ),
              borderRadius: BorderRadius.circular(24),
            ),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Row(
                  children: [
                    Container(
                      padding: const EdgeInsets.all(12),
                      decoration: BoxDecoration(
                        color: Colors.grey.withOpacity(0.2),
                        borderRadius: BorderRadius.circular(12),
                      ),
                      child: const Icon(Icons.settings, color: Colors.grey, size: 32),
                    ),
                    const SizedBox(width: 16),
                    const Flexible(
                      child: Text(
                        '设置',
                        style: TextStyle(
                          fontSize: 28,
                          fontWeight: FontWeight.bold,
                          color: Colors.white,
                        ),
                        maxLines: 1,
                        overflow: TextOverflow.ellipsis,
                      ),
                    ),
                    const Spacer(),
                    IconButton(
                      onPressed: () => Navigator.pop(context),
                      icon: const Icon(Icons.close, color: Colors.white),
                    ),
                  ],
                ),
                const Divider(height: 32, color: Colors.white24),
                Expanded(
                  child: SingleChildScrollView(
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        _buildSettingItem(
                          icon: Icons.volume_up,
                          title: '音效',
                          subtitle: '开启/关闭游戏音效',
                          value: true,
                        ),
                        const SizedBox(height: 16),
                        _buildSettingItem(
                          icon: Icons.music_note,
                          title: '背景音乐',
                          subtitle: '开启/关闭背景音乐',
                          value: true,
                        ),
                        const SizedBox(height: 16),
                        _buildSettingItem(
                          icon: Icons.vibration,
                          title: '震动反馈',
                          subtitle: '开启/关闭震动反馈',
                          value: false,
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildSettingItem({
    required IconData icon,
    required String title,
    required String subtitle,
    required bool value,
  }) {
    return Container(
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        color: Colors.white.withOpacity(0.1),
        borderRadius: BorderRadius.circular(16),
      ),
      child: Row(
        children: [
          Container(
            padding: const EdgeInsets.all(12),
            decoration: BoxDecoration(
              color: Colors.white.withOpacity(0.1),
              borderRadius: BorderRadius.circular(12),
            ),
            child: Icon(icon, color: Colors.white70, size: 28),
          ),
          const SizedBox(width: 16),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  title,
                  style: const TextStyle(
                    fontSize: 16,
                    fontWeight: FontWeight.bold,
                    color: Colors.white,
                  ),
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                ),
                const SizedBox(height: 4),
                Text(
                  subtitle,
                  style: TextStyle(
                    fontSize: 12,
                    color: Colors.white.withOpacity(0.6),
                  ),
                  maxLines: 2,
                  overflow: TextOverflow.ellipsis,
                ),
              ],
            ),
          ),
          Switch(
            value: value,
            onChanged: (val) {},
            activeColor: Colors.green,
          ),
        ],
      ),
    );
  }

  void _showAbout(BuildContext context) {
    showDialog(
      context: context,
      builder: (context) => Dialog(
        backgroundColor: Colors.transparent,
        child: ConstrainedBox(
          constraints: BoxConstraints(
            maxHeight: MediaQuery.of(context).size.height * 0.6,
          ),
          child: Container(
            padding: const EdgeInsets.all(28),
            decoration: BoxDecoration(
              gradient: LinearGradient(
                colors: [Colors.grey.shade900, Colors.grey.shade800],
              ),
              borderRadius: BorderRadius.circular(24),
            ),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Row(
                  children: [
                    Container(
                      padding: const EdgeInsets.all(12),
                      decoration: BoxDecoration(
                        color: Colors.purple.withOpacity(0.2),
                        borderRadius: BorderRadius.circular(12),
                      ),
                      child: const Icon(Icons.info_outline, color: Colors.purple, size: 32),
                    ),
                    const SizedBox(width: 16),
                    const Flexible(
                      child: Text(
                        '关于',
                        style: TextStyle(
                          fontSize: 28,
                          fontWeight: FontWeight.bold,
                          color: Colors.white,
                        ),
                        maxLines: 1,
                        overflow: TextOverflow.ellipsis,
                      ),
                    ),
                    const Spacer(),
                    IconButton(
                      onPressed: () => Navigator.pop(context),
                      icon: const Icon(Icons.close, color: Colors.white),
                    ),
                  ],
                ),
                const Divider(height: 32, color: Colors.white24),
                Expanded(
                  child: SingleChildScrollView(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Container(
                          padding: const EdgeInsets.all(24),
                          decoration: BoxDecoration(
                            gradient: const LinearGradient(
                              colors: [Colors.orange, Colors.blue],
                            ),
                            shape: BoxShape.circle,
                          ),
                          child: const Icon(
                            Icons.extension,
                            size: 80,
                            color: Colors.white,
                          ),
                        ),
                        const SizedBox(height: 24),
                        const Text(
                          '冰火人闯关',
                          style: TextStyle(
                            fontSize: 28,
                            fontWeight: FontWeight.bold,
                            color: Colors.white,
                          ),
                        ),
                        const SizedBox(height: 12),
                        const Text(
                          'Fireboy & Watergirl Adventure',
                          style: TextStyle(
                            fontSize: 16,
                            color: Colors.white70,
                          ),
                        ),
                        const SizedBox(height: 24),
                        const Text(
                          '一款经典的双人协作闯关游戏,\n控制火焰人和冰人配合,\n完成各种挑战!',
                          textAlign: TextAlign.center,
                          style: TextStyle(
                            fontSize: 14,
                            color: Colors.white70,
                            height: 1.6,
                          ),
                        ),
                        const SizedBox(height: 32),
                        const Text(
                          'Version 1.0.0',
                          style: TextStyle(
                            fontSize: 14,
                            // ignore: deprecated_member_use
                            color: Colors.white54,
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

// 背景粒子绘制器
class ParticlePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()..color = Colors.white.withOpacity(0.08);

    for (int i = 0; i < 80; i++) {
      final x = (i * 97) % size.width;
      final y = (i * 53) % size.height;
      final radius = (i % 4) + 1.0;

      canvas.drawCircle(
        Offset(x.toDouble(), y.toDouble()),
        radius,
        paint,
      );
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

class LevelSelectScreen extends StatelessWidget {
  const LevelSelectScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('选择关卡'),
        centerTitle: true,
      ),
      body: GridView.builder(
        padding: const EdgeInsets.all(16),
        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 3,
          childAspectRatio: 1,
          crossAxisSpacing: 16,
          mainAxisSpacing: 16,
        ),
        itemCount: 9,
        itemBuilder: (context, index) {
          int level = index + 1;
          return GestureDetector(
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => GameScreen(level: level),
                ),
              );
            },
            child: Container(
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  begin: Alignment.topLeft,
                  end: Alignment.bottomRight,
                  colors: [Colors.red, Colors.blue],
                ),
                borderRadius: BorderRadius.circular(16),
                boxShadow: [
                  BoxShadow(
                    color: Colors.black.withOpacity(0.3),
                    blurRadius: 8,
                    offset: const Offset(0, 4),
                  ),
                ],
              ),
              child: Center(
                child: Text(
                  '$level',
                  style: const TextStyle(
                    fontSize: 48,
                    fontWeight: FontWeight.bold,
                    color: Colors.white,
                  ),
                ),
              ),
            ),
          );
        },
      ),
    );
  }
}

class GameScreen extends StatefulWidget {
  final int level;

  const GameScreen({super.key, required this.level});

  @override
  State<GameScreen> createState() => _GameState();
}

class _GameState extends State<GameScreen> {
  late Timer _gameTimer;
  bool _isPaused = false;
  bool _gameOver = false;
  bool _gameWin = false;
  String _deathReason = '';

  // 游戏状态
  Offset _fireboyPosition = const Offset(50, 300);
  Offset _watergirlPosition = const Offset(250, 300);
  Size _playerSize = const Size(30, 40);
  double _fireboyVelocityX = 0;
  double _fireboyVelocityY = 0;
  double _watergirlVelocityX = 0;
  double _watergirlVelocityY = 0;
  bool _fireboyOnGround = false;
  bool _watergirlOnGround = false;

  // 关卡元素
  List<Platform> _platforms = [];
  List<LavaPool> _lavaPools = [];
  List<WaterPool> _waterPools = [];
  List<Gem> _gems = [];

  // 门的位置
  late Offset _redDoorPosition;
  late Offset _blueDoorPosition;
  bool _fireboyAtDoor = false;
  bool _watergirlAtDoor = false;

  // 收集统计
  int _fireboyGems = 0;
  int _watergirlGems = 0;
  int _totalFireboyGems = 0;
  int _totalWatergirlGems = 0;

  // 按键状态
  bool _leftPressed = false;
  bool _rightPressed = false;
  bool _fireboyJumpPressed = false;
  bool _watergirlLeftPressed = false;
  bool _watergirlRightPressed = false;
  bool _watergirlJumpPressed = false;

  // 移动端虚拟按键
  bool _showControls = true;

  @override
  void initState() {
    super.initState();
    _loadLevel();
    _startGame();
  }

  void _loadLevel() {
    // 根据关卡号加载不同的关卡设计
    switch (widget.level) {
      case 1:
        _loadLevel1();
        break;
      case 2:
        _loadLevel2();
        break;
      case 3:
        _loadLevel3();
        break;
      default:
        _loadLevel1();
    }
  }

  void _loadLevel1() {
    _fireboyPosition = const Offset(50, 400);
    _watergirlPosition = const Offset(100, 400);

    // 平台
    _platforms = [
      const Platform(x: 0, y: 480, width: 400, height: 20), // 地面
      const Platform(x: 0, y: 350, width: 150, height: 20),
      const Platform(x: 200, y: 350, width: 200, height: 20),
      const Platform(x: 0, y: 220, width: 120, height: 20),
      const Platform(x: 180, y: 220, width: 220, height: 20),
      const Platform(x: 300, y: 100, width: 100, height: 20),
    ];

    // 岩浆和水池
    _lavaPools = [
      const LavaPool(x: 150, y: 460, width: 50, height: 20),
    ];

    _waterPools = [
      const WaterPool(x: 250, y: 460, width: 50, height: 20),
    ];

    // 宝石
    _gems = [
      const Gem(x: 75, y: 300, color: Colors.red),
      const Gem(x: 300, y: 300, color: Colors.blue),
      const Gem(x: 60, y: 170, color: Colors.red),
      const Gem(x: 300, y: 170, color: Colors.blue),
    ];

    _totalFireboyGems = 2;
    _totalWatergirlGems = 2;

    // 门
    _redDoorPosition = const Offset(320, 50);
    _blueDoorPosition = const Offset(250, 50);
  }

  void _loadLevel2() {
    _fireboyPosition = const Offset(30, 400);
    _watergirlPosition = const Offset(80, 400);

    _platforms = [
      const Platform(x: 0, y: 480, width: 400, height: 20),
      const Platform(x: 0, y: 380, width: 100, height: 20),
      const Platform(x: 150, y: 380, width: 100, height: 20),
      const Platform(x: 300, y: 380, width: 100, height: 20),
      const Platform(x: 50, y: 280, width: 100, height: 20),
      const Platform(x: 250, y: 280, width: 100, height: 20),
      const Platform(x: 150, y: 180, width: 100, height: 20),
      const Platform(x: 50, y: 100, width: 80, height: 20),
      const Platform(x: 270, y: 100, width: 80, height: 20),
    ];

    _lavaPools = [
      const LavaPool(x: 100, y: 460, width: 50, height: 20),
      const LavaPool(x: 250, y: 460, width: 50, height: 20),
    ];

    _waterPools = [
      const WaterPool(x: 200, y: 340, width: 50, height: 20),
    ];

    _gems = [
      const Gem(x: 50, y: 340, color: Colors.red),
      const Gem(x: 350, y: 340, color: Colors.blue),
      const Gem(x: 100, y: 240, color: Colors.red),
      const Gem(x: 300, y: 240, color: Colors.blue),
      const Gem(x: 200, y: 140, color: Colors.green),
    ];

    _totalFireboyGems = 3;
    _totalWatergirlGems = 2;

    _redDoorPosition = const Offset(60, 50);
    _blueDoorPosition = const Offset(290, 50);
  }

  void _loadLevel3() {
    _fireboyPosition = const Offset(30, 400);
    _watergirlPosition = const Offset(70, 400);

    _platforms = [
      const Platform(x: 0, y: 480, width: 400, height: 20),
      const Platform(x: 0, y: 380, width: 80, height: 20),
      const Platform(x: 120, y: 350, width: 80, height: 20),
      const Platform(x: 240, y: 320, width: 80, height: 20),
      const Platform(x: 320, y: 380, width: 80, height: 20),
      const Platform(x: 50, y: 260, width: 80, height: 20),
      const Platform(x: 170, y: 230, width: 80, height: 20),
      const Platform(x: 290, y: 260, width: 80, height: 20),
      const Platform(x: 120, y: 160, width: 80, height: 20),
      const Platform(x: 200, y: 100, width: 100, height: 20),
    ];

    _lavaPools = [
      const LavaPool(x: 80, y: 460, width: 60, height: 20),
      const LavaPool(x: 200, y: 460, width: 60, height: 20),
      const LavaPool(x: 300, y: 340, width: 50, height: 20),
    ];

    _waterPools = [
      const WaterPool(x: 280, y: 460, width: 70, height: 20),
      const WaterPool(x: 100, y: 220, width: 50, height: 20),
    ];

    _gems = [
      const Gem(x: 40, y: 340, color: Colors.red),
      const Gem(x: 160, y: 310, color: Colors.red),
      const Gem(x: 280, y: 280, color: Colors.blue),
      const Gem(x: 90, y: 220, color: Colors.red),
      const Gem(x: 210, y: 190, color: Colors.blue),
      const Gem(x: 330, y: 220, color: Colors.blue),
      const Gem(x: 160, y: 120, color: Colors.green),
      const Gem(x: 250, y: 60, color: Colors.green),
    ];

    _totalFireboyGems = 4;
    _totalWatergirlGems = 3;

    _redDoorPosition = const Offset(210, 50);
    _blueDoorPosition = const Offset(260, 50);
  }

  void _startGame() {
    _gameTimer = Timer.periodic(const Duration(milliseconds: 16), (timer) {
      if (!_isPaused && !_gameOver && !_gameWin) {
        _updateGame();
      }
    });
  }

  void _updateGame() {
    // 火焰人移动
    if (_leftPressed) {
      _fireboyVelocityX = -4;
    } else if (_rightPressed) {
      _fireboyVelocityX = 4;
    } else {
      _fireboyVelocityX = 0;
    }

    if (_fireboyJumpPressed && _fireboyOnGround) {
      _fireboyVelocityY = -12;
      _fireboyOnGround = false;
    }

    // 冰人移动
    if (_watergirlLeftPressed) {
      _watergirlVelocityX = -4;
    } else if (_watergirlRightPressed) {
      _watergirlVelocityX = 4;
    } else {
      _watergirlVelocityX = 0;
    }

    if (_watergirlJumpPressed && _watergirlOnGround) {
      _watergirlVelocityY = -12;
      _watergirlOnGround = false;
    }

    // 应用重力
    _fireboyVelocityY += 0.5;
    _watergirlVelocityY += 0.5;

    // 更新位置
    _fireboyPosition += Offset(_fireboyVelocityX, _fireboyVelocityY);
    _watergirlPosition += Offset(_watergirlVelocityX, _watergirlVelocityY);

    // 边界检测
    _fireboyPosition = Offset(
      _fireboyPosition.dx.clamp(0, 370),
      _fireboyPosition.dy.clamp(0, 440),
    );
    _watergirlPosition = Offset(
      _watergirlPosition.dx.clamp(0, 370),
      _watergirlPosition.dy.clamp(0, 440),
    );

    // 平台碰撞检测
    _fireboyOnGround = false;
    _watergirlOnGround = false;

    for (var platform in _platforms) {
      _checkPlatformCollision(_fireboyPosition, platform, true);
      _checkPlatformCollision(_watergirlPosition, platform, false);
    }

    // 危险区域检测
    _checkDangerZones();

    // 宝石收集
    _collectGems();

    // 检查是否到达门口
    _checkDoorCollision();

    setState(() {});
  }

  void _checkPlatformCollision(Offset position, Platform platform, bool isFireboy) {
    Rect playerRect = Rect.fromLTWH(
      position.dx,
      position.dy,
      _playerSize.width,
      _playerSize.height,
    );

    Rect platformRect = Rect.fromLTWH(
      platform.x.toDouble(),
      platform.y.toDouble(),
      platform.width.toDouble(),
      platform.height.toDouble(),
    );

    if (playerRect.overlaps(platformRect)) {
      // 从上方落下
      if ((isFireboy ? _fireboyVelocityY : _watergirlVelocityY) > 0 &&
          position.dy + _playerSize.height <= platformRect.top + 10) {
        position = Offset(
          position.dx,
          platformRect.top - _playerSize.height,
        );
        if (isFireboy) {
          _fireboyPosition = position;
          _fireboyOnGround = true;
          _fireboyVelocityY = 0;
        } else {
          _watergirlPosition = position;
          _watergirlOnGround = true;
          _watergirlVelocityY = 0;
        }
      }
      // 从下方碰撞
      else if ((isFireboy ? _fireboyVelocityY : _watergirlVelocityY) < 0 &&
          position.dy >= platformRect.bottom - 10) {
        position = Offset(position.dx, platformRect.bottom);
        if (isFireboy) {
          _fireboyPosition = position;
          _fireboyVelocityY = 0;
        } else {
          _watergirlPosition = position;
          _watergirlVelocityY = 0;
        }
      }
    }
  }

  void _checkDangerZones() {
    Rect fireboyRect = Rect.fromLTWH(
      _fireboyPosition.dx,
      _fireboyPosition.dy,
      _playerSize.width,
      _playerSize.height,
    );

    Rect watergirlRect = Rect.fromLTWH(
      _watergirlPosition.dx,
      _watergirlPosition.dy,
      _playerSize.width,
      _playerSize.height,
    );

    // 检查岩浆 - 火焰人安全,冰人危险
    for (var lava in _lavaPools) {
      Rect lavaRect = Rect.fromLTWH(
        lava.x.toDouble(),
        lava.y.toDouble(),
        lava.width.toDouble(),
        lava.height.toDouble(),
      );

      if (watergirlRect.overlaps(lavaRect)) {
        _gameOver = true;
        _deathReason = '冰人掉进了岩浆!';
        return;
      }
    }

    // 检查水池 - 冰人安全,火焰人危险
    for (var water in _waterPools) {
      Rect waterRect = Rect.fromLTWH(
        water.x.toDouble(),
        water.y.toDouble(),
        water.width.toDouble(),
        water.height.toDouble(),
      );

      if (fireboyRect.overlaps(waterRect)) {
        _gameOver = true;
        _deathReason = '火焰人掉进了水池!';
        return;
      }
    }
  }

  void _collectGems() {
    Rect fireboyRect = Rect.fromLTWH(
      _fireboyPosition.dx + 5,
      _fireboyPosition.dy + 5,
      _playerSize.width - 10,
      _playerSize.height - 10,
    );

    Rect watergirlRect = Rect.fromLTWH(
      _watergirlPosition.dx + 5,
      _watergirlPosition.dy + 5,
      _playerSize.width - 10,
      _playerSize.height - 10,
    );

    for (int i = _gems.length - 1; i >= 0; i--) {
      Gem gem = _gems[i];
      Rect gemRect = Rect.fromLTWH(gem.x.toDouble(), gem.y.toDouble(), 20, 20);

      if (fireboyRect.overlaps(gemRect) && gem.color == Colors.red) {
        _fireboyGems++;
        _gems.removeAt(i);
      } else if (watergirlRect.overlaps(gemRect) && gem.color == Colors.blue) {
        _watergirlGems++;
        _gems.removeAt(i);
      } else if ((fireboyRect.overlaps(gemRect) || watergirlRect.overlaps(gemRect)) && gem.color == Colors.green) {
        _fireboyGems++;
        _watergirlGems++;
        _gems.removeAt(i);
      }
    }
  }

  void _checkDoorCollision() {
    Rect fireboyRect = Rect.fromLTWH(
      _fireboyPosition.dx,
      _fireboyPosition.dy,
      _playerSize.width,
      _playerSize.height,
    );

    Rect watergirlRect = Rect.fromLTWH(
      _watergirlPosition.dx,
      _watergirlPosition.dy,
      _playerSize.width,
      _playerSize.height,
    );

    Rect redDoorRect = Rect.fromLTWH(_redDoorPosition.dx, _redDoorPosition.dy, 40, 60);
    Rect blueDoorRect = Rect.fromLTWH(_blueDoorPosition.dx, _blueDoorPosition.dy, 40, 60);

    _fireboyAtDoor = fireboyRect.overlaps(redDoorRect);
    _watergirlAtDoor = watergirlRect.overlaps(blueDoorRect);

    if (_fireboyAtDoor && _watergirlAtDoor) {
      _gameWin = true;
      _gameTimer.cancel();
    }
  }

  @override
  void dispose() {
    _gameTimer.cancel();
    super.dispose();
  }

  void _restartLevel() {
    setState(() {
      _gameOver = false;
      _gameWin = false;
      _deathReason = '';
      _fireboyGems = 0;
      _watergirlGems = 0;
      _gems.clear();
      _loadLevel();
    });
  }

  void _nextLevel() {
    if (widget.level < 9) {
      Navigator.pushReplacement(
        context,
        MaterialPageRoute(
          builder: (context) => GameScreen(level: widget.level + 1),
        ),
      );
    } else {
      Navigator.pop(context);
      showDialog(
        context: context,
        builder: (context) => AlertDialog(
          title: const Text('恭喜通关!'),
          content: const Text('你已完成所有关卡!'),
          actions: [
            TextButton(
              onPressed: () {
                Navigator.pop(context);
                Navigator.pop(context);
              },
              child: const Text('返回'),
            ),
          ],
        ),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey[900],
      body: Column(
        children: [
          // 顶部状态栏
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
            color: Colors.black87,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Row(
                  children: [
                    IconButton(
                      icon: const Icon(Icons.arrow_back),
                      onPressed: () {
                        _gameTimer.cancel();
                        Navigator.pop(context);
                      },
                    ),
                    Text(
                      '关卡 ${widget.level}',
                      style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                    ),
                  ],
                ),
                Row(
                  children: [
                    const Icon(Icons.diamond, color: Colors.red, size: 20),
                    Text(' $_fireboyGems/$_totalFireboyGems'),
                    const SizedBox(width: 16),
                    const Icon(Icons.diamond, color: Colors.blue, size: 20),
                    Text(' $_watergirlGems/$_totalWatergirlGems'),
                  ],
                ),
                IconButton(
                  icon: Icon(_isPaused ? Icons.play_arrow : Icons.pause),
                  onPressed: () {
                    setState(() {
                      _isPaused = !_isPaused;
                    });
                  },
                ),
              ],
            ),
          ),
          // 游戏区域
          Expanded(
            child: GestureDetector(
              onTap: () {
                setState(() {
                  _showControls = !_showControls;
                });
              },
              child: Container(
                color: Colors.grey[800],
                child: Stack(
                  children: [
                    // 平台
                    ..._platforms.map((platform) => Positioned(
                          left: platform.x.toDouble(),
                          top: platform.y.toDouble(),
                          child: Container(
                            width: platform.width.toDouble(),
                            height: platform.height.toDouble(),
                            decoration: BoxDecoration(
                              color: Colors.brown[700],
                              borderRadius: BorderRadius.circular(4),
                              border: Border.all(color: Colors.brown[900]!, width: 2),
                            ),
                          ),
                        )),
                    // 岩浆
                    ..._lavaPools.map((lava) => Positioned(
                          left: lava.x.toDouble(),
                          top: lava.y.toDouble(),
                          child: Container(
                            width: lava.width.toDouble(),
                            height: lava.height.toDouble(),
                            decoration: BoxDecoration(
                              gradient: LinearGradient(
                                colors: [Colors.red, Colors.orange, Colors.yellow],
                              ),
                              borderRadius: BorderRadius.circular(8),
                            ),
                          ),
                        )),
                    // 水池
                    ..._waterPools.map((water) => Positioned(
                          left: water.x.toDouble(),
                          top: water.y.toDouble(),
                          child: Container(
                            width: water.width.toDouble(),
                            height: water.height.toDouble(),
                            decoration: BoxDecoration(
                              gradient: LinearGradient(
                                colors: [Colors.blue.shade300, Colors.blue, Colors.blue.shade900],
                              ),
                              borderRadius: BorderRadius.circular(8),
                            ),
                          ),
                        )),
                    // 宝石
                    ..._gems.map((gem) => Positioned(
                          left: gem.x.toDouble(),
                          top: gem.y.toDouble(),
                          child: Container(
                            width: 20,
                            height: 20,
                            decoration: BoxDecoration(
                              color: gem.color,
                              shape: BoxShape.circle,
                              boxShadow: [
                                BoxShadow(
                                  color: gem.color.withOpacity(0.6),
                                  blurRadius: 10,
                                  spreadRadius: 2,
                                ),
                              ],
                            ),
                          ),
                        )),
                    // 门
                    Positioned(
                      left: _redDoorPosition.dx,
                      top: _redDoorPosition.dy,
                      child: Container(
                        width: 40,
                        height: 60,
                        decoration: BoxDecoration(
                          gradient: LinearGradient(
                            colors: [Colors.red.shade400, Colors.red.shade900],
                          ),
                          borderRadius: BorderRadius.circular(4),
                          border: Border.all(color: Colors.yellow, width: 2),
                        ),
                        child: const Icon(Icons.exit_to_app, color: Colors.yellow),
                      ),
                    ),
                    Positioned(
                      left: _blueDoorPosition.dx,
                      top: _blueDoorPosition.dy,
                      child: Container(
                        width: 40,
                        height: 60,
                        decoration: BoxDecoration(
                          gradient: LinearGradient(
                            colors: [Colors.blue.shade400, Colors.blue.shade900],
                          ),
                          borderRadius: BorderRadius.circular(4),
                          border: Border.all(color: Colors.yellow, width: 2),
                        ),
                        child: const Icon(Icons.exit_to_app, color: Colors.yellow),
                      ),
                    ),
                    // 火焰人
                    Positioned(
                      left: _fireboyPosition.dx,
                      top: _fireboyPosition.dy,
                      child: Container(
                        width: _playerSize.width,
                        height: _playerSize.height,
                        decoration: BoxDecoration(
                          gradient: LinearGradient(
                            colors: [Colors.orange, Colors.red],
                          ),
                          borderRadius: BorderRadius.circular(8),
                          boxShadow: [
                            BoxShadow(
                              color: Colors.orange.withOpacity(0.6),
                              blurRadius: 10,
                              spreadRadius: 2,
                            ),
                          ],
                        ),
                        child: const Icon(Icons.local_fire_department, color: Colors.white),
                      ),
                    ),
                    // 冰人
                    Positioned(
                      left: _watergirlPosition.dx,
                      top: _watergirlPosition.dy,
                      child: Container(
                        width: _playerSize.width,
                        height: _playerSize.height,
                        decoration: BoxDecoration(
                          gradient: LinearGradient(
                            colors: [Colors.lightBlue, Colors.blue],
                          ),
                          borderRadius: BorderRadius.circular(8),
                          boxShadow: [
                            BoxShadow(
                              color: Colors.blue.withOpacity(0.6),
                              blurRadius: 10,
                              spreadRadius: 2,
                            ),
                          ],
                        ),
                        child: const Icon(Icons.ac_unit, color: Colors.white),
                      ),
                    ),
                    // 暂停覆盖层
                    if (_isPaused)
                      Container(
                        color: Colors.black.withOpacity(0.7),
                        child: const Center(
                          child: Column(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              Icon(Icons.pause, size: 80, color: Colors.white),
                              SizedBox(height: 16),
                              Text('暂停', style: TextStyle(fontSize: 32, color: Colors.white)),
                            ],
                          ),
                        ),
                      ),
                    // 游戏结束覆盖层
                    if (_gameOver)
                      Container(
                        color: Colors.black.withOpacity(0.8),
                        child: Center(
                          child: Column(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              const Icon(Icons.close, size: 80, color: Colors.red),
                              const SizedBox(height: 16),
                              const Text('游戏结束', style: TextStyle(fontSize: 32, color: Colors.white)),
                              const SizedBox(height: 16),
                              Text(_deathReason, style: const TextStyle(fontSize: 18, color: Colors.white)),
                              const SizedBox(height: 32),
                              ElevatedButton(
                                onPressed: _restartLevel,
                                child: const Text('重新开始'),
                              ),
                            ],
                          ),
                        ),
                      ),
                    // 胜利覆盖层
                    if (_gameWin)
                      Container(
                        color: Colors.black.withOpacity(0.8),
                        child: Center(
                          child: Column(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              const Icon(Icons.emoji_events, size: 80, color: Colors.yellow),
                              const SizedBox(height: 16),
                              const Text('过关!', style: TextStyle(fontSize: 32, color: Colors.white)),
                              const SizedBox(height: 16),
                              Text(
                                '收集宝石: 火焰人 $_fireboyGems/$_totalFireboyGems, 冰人 $_watergirlGems/$_totalWatergirlGems',
                                style: const TextStyle(fontSize: 16, color: Colors.white),
                              ),
                              const SizedBox(height: 32),
                              Row(
                                mainAxisAlignment: MainAxisAlignment.center,
                                children: [
                                  ElevatedButton(
                                    onPressed: _restartLevel,
                                    child: const Text('重新开始'),
                                  ),
                                  const SizedBox(width: 16),
                                  ElevatedButton(
                                    onPressed: _nextLevel,
                                    child: const Text('下一关'),
                                  ),
                                ],
                              ),
                            ],
                          ),
                        ),
                      ),
                    // 虚拟控制
                    if (_showControls && !_gameOver && !_gameWin && !_isPaused)
                      Positioned(
                        bottom: 20,
                        left: 20,
                        right: 20,
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            // 冰人控制
                            Column(
                              children: [
                                GestureDetector(
                                  onTapDown: (_) => setState(() => _watergirlJumpPressed = true),
                                  onTapUp: (_) => setState(() => _watergirlJumpPressed = false),
                                  onTapCancel: () => setState(() => _watergirlJumpPressed = false),
                                  child: Container(
                                    width: 60,
                                    height: 60,
                                    decoration: BoxDecoration(
                                      color: Colors.blue.withOpacity(0.7),
                                      shape: BoxShape.circle,
                                      border: Border.all(color: Colors.white, width: 2),
                                    ),
                                    child: const Icon(Icons.arrow_upward, color: Colors.white),
                                  ),
                                ),
                                const SizedBox(height: 10),
                                Row(
                                  children: [
                                    GestureDetector(
                                      onTapDown: (_) => setState(() => _watergirlLeftPressed = true),
                                      onTapUp: (_) => setState(() => _watergirlLeftPressed = false),
                                      onTapCancel: () => setState(() => _watergirlLeftPressed = false),
                                      child: Container(
                                        width: 60,
                                        height: 60,
                                        decoration: BoxDecoration(
                                          color: Colors.blue.withOpacity(0.7),
                                          shape: BoxShape.circle,
                                          border: Border.all(color: Colors.white, width: 2),
                                        ),
                                        child: const Icon(Icons.arrow_back, color: Colors.white),
                                      ),
                                    ),
                                    const SizedBox(width: 10),
                                    GestureDetector(
                                      onTapDown: (_) => setState(() => _watergirlRightPressed = true),
                                      onTapUp: (_) => setState(() => _watergirlRightPressed = false),
                                      onTapCancel: () => setState(() => _watergirlRightPressed = false),
                                      child: Container(
                                        width: 60,
                                        height: 60,
                                        decoration: BoxDecoration(
                                          color: Colors.blue.withOpacity(0.7),
                                          shape: BoxShape.circle,
                                          border: Border.all(color: Colors.white, width: 2),
                                        ),
                                        child: const Icon(Icons.arrow_forward, color: Colors.white),
                                      ),
                                    ),
                                  ],
                                ),
                                const SizedBox(height: 8),
                                const Text('冰人', style: TextStyle(color: Colors.blue, fontWeight: FontWeight.bold)),
                              ],
                            ),
                            // 火焰人控制
                            Column(
                              children: [
                                GestureDetector(
                                  onTapDown: (_) => setState(() => _fireboyJumpPressed = true),
                                  onTapUp: (_) => setState(() => _fireboyJumpPressed = false),
                                  onTapCancel: () => setState(() => _fireboyJumpPressed = false),
                                  child: Container(
                                    width: 60,
                                    height: 60,
                                    decoration: BoxDecoration(
                                      color: Colors.orange.withOpacity(0.7),
                                      shape: BoxShape.circle,
                                      border: Border.all(color: Colors.white, width: 2),
                                    ),
                                    child: const Icon(Icons.arrow_upward, color: Colors.white),
                                  ),
                                ),
                                const SizedBox(height: 10),
                                Row(
                                  children: [
                                    GestureDetector(
                                      onTapDown: (_) => setState(() => _leftPressed = true),
                                      onTapUp: (_) => setState(() => _leftPressed = false),
                                      onTapCancel: () => setState(() => _leftPressed = false),
                                      child: Container(
                                        width: 60,
                                        height: 60,
                                        decoration: BoxDecoration(
                                          color: Colors.orange.withOpacity(0.7),
                                          shape: BoxShape.circle,
                                          border: Border.all(color: Colors.white, width: 2),
                                        ),
                                        child: const Icon(Icons.arrow_back, color: Colors.white),
                                      ),
                                    ),
                                    const SizedBox(width: 10),
                                    GestureDetector(
                                      onTapDown: (_) => setState(() => _rightPressed = true),
                                      onTapUp: (_) => setState(() => _rightPressed = false),
                                      onTapCancel: () => setState(() => _rightPressed = false),
                                      child: Container(
                                        width: 60,
                                        height: 60,
                                        decoration: BoxDecoration(
                                          color: Colors.orange.withOpacity(0.7),
                                          shape: BoxShape.circle,
                                          border: Border.all(color: Colors.white, width: 2),
                                        ),
                                        child: const Icon(Icons.arrow_forward, color: Colors.white),
                                      ),
                                    ),
                                  ],
                                ),
                                const SizedBox(height: 8),
                                const Text('火焰人', style: TextStyle(color: Colors.orange, fontWeight: FontWeight.bold)),
                              ],
                            ),
                          ],
                        ),
                      ),
                    // 隐藏控制提示
                    if (!_showControls)
                      Positioned(
                        top: 80,
                        left: 0,
                        right: 0,
                        child: Center(
                          child: Container(
                            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                            decoration: BoxDecoration(
                              color: Colors.black.withOpacity(0.6),
                              borderRadius: BorderRadius.circular(20),
                            ),
                            child: const Text('点击屏幕显示/隐藏控制', style: TextStyle(color: Colors.white)),
                          ),
                        ),
                      ),
                  ],
                ),
              ),
            ),
          ),
          // 键盘操作说明
          Container(
            padding: const EdgeInsets.all(12),
            color: Colors.black87,
            child: Wrap(
              alignment: WrapAlignment.center,
              spacing: 16,
              children: [
                Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    const Text('火焰人: ', style: TextStyle(color: Colors.orange)),
                    _buildKeyBadge('A'),
                    _buildKeyBadge('D'),
                    _buildKeyBadge('W'),
                  ],
                ),
                Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    const Text('冰人: ', style: TextStyle(color: Colors.blue)),
                    _buildKeyBadge('J'),
                    _buildKeyBadge('L'),
                    _buildKeyBadge('I'),
                  ],
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildKeyBadge(String key) {
    return Container(
      margin: const EdgeInsets.symmetric(horizontal: 2),
      padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
      decoration: BoxDecoration(
        color: Colors.grey[700],
        borderRadius: BorderRadius.circular(6),
        border: Border.all(color: Colors.grey[500]!),
      ),
      child: Text(key, style: const TextStyle(fontSize: 14)),
    );
  }
}

// 游戏元素类
class Platform {
  final int x;
  final int y;
  final int width;
  final int height;

  const Platform({
    required this.x,
    required this.y,
    required this.width,
    required this.height,
  });
}

class LavaPool {
  final int x;
  final int y;
  final int width;
  final int height;

  const LavaPool({
    required this.x,
    required this.y,
    required this.width,
    required this.height,
  });
}

class WaterPool {
  final int x;
  final int y;
  final int width;
  final int height;

  const WaterPool({
    required this.x,
    required this.y,
    required this.width,
    required this.height,
  });
}

class Gem {
  final double x;
  final double y;
  final Color color;

  const Gem({
    required this.x,
    required this.y,
    required this.color,
  });
}

class Lever {
  final double x;
  final double y;
  bool isActive;

  Lever({
    required this.x,
    required this.y,
    this.isActive = false,
  });
}

class Gate {
  final double x;
  final double y;
  bool isOpen;

  Gate({
    required this.x,
    required this.y,
    this.isOpen = false,
  });
}


Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐