【基於Flutter&Flame 的飛機大戰開發筆記】子彈升級和補給
theme: cyanosis highlight: xcode
前言
敵機Component
重構之後,飛機大戰的基礎能力就基本成型了。本文會對子彈Component
作一次升級,新增遊戲中的子彈道具,以及它與戰機Component
的碰撞處理。
筆者將這一系列文章收錄到以下專欄,歡迎有興趣的同學閱讀:
子彈特性
前面只是簡單的定義了類Bullet1
作為子彈Component
,根據已有的屬性可以定義一個屬於子彈的父類Bullet
,這裡繼續使用抽象類。
```dart
abstract class Bullet extends SpriteAnimationComponent with CollisionCallbacks {
Bullet({required this.speed, required this.attack})
: super(size: Vector2(5, 11));
double speed; int attack;
Future
@override
Future
add(MoveEffect.to(
Vector2(position.x, -size.y), EffectController(speed: speed),
onComplete: () {
removeFromParent();
}));
add(RectangleHitbox());
}
void loss() {
removeFromParent();
}
}
``
定義比較簡單
- 子彈擁有屬於自己的速度
speed,傷害
attack。
- 固定
size = 5 * 11。
- 由於**不同子彈的貼圖不同**,定義一個抽象方法
bulletAnimation()由子類載入。
- 使用
MoveEffect代替之前的
s = v * t控制移動,這個前文有講到。這裡是**由初始位置(一般是
戰機Component的頭部)移動到螢幕最上方**。
-
loss()方法是與
敵機Component`發生碰撞時的呼叫。
以上所列出的就是目前子彈的共有特性了。
升級子彈
遊戲中戰機Component
會通過獲得道具的方式,短暫獲取強化版子彈。這裡用類Bullet2
表示
```dart
class Bullet2 extends Bullet {
Bullet2({required super.speed, required super.attack});
@override
Future
先來看看最終效果吧
子彈補給
如上面的效果,遊戲中會隨機生成子彈補給。這裡定義一個抽象類Supply
。補給Component
的效果是勻速向下移動並帶有小幅度的晃動。
- 勻速向下移動繼續採用MoveEffect
的方式。
- 小幅度的晃動需要使用RotateEffect
做一個小幅度的旋轉。由於需要一個吊起來來回晃動的效果,所以我們還需要將錨點設定為topCenter
,令旋轉支點為上方居中的位置。
故最後的邏輯為 ```dart abstract class Supply extends SpriteComponent with HasGameRef { Supply({position, size}) : super(position: position, size: size, anchor: Anchor.topCenter);
@override
Future
add(RotateEffect.by(15 / 180 * pi,
EffectController(duration: 2, reverseDuration: 2, infinite: true)));
add(RectangleHitbox()..debugMode = true);
}
}
``
- 移動距離是**從螢幕最上方向螢幕最下方移動**。
- 旋轉角度是弧度,這裡是
(15 / 180)pi,需要來回晃動,所以這裡**設定了正反方向的持續時間且效果是無限迴圈的**。
- 最後需要新增
RectangleHitbox,作為與
戰機Component的碰撞檢測。ps:碰撞檢測的邏輯在子類實現,這裡目前是
類BulletSupply`。
子類的邏輯幾乎只有碰撞檢測,這個在下文會講到,先來看看這個實現的效果
升級與恢復
在子彈補給Component
中,碰撞檢測與戰機Component
發生碰撞後
- 會觸發其upgradeBullet()
方法,此時會變更bulletType
,即子彈型別。
- 新增一個0.15s
的ColorEffect
,作為子彈升級的反饋。
- 開啟一個Timer
,定時5s
,作為子彈恢復回正常的計時。ps:_bulletUpgradeTimer
設定了autoStart = false
,不允許自動開啟。當呼叫start()
時,進度會重置,可理解為連續獲得補給計時會重置。
```dart
// class BulletSupply
@override
void onCollisionStart(
Set
// class Player int bulletType = 1;
_bulletUpgradeTimer = Timer(5, onTick: _downgradeBullet, autoStart: false);
void upgradeBullet() { bulletType = 2; add(ColorEffect(Colors.blue.shade900, const Offset(0.3, 0.0), EffectController(duration: 0.15)));
_bulletUpgradeTimer.start(); }
void _downgradeBullet() { bulletType = 1; }
// timer.dart /// Start the timer from 0. void start() { reset(); resume(); } ```
由於戰機Component
,類Player
本身擁有一個定時器用於發射子彈,故在子彈型別bulletType
修改後,下一次發射子彈的邏輯就需要變更。
```dart
// class Player
void _addBullet() {
if (bulletType == 2) {
final Bullet2 bullet2 = Bullet2(speed: 400, attack: 2);
bullet2.priority = 1;
bullet2.position = Vector2(position.x + size.x / 2 - 10, position.y + 10);
final Bullet2 bullet2a = Bullet2(speed: 400, attack: 2);
bullet2a.priority = 1;
bullet2a.position =
Vector2(position.x + size.x / 2 + 10, position.y + 10);
gameRef.add(bullet2);
gameRef.add(bullet2a);
} else { final Bullet1 bullet1 = Bullet1(speed: 200, attack: 1); bullet1.priority = 1; bullet1.position = Vector2(position.x + size.x / 2, position.y); gameRef.add(bullet1); } } ```
補給生成
還記得那個敵機生成器EnemyCreator
嗎?這裡暫時通過它的定時來生成補給
```dart
// class EnemyCreator
void _createEnemy() {
final width = gameRef.size.x;
double x = _random.nextDouble() * width;
final double random = _random.nextDouble();
if (random < 0.05) {
final size = Vector2(60, 75);
if (width - x < size.x / 2) {
x = width - size.x / 2;
} else if (x < size.x / 2) {
x = size.x / 2;
}
final enemySupply =
BulletSupply(position: Vector2(x, -size.y), size: size);
add(enemySupply);
return;
}
。。。
``
需要注意的是:由於
補給Component的**錨點被修改為
topCenter**,所以
position的位置也**被移動到了
topCenter`**。這裡的邊界計算需要按此情況作適配。
最後
本文記錄子彈型別的擴充套件、子彈補給的效果和生成實現以及戰機Component
的子彈升級的邏輯。至此,飛機大戰的功能基本上都實現了,剩下附加道具、計分系統以及生命值系統等功能。後續會考慮參考官方的bloc
例子對整個專案的結構進行修改。
- 用華為CameraKit實現預覽和拍照
- 重溫今日頭條螢幕適配方案
- 【基於Flutter&Flame 的飛機大戰開發筆記】展示面板及重新開始選單
- 【基於Flutter&Flame 的飛機大戰開發筆記】利用bloc管理遊戲狀態
- 【基於Flutter&Flame 的飛機大戰開發筆記】子彈升級和補給
- 【基於Flutter&Flame 的飛機大戰開發筆記】重構敵機
- 【基於Flutter&Flame 的飛機大戰開發筆記】子彈發射及碰撞檢測
- 【基於Flutter&Flame 的飛機大戰開發筆記】敵機生成器
- 【基於Flutter&Flame 的飛機大戰開發筆記】搭建專案及建立一架戰機
- 一文搞定移動端接入ncnn模型(包括Android、iOS)
- 在Android上實現Metal的計算Demo
- 移動端執行JS指令碼除錯方案-單元測試
- 為什麼Glide4.x中的AppGlideModule不應該出現在Library中
- CameraX OpenGL預覽的全新版本
-
有關Swift Codable解析成Dictionary
的一些事 - 在iOS應用上進行記憶體監控
- 體驗一下用Metal畫圖
- 在iOS上進行WebP編碼是一種怎樣的體驗之為何cpu佔用如此之高?
- 在iOS上進行WebP編碼是一種怎樣的體驗?