iT邦幫忙

2024 iThome 鐵人賽

DAY 4
0
Mobile Development

用Flutter Flame做遊戲!Live!系列 第 5

移動遊戲中的物體:Dragcallback和Component

  • 分享至 

  • xImage
  •  

DragCallbacks就像各種AndroidNative原生開發時用來處理點擊或觸碰的Listener一樣,只是它叫做「callback」。
(真的不懂很多人、或很多文章喜歡煞有其事的解釋和定義「Listener」與「callback」的不同。)

一個FlameGame可以擴充一個DragCallbacks


class MyGame extends flame.FlameGame with DragCallbacks{

  @override
  void onDragUpdate(DragUpdateEvent event) {
    super.onDragUpdate(event);
  }

}

比較奇妙的地方是按照Flutter的特性,DragCallbacks不單單只是個接口(interface),而是有自己完整的物件特性,——它自己也是繼承自Component。
(這裡會有些有趣的假想,晚點、或過幾天來測試。)

但什麼是Component?
如果Flutter中,所有東西都是Widget,那Flame中所有東西都是Component。——除了FlameGame本身以外吧!

遊戲選單是Component,遊戲角色是個COmponent,遊戲怪物是個COmponent,遊戲中一顆子彈也「可以」是個Component。

所有東西都是Component。
而Component跟FlameGame一樣也有「update」與「render」。

例如...


class FlowerComponent extends PositionComponent with DragCallbacks {
  @override
  void render(Canvas canvas) {
    super.render(canvas);
    flowerPainter.paint(canvas, Size(size.x, size.y));
  }

  @override
  void update(double dt) {
    super.update(dt);
    newIndex += dt*33.333;
    flowerPainter.setIndex( (newIndex.toInt()%30));
  }
}

這是個利用Component畫花、而不在FlameGame中畫的方法。

FlameGame有個「add」函數,可以將「Component」跟FlameGame連結起來,則FlameGame運行時,自然會去呼叫它所有的Component內的「update」與「render」。
(比較奇妙的是:Component內的render時使用的座標完全是以自己的左上角為(0,0),不會被這個Component在整個FlameGame中的座標所影響。這大大降低了設計render的難度....或事實上反而增加了?)


  @override
  Future<void> onLoad() async {
    square = FlowerComponent();
    square.width = 80;
    square.height = 80;
    add(square);

  }

可以看到這段範例中有「幫Component設定大小」的程式碼。
就跟許多Widget一樣,Component必須要指定大小給它。(然後這段功能會預設這個Component的座標為(0,0)
。)


回來講DragCallbacks。

結合上一篇的範例,先直接在FlameGame中使用DragCallbacks,然後來拖動花吧!


  flame.NotifyingVector2 position = flame.NotifyingVector2(40, 40);
  
  @override
  void onDragUpdate(DragUpdateEvent event) {
    super.onDragUpdate(event);
    position.add(event.localDelta);
    flowerPainter.setCenter(position.x, position.y);
  }

可以看出來,程式碼必須新增一個參數,用來管理CustomPainter所需要的「座標」,(其實FlowerPainter也做了些修正,例如增加了可以隨時變換座標的「setCenter」,還有繪圖時會使用這個Center座標。)

但操作上真正的問題是:整個遊戲畫面的每一個地方點擊滑動時,花朵都會跟著移動。
也就是說:需要自行判斷玩家是否點擊到了花朵才行,如果沒有點擊到,則「花朵座標變化」的程式碼就不該執行。

(其實這段程式碼不難,只是累了、工作量很大,所以就不做了。)

但如果改用Component來擴充實作DragCallbacks,結果就不一樣了!

  @override
  void onDragUpdate(DragUpdateEvent event) {
   position.add(event.localDelta);
  }

這樣就好了!
這樣就能精準的移動花朵!
(但其實不是所有Component擴充實作DragCallbacks後都有這樣的結果,必須要是PositionComponent才行,因為PositionComponent有自帶判斷「是否被點擊」的功能。)


這個簡單的測試跟比較,讓我們知道了「使用Component」的潛在優勢。
因為這個框架並不會限制我們進行設計的方向與限度,還能大幅度簡化我們需要做的事情。


上一篇
來使用Flame引擎...
下一篇
中秋節:簡單補充一下遊戲引擎的作用
系列文
用Flutter Flame做遊戲!Live!26
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言