前言
半個月前,有一位B站的小兄弟加我微信,諮詢我這種地圖在Flutter裡如何實現...
類似的東西,我以前用flash
做過,在小程式
裡也實現過。雖然我對Flutter不算是特別熟悉,但沒覺得有多難,便答應了幫這位小兄弟做個Demo,他也挺客氣的答應幫我充個艦長
。
為避免貼大段程式碼,文中程式碼部分僅作為參考,並非全部程式碼,請理解後自行補全或者下載原始碼進行學習。
繪製方案選型
用什麼來畫呢?我給小兄弟的例子是用custompainter
繪製的,但本文裡我會用Widget
來實現,原因是地塊不多的話,用Widget
也感受不到什麼效能差距。自己用custompainter
實現的話,會麻煩一些
比如顯示一張圖片...
- 用
Widget
Image.asset("圖片路徑");
複製程式碼
- 在
Custompainter
裡
ImageStream stream = AssetImage("圖片路徑", bundle: rootBundle).resolve(ImageConfiguration.empty);
void listener(ImageInfo frame, bool synchronousCall) {
final UI.Image image = frame.image;
//將Image繪製到畫布上
canvas.drawImage(image, UI.Offset(60.0, 60.0), Paint());
stream.removeListener(ImageStreamListener(listener));
}
stream.addListener(ImageStreamListener(listener));
複製程式碼
匯入圖片素材
我準備了兩個地塊款式,兩款樹的圖片,全放在Flutter專案目錄裡的assets
目錄下
這樣我們在pubspec.yaml
(flutter專案的package.json
)裡配置一下就可以用以下程式碼來顯示圖片了
Image.asset("assets/floor1.png");
複製程式碼
配置佈局
其實這個地塊,我們只需要一個陣列就可以配置。不過是20塊地嘛?我們建立一個長度為20的陣列來管理地塊
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
複製程式碼
現在我們加幾個換行符,讓這個陣列對地塊的表述是不是更直觀了?
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0
複製程式碼
這樣是不是更清晰了?地塊的等級,有沒有澆水,有沒有樹都可以用數字來表示,比如你的地塊和樹的款式都不超過10個的話,那麼地塊款式用個位1-9表示,樹的種類用十位0-9表示。
1,1,1,1,1,
1,11,1,1,1,
1,1,1,1,1,
1,1,1,1,1,
1,1,1,1,1
複製程式碼
這就代表所有地塊用1號圖片,並且在第2行的第2個地塊上種了一棵1號款式的樹
當然這個陣列裡放Map
也是可以的,不是非要純數字。這樣可以存放更多資訊,但在本例裡數字已經足夠了。
想明白了配置,我們只需要用Widget
構建出來就行了
構建佈局
這裡我用Stack
+Positioned
來構建佈局
Stack和Positioned的結合就像是
css
裡的position:absolute
List<int> map = [
1,1,1,1,1,
1,1,1,1,1,
1,1,1,1,1,
1,1,1,1,1,
1,1,1,1,1
];
for(int i = 0;i<map.length;i++){
all.add(Positioned(
left: (i%rowCount).floor()*floorSize.width,
top:(i/rowCount).floor()*floorSize.height,
child: Text("$i")
));
}
複製程式碼
這是按序號橫排
如果需要按序號縱向排列,只需要將%
和/
對調一下
left: (i/rowCount).floor()*floorSize.width,
top:(i%rowCount).floor()*floorSize.height,
複製程式碼
現在我們把地塊的圖片顯示出來
left: (i/rowCount).floor()*floorSize.width,
top:(i%rowCount).floor()*floorSize.height,
child: Image.asset("assets/floor1.png",width: floorSize.width,height: floorSize.height)
複製程式碼
由於地塊是菱形,所以我們還需要計算一下偏移
- 按橫排序號上移50%
- 按豎排序號右移50%
- 寬高減半計算
int xIndex = (i/rowCount).floor();
int yIndex = (i%rowCount).floor();
Positioned(
left: xIndex*floorSize.width/2+yIndex*floorSize.width/2,
top:yIndex*floorSize.height/2-xIndex*floorSize.height/2
)
複製程式碼
TADA! 我們成功拼出了地塊對不對!
現在讓地塊按照陣列來顯示地塊圖片
List<int> map = [
1,1,1,1,1,
1,1,1,1,1,
1,1,2,1,1,
1,1,1,1,1,
1,1,1,1,1
];
Image.asset("assets/floor${map[i]}.png")
複製程式碼
把樹加進來
前面我們制定的配置格式為個位數表示地塊,十位數表示樹種類
,那麼程式碼如下
int floorType = map[i]%10;//數字取個位
int treeType = ((map[i]%100)/10).floor();//數字取十位
複製程式碼
剩下就是把樹的圖片顯示出來了
List<int> map = [
1,1,1,1,1,
1,1,51,1,1,
1,1,42,1,1,
1,1,51,1,1,
1,1,1,1,1
];
int treeType = ((map[i]%100)/10).floor();
if(treeType>0){
all.add(Positioned(
left: xIndex*floorSize.width/2+yIndex*floorSize.width/2-treeSize.width*.3,
top:yIndex*floorSize.height/2-xIndex*floorSize.height/2+135-treeSize.height,
child: Image.asset("assets/youzi$treeType.png",width: treeSize.width,height: treeSize.height)
));
}
複製程式碼
TADA! 我們成功種上樹了!
縮放移動怎麼解決?
在Flutter裡非常簡單,用InteractiveViewer
!!
InteractiveViewer(
boundaryMargin: const EdgeInsets.all(double.infinity),
minScale: 0.2,
maxScale: 2,
child: getMapWidget() //這個函式返回的就是前面構建的地塊Stack
)
複製程式碼
後記
這僅僅只完成了最簡單的農場遊戲佈局,不過相信大家已經通過這篇文章理解了實現方式,用任意框架都可以輕易完成了吧!
不過要真的完成開心農場遊戲,還有很多狀態需要處理。後面如果有空,我會再利用雲開發在flutter裡實現一個完整的“
開心農場
”,感興趣的小夥伴們請關注我的掘金和github喲~
Github倉庫
配套視訊教程:www.bilibili.com/video/BV1XA…
(發文時還沒空錄視訊,應該會在今晚錄製完成
)
請關注我
我是大帥
,一個老
程式猿
!