在Flutter裡實現一個開心農場地塊佈局!Web前端工程師也可以看看,作為Flutter入門。

大帥老猿發表於2021-08-17

前言

半個月前,有一位B站的小兄弟加我微信,諮詢我這種地圖在Flutter裡如何實現...

image.png

image.png

類似的東西,我以前用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));
複製程式碼

匯入圖片素材

image.png

我準備了兩個地塊款式,兩款樹的圖片,全放在Flutter專案目錄裡的assets目錄下

image.png

這樣我們在pubspec.yaml(flutter專案的package.json)裡配置一下就可以用以下程式碼來顯示圖片了

image.png

Image.asset("assets/floor1.png");
複製程式碼

配置佈局

其實這個地塊,我們只需要一個陣列就可以配置。不過是25塊地嘛?我們建立一個長度為25的陣列來管理地塊

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")
  ));
}
複製程式碼

這是按序號橫排

image.png

如果需要按序號縱向排列,只需要將%/對調一下

left: (i/rowCount).floor()*floorSize.width,
top:(i%rowCount).floor()*floorSize.height,
複製程式碼

image.png

現在我們把地塊的圖片顯示出來

left: (i/rowCount).floor()*floorSize.width,
top:(i%rowCount).floor()*floorSize.height,
child: Image.asset("assets/floor1.png",width: floorSize.width,height: floorSize.height)
複製程式碼

image.png

由於地塊是菱形,所以我們還需要計算一下偏移

  1. 按橫排序號上移50%
  2. 按豎排序號右移50%
  3. 寬高減半計算
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
)
複製程式碼

image.png

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")
複製程式碼

image.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)
    ));
}
複製程式碼

image.png

TADA! 我們成功種上樹了!

縮放移動怎麼解決?

在Flutter裡非常簡單,用InteractiveViewer!!

InteractiveViewer(
    boundaryMargin: const EdgeInsets.all(double.infinity),
    minScale: 0.2,
    maxScale: 2,
    child: getMapWidget() //這個函式返回的就是前面構建的地塊Stack
)
複製程式碼

2021-08-17 11_42_57.gif

後記

這僅僅只完成了最簡單的農場遊戲佈局,不過相信大家已經通過這篇文章理解了實現方式,用任意框架都可以輕易完成了吧!

不過要真的完成開心農場遊戲,還有很多狀態需要處理。後面如果有空,我會再利用雲開發在flutter裡實現一個完整的“開心農場”,感興趣的小夥伴們請關注我的掘金和github喲~

Github倉庫

github.com/ezshine/flu…

配套視訊教程:www.bilibili.com/video/BV1XA…

請關注我

我是大帥,一個程式

2222.jpg

相關文章