iT邦幫忙

2023 iThome 鐵人賽

DAY 14
0
SideProject30

年輕人,想玩自己寫!系列 第 14

第十三章,試著找回信心

  • 分享至 

  • xImage
  •  

為了找回一點信心,救回專案,先試著做做看小遊戲吧。
參考Flame的官網,發現他在頁面的最底下有一些Tutorials。
我們可以照著這些說明試著將範例實作出來~

參照範例 Ember Quest Game Tutorial

(網址:https://docs.flame-engine.org/main/tutorials/platformer/platformer.html#ember-quest-game-tutorial)

  1. 第一步就是準備圖啦~下面這些都是源自官方文件的圖,直接右鍵另存進專案就可以使用了。
    https://docs.flame-engine.org/main/_images/block.pnghttps://docs.flame-engine.org/main/_images/ember.pnghttps://docs.flame-engine.org/main/_images/heart_half.pnghttps://docs.flame-engine.org/main/_images/heart.pnghttps://docs.flame-engine.org/main/_images/water_enemy.pnghttps://docs.flame-engine.org/main/_images/ground.png
  2. 然後放入Flutter專案裡。
    emberquest/
    ├─assets/
    │ └─images/
    │ ├─block.png
    │ ├─ember.png
    │ ├─heart_half.png
    | ├─ground.png
    │ ├─heart.png
    │ └─water_enemy.png
    ├─lib/
    │ └─main.dart
    └─pubspec.yaml
    在pubspec.yaml裡加:
flutter:
 assets:
   - assets/images/
  1. 然後在main.dart裡是這樣的:
void main() {
  runApp(
    const GameWidget<你的遊戲(FlameGame類)>.controlled(
      gameFactory: 你的遊戲(FlameGame類).new,

    ),
  );
}

要注意那個「controlled」很重要!不是這樣導入你的角色根本不會動!(之前有提過直接將FlameGame包個GameWidget的方式「GameWidget(game:FlameGame())」,在這裡會導致角色控制項失效。)
4. 然後在你的遊戲畫面裡,先將剛剛有的圖檔先全部載入。同時還有我們的遊戲視角。
5. 開始要創造我們的主角Ember了~

class EmberPlayer extends SpriteAnimationComponent ///精靈Component
    with HasGameRef<你的遊戲> {
  EmberPlayer({
    required super.position,
  }) : super(size: Vector2.all(64), anchor: Anchor.center);

  @override
  void onLoad() {
    animation = SpriteAnimation.fromFrameData(
      game.images.fromCache('ember.png'),
      SpriteAnimationData.sequenced(
        amount: 4,                        ///將圖切成4等份
        textureSize: Vector2.all(16),     ///每等份大小(也就是說,看你的精靈圖一格是多大)
        stepTime: 0.12,                   ///播放速度
      ),
    );
  }
}
  1. 當然我們會希望我們的角色可以移動,範例裡的,是用鍵盤移動
class EmberQuestGame extends FlameGame
    with HasCollisionDetection, HasKeyboardHandlerComponents {
    @override
  bool onKeyEvent(RawKeyEvent event, Set<LogicalKeyboardKey> keysPressed) {
    horizontalDirection = 0;
    horizontalDirection += (keysPressed.contains(LogicalKeyboardKey.keyA) ||
            keysPressed.contains(LogicalKeyboardKey.arrowLeft))
        ? -1
        : 0;
    horizontalDirection += (keysPressed.contains(LogicalKeyboardKey.keyD) ||
            keysPressed.contains(LogicalKeyboardKey.arrowRight))
        ? 1
        : 0;

    return true;
  }
  @override
  void update(double dt) {
    velocity.x = horizontalDirection * moveSpeed;
    game.objectSpeed = 0;
    // Prevent ember from going backwards at screen edge.
    if (position.x - 36 <= 0 && horizontalDirection < 0) {
      velocity.x = 0;
    }
    // Prevent ember from going beyond half screen.
    if (position.x + 64 >= game.size.x / 2 && horizontalDirection > 0) {
      velocity.x = 0;
      game.objectSpeed = -moveSpeed;
    }

    // Apply basic gravity.
    velocity.y += gravity;

    // Determine if ember has jumped.
    if (hasJumped) {
      if (isOnGround) {
        velocity.y = -jumpSpeed;
        isOnGround = false;
      }
      hasJumped = false;
    }

    // Prevent ember from jumping to crazy fast.
    velocity.y = velocity.y.clamp(-jumpSpeed, terminalVelocity);

    // Adjust ember position.
    position += velocity * dt;

    // Flip ember if needed.
    if (horizontalDirection < 0 && scale.x > 0) {
      flipHorizontally();
    } else if (horizontalDirection > 0 && scale.x < 0) {
      flipHorizontally();
    }
    super.update(dt);
  }

但我們將來比較可能會是手遊,所以我會想試著加搖捍(在遊戲那個class裡):

 final knobPaint = BasicPalette.blue.withAlpha(200).paint();
    final backgroundPaint = BasicPalette.blue.withAlpha(100).paint();
    joystick = JoystickComponent(
      knob: CircleComponent(radius: 25, paint: knobPaint),
      background: CircleComponent(radius: 60, paint: backgroundPaint),
      margin: const EdgeInsets.only(left: 40, bottom: 40),
    );
    
    @override
  void update(double dt) {
    super.update(dt);
    if (!joystick.delta.isZero()) {
      Vector2 ds = joystick.relativeDelta * _ember.moveSpeed * dt;
      _ember.move(ds);
    }
  }

在ember裡也要加入move的方法去接收joystick傳給他的vector。

  1. 範例裡還有提到怎麼讓場景循環
    https://docs.flame-engine.org/main/_images/LevelSegmentSketch.jpg
    像是這樣先規劃好,然後將他們分成一段一段的,建在一個類別裡管理。
    在角色移動的同時,也隨機選一段去填充,就能有無限的效果了。
    https://s21.aconvert.com/convert/p3r68-cdx67/vrq84-o83ey.gif

參考資料:
Flame官方文件
【Flutter&Flame 游戏 - 贰】操纵杆与角色移动


上一篇
第十二章,這鍋這麼大,該怎麼背才對?失火的專案有救嗎?
下一篇
第十四章,今天就跟上里程碑吧
系列文
年輕人,想玩自己寫!31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言