再說一次,F(xiàn)lutter非常的牛址儒,數(shù)年前用IOS原生想要寫一款螞蟻攻防的二維游戲,但是復(fù)雜的Object-C開發(fā)到一半衅疙,覺得邏輯混亂復(fù)雜莲趣,畫面也不自然。于是不得不放棄饱溢。
當(dāng)最近認識了Flutter以及跨平臺的開發(fā)時喧伞,不禁萌生了再次使用Flutter來完成這款游戲的想法,先后了解了Flame和SpriteWidget游戲引擎绩郎,由于Flame相對多一點說明潘鲫,因此決定采用Flame進行開發(fā),關(guān)于SpriteWidget也是可以實現(xiàn)的肋杖,貌似功能更豐富溉仑,但是好像沒有再更新了。
Flame開發(fā)游戲可以參考以下說明和Demo:
1. Create a Mobile Game with Flutter and Flame – Beginner Tutorial
2. 中文翻譯(有空繼續(xù))- Flame開發(fā)Flutter游戲 (二)
3. Github Demo - japalekhin/langaw
4. Github Demo - flame-engine/trex-flame
如果僅僅制作一個類似于langaw的小型游戲状植,參考Tutorial和langaw就夠了浊竟,但是稍微復(fù)雜一些的游戲,就不能夠使用Game類津畸,需要使用BaseGame類振定,使用Components,相對來講洼畅,位置的相對計算吩案,render,components.add, 以及update的使用帝簇,就需要搞清楚相互的關(guān)系。然后Flame說明比較簡單靠益,能找到的資料也非常有限丧肴。
通過在開發(fā)中遇到的問題,記錄一下Flame的一些游戲中用到的場景如何實現(xiàn)胧后,絕對原創(chuàng)芋浮,目前絕無僅有,全互聯(lián)網(wǎng)唯一。
(-)旋轉(zhuǎn)的物體
參考Flame Issue #90給出了完整的旋轉(zhuǎn)一個方塊的方法纸巷,注意prepareCanvas(c);原理是為旋轉(zhuǎn)目標(biāo)準(zhǔn)備canvas镇草,尺寸大小為目標(biāo)大小,然后update改變目標(biāo)的angle瘤旨,當(dāng)然角度改變按照anchor來進行梯啤。
Square(double size, this.rotate) {
? width = height = size;
? anchor = Anchor.center;
}
@override
void render(Canvas c) {
? prepareCanvas(c);
? c.drawRect(Rect.fromLTWH(0, 0, width, height), Palette.white.paint);
? c.drawRect(Rect.fromLTWH(0, 0, 3, 3), Palette.red.paint);
? c.drawRect(Rect.fromLTWH(width / 2, height / 2, 3, 3), Palette.blue.paint);
}
定義對象時,定義一個width = height = size;然后在render方法中從(0, 0, width, height)繪制對象存哲,這樣改變angle就可以進行旋轉(zhuǎn)因宇,如果不是這樣,會按照你定義的整個對象類尺寸進行旋轉(zhuǎn)祟偷。
這樣就有幾個問題察滑,1,如何將這個類變成PositionComponent修肠?贺辰;2, 如果對象是Sprite或者動畫AnimationComponent嵌施,又如何旋轉(zhuǎn)饲化?3, 如果添加多個對象在一起艰管,如何旋轉(zhuǎn)滓侍?
下面就是我的心得體會,當(dāng)然中間也踩了很多坑牲芋,做了很多測試撩笆。
(待續(xù))
Flame的生命周期:
參考Flame Issue#16 ,可以在對于BaseGame或者Game通過設(shè)備App的lifeCycle進行控制:
@override
void lifecycleStateChange(AppLifecycleState state) {
? if (state != AppLifecycleState.resumed) {
??? // pause your updates
??? // pause all audio players
? } else {
??? // resume your updates
??? // resume all audio players
? }
}
The Game class has a listener for changes in the app lifecycle, which can hook to resume and paused. You can also stop your update logic with a flag variable as well, so that your game doesn't update while on background.
Game類有一個app的lifecycle的監(jiān)聽缸浦,可以用來處理resume/paused的狀態(tài)轉(zhuǎn)換夕冲。你可以使用一個標(biāo)簽參數(shù)來停止你的upate邏輯,這樣你的游戲就不會在后臺繼續(xù)更新裂逐。
IphoneX 劉海屏適配:
final double topPadding = MediaQuery.of(context).padding.top;
final double bottomPadding = MediaQuery.of(context).padding.bottom;
如果使用的是自定義布局的話歹鱼, Flutter 提供了媒體查詢的接口, 可與獲取到上邊距和下邊距的值卜高。
上邊距在 iPhoneX 上的值是 44弥姻, 在其他設(shè)備上的值是 20, 是包含了電池條的高度的掺涛。
下邊距在iPhoneX 上的值是34庭敦,在其他設(shè)備上的值是 0。
現(xiàn)在Flutter出了一個新的Widget薪缆,叫做 SafeArea 秧廉, 直接在外面包一層這個Widget, 就可以讓子Widget 不會被劉海覆蓋了。
MediaQuery可以建立widget查詢解析給定的子樹疼电。但是對于Flame嚼锄,不是簡單的widget,上面方法使用時無法輸入context蔽豺。
使用MediaQueryData.fromWindow(window)獲取window的信息区丑,這樣來獲取上下邊界信息。
topPadding = MediaQueryData.fromWindow(window).padding.top;
bottomPadding = MediaQueryData.fromWindow(window).padding.bottom;