前言

在Flutter連續大版本的迭代下,發現2年前的項目bladeofgod/tank_combat (github.com)已經沒法跑了,為此進行了適配和代碼的重構。

相較於老項目,重構後的項目在代碼設計以及註釋上更為規範、合理及詳盡,藉此,希望初學者能有所收穫。此外,由於是學習類demo,所以未經過審慎思考,如有設計不合理或不嚴謹的地方,還望指正。

ps:玩家無敵  :D

Flame

本項目依賴於Flame,而Flame是一個基於flutter的遊戲引擎庫。

Flame 引擎的目的是為使用 Flutter 開發的遊戲會遇到的常見問題提供一套完整的解決方案。

目前 Flame 提供了以下功能:

  • 遊戲循環 (game loop)
  • 組件/對象系統 (FCS)
  • 特效與粒子效果
  • 碰撞檢測
  • 手勢和輸入支持
  • 圖片、動畫、精靈圖 (sprite) 以及精靈圖組
  • 一些簡化開發的實用工具類

Flame本身提供很多的組件,輔助管理Game Entity的生命週期、計算等。但是項目中並未完全使用,主要是希望能多一些自定義view(繪製)相關的代碼,以輔助初學者練習繪製。

TankCombat

在項目中,不僅可以瞭解到繪製相關的知識,還可以對Fluttermixin接口抽象類工廠構造函數extension等語言特性,以及一些簡單地設計模式有個初步的認識。

下面對各節點做一個簡單地介紹。

繪製

因為之前做過相關係列的介紹,這裏不做贅述,可以參考之前的文章以及代碼註釋。Flutter&Flame——TankCombat遊戲開發(一) - 掘金 (juejin.cn)

Mixin

在入口類TankGame中,我們可以看到混入複合混入的應用。

ps: 複合混入,我自己編的名字。 :D

faster whisper引擎下載_faster whisper引擎下載

複合混入:

faster whisper引擎下載_#swift_02

接口和繼承

tank_model.dart等文件中我們可以看到抽象類接口的簡單應用。

faster whisper引擎下載_#前端_03

設計模式

在混入類TankTheater中,通過跟蹤電腦tank的生成,我們可以瞭解到代理,工廠,Builder等設計模式的簡單應用。

faster whisper引擎下載_#前端_04

代理類ComputerTankSpawner的結構圖。

faster whisper引擎下載_faster whisper引擎下載_05

工廠構造函數和extension

工廠構造函數

為了方便標準化對象的創建,如:
坦克發射過程中,一輛坦克可以發射n枚炮彈,所以我們需要創建位置相對獨立但與坦克相關的拷貝對象

///抽象類
abstract class BaseBullet extends WindowComponent{

  ///...其他構造函數

  ///抽象
  BaseBullet copyWith({
    int? tankId,
    Size? activeSize,
    Offset? position,
    double? angle,
    BulletStatus status = BulletStatus.none,
  });
  
  ///.....其它代碼
 }
 
 
 ///實現類之一
 /// * 玩家炮彈
class PlayerBullet extends BaseBullet{

  PlayerBullet({required int tankId, required Size activeSize})
      : super(tankId: tankId, activeSize: activeSize);

  ///...其他代碼

  @override
  PlayerBullet copyWith({int? tankId, Size? activeSize, Offset? position, double? angle, BulletStatus status = BulletStatus.none}) {
    final PlayerBullet pb = PlayerBullet(tankId: tankId ?? this.tankId, activeSize: activeSize ?? this.activeSize);
    pb.position = position ?? Offset.zero;
    pb.angle = angle ?? 0;
    pb.status = status;
    return pb;
  }

}

extension

通過對List使用extension,可以簡化對List<componenet>的遍歷調用:

extension GameExtension<T extends WindowComponent> on List<T>{

  void onGameResize(Vector2 canvasSize) {
    forEach((element) => element.onGameResize(canvasSize));
  }

  void render(Canvas canvas) {
    forEach((element) => element.render(canvas));
  }

  void update(double dt) {
    forEach((element) => element.update(dt));
  }


}

至此,主要節點的介紹便完結了,更多實現細節可以在項目中瞭解,謝謝閲讀。