Flutter實(shí)現(xiàn)拼圖游戲

demo.gif

實(shí)現(xiàn)這個小游戲, 需要哪些知識點(diǎn)了?

一. 加載圖片

Future<ui.Image> getImage(String path) async {
    ByteData data = await rootBundle.load(path);
    ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List());
    FrameInfo frameInfo = await codec.getNextFrame();
    image = frameInfo.image;
    return image;
}

二. 繪圖api

在flutter中有著跟android近乎一樣的canvas API. 但是也有些差異

  1. Android中的Rect.offset/Rect.offsetTo直接生效, 對應(yīng)flutter中的React.shift, 結(jié)果在返回值里.
  2. Android中的畫布通過bitmap構(gòu)建canvas, 接著直接調(diào)用canvas繪制, 繪制的內(nèi)容就跑到bitmap上了, 而在flutter里需要這樣
PictureRecorder recorder = PictureRecorder();
Canvas canvas = Canvas(recorder, Rect.fromLTWH(0.0, 0.0, width, height));
canvas.drawXXX();
...
Image image = canvas.endRecording().toImage(saveWidth, saveHeight);
//保存
image.toByteData(format: ImageByteFormat.png).then((data) {
    File file = File(path);
    file.writeAsBytes(data.buffer.asUint8List());
})
  1. Android里繪制文字比較直觀, 通過paint設(shè)置蠶食, 然后直接canvas.drawText, flutter里第一次用有點(diǎn)周折
ParagraphBuilder pb = ParagraphBuilder(ParagraphStyle(
  textAlign: TextAlign.center,
  fontWeight: FontWeight.w300,
  fontStyle: FontStyle.normal,
  fontSize: hitNode == node ? 20.0 : 15.0,
));
pb.pushStyle(ui.TextStyle(color: Color(0xff00ff00)));
pb.addText('${node.index + 1}');

ParagraphConstraints pc = ParagraphConstraints(width: node.rect.width);
//這里需要先layout, 后面才能獲取到文字高度
Paragraph paragraph = pb.build()..layout(pc);
//文字居中顯示
Offset offset = Offset(node.rect.width * (node.curIndex%level), node.rect.width * ((node.curIndex/level).floor() + 0.5) - paragraph.height/2);
canvas.drawParagraph(paragraph, offset);

三. 動畫

Android里有屬性動畫, Flutter也有對應(yīng)的動畫, 但是多了個AnimationController.dispose調(diào)用

AnimationController controller = AnimationController(
  vsync: this,
  duration: const Duration(milliseconds: 1000),
);
ani = IntTween(begin: 0, end: 100).animate(controller);
ani.addListener(() {
    print(ani.value);
})
controller.forward();
//釋放資源
controller.dispose();

四. 實(shí)現(xiàn)差異

Android里可以直接在自定義View里寫完所有代碼(繪制和交互邏輯), 調(diào)用上層完全不需要關(guān)心內(nèi)部如何實(shí)現(xiàn). 狀態(tài)變更直接View.invalidate.
而在flutter里需要實(shí)現(xiàn)CustomPainter, 它只負(fù)責(zé)顯示(繪制). 而狀態(tài)變更和交互邏輯則寫在StateWidget里. 這也符合flutter通過狀態(tài)管理的理念.
只不過要傳遞大量參數(shù)到下層, 稍顯麻煩, 僅僅只是為了一個draw(顯示).

五. 游戲可解性

可以通過計算這個排列的逆序數(shù)個數(shù)加空格位置的坐標(biāo), 最終得到的數(shù)的奇偶性判斷, 如果不ok, 再繼續(xù)生成直到ok.

github傳送

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容