0%

【文章翻譯】How to build your own Flutter slide puzzle

【文章內容使用 Gemini 1.5 Pro 自動產生】

您可能已經閱讀過 [Flutter 拼圖黑客挑戰](https://flutterhack.devpost.com/),並正在思考如何將您的創造力推向新的極限。我們在此提供有關樣本程式碼庫結構的更多資訊,並提供一些關於如何建立您的比賽提交的一些想法。

滑動拼圖架構

提供的原始碼實作了一個分層架構,使用 flutter_bloc 管理狀態。Bloc 處理從遊戲邏輯到主題的所有內容。所有狀態都以一致的方式管理;針對拼圖邏輯的任何更新,您只需要找到對應的 bloc 並更新它。重設和洗牌遊戲按鈕、計時器和倒計時都是獨立的 bloc,因此這些可能是您考慮實作創造性的其他地方:也許是沙漏作為計時器?或者是一個華麗的洗牌順序?

請注意,所有遊戲邏輯都包含在一個名為 PuzzleBloc 的單一 bloc 中。它將透過事件更新,例如點擊一個磁磚以移動拼圖磁磚的 TileTapped 事件,或使用 PuzzleReset 完全重設拼圖板。每次拼圖更新時,都會發出新的拼圖狀態。

class PuzzleBloc extends Bloc<PuzzleEvent, PuzzleState> {
PuzzleBloc(this._size, {this.random}) : super(const PuzzleState() {
on<PuzzleInitialized>(_onPuzzleInitialized);
on<TileTapped>(_onTileTapped);
on<PuzzleReset>(_onPuzzleReset);
}
  void _onPuzzleInitialized(
PuzzleInitialized event,
Emitter<PuzzleState> emit,
) {...}
void _onTileTapped(
TileTapped event,
Emitter<PuzzleState> emit,
) {...}
void _onPuzzleReset(
PuzzleReset event,
Emitter<PuzzleState> emit,
) {...}
}

自訂主題

樣本拼圖程式碼包含 Simple 和 Dashatar 兩種主題。這些可以用作您自訂主題的起點 - 盡情借用所需部分,或從頭開始。您如何實作拼圖取決於您自己!您可以考慮發揮創造力的其中一個地方是拼圖主題。

Flutter slide puzzle with Dash in the lower right corner

所有演示中的主題都在 PuzzlePage 的頂部發生。它已抽象化,因此您只需要更新一個地方的主題元素,更改就會反映到所有地方。Simple 和 Dashatar 主題都定義了一系列選項,例如螢幕背景、選單、標誌、按鈕、文字顏色、主題是否顯示計時器(Dashatar 主題中出現,但 Simple 主題中沒有),等等。您可以在儲存庫根目錄的「dashatar」和「simple」目錄中找到它們。

/// {@template simple_theme}
/// The simple puzzle theme.
/// {@endtemplate}
class SimpleTheme extends PuzzleTheme {
/// {@macro simple_theme}
const SimpleTheme() : super();
  @override
Color get backgroundColor => PuzzleColors.white;
  @override
Color get buttonColor => PuzzleColors.primary6;
  @override
Color get hoverColor => PuzzleColors.primary3;
  @override
Color get pressedColor => PuzzleColors.primary7;
  ...
}

每個拼圖主題都有一個 LayoutDelegate,它計算該主題的佈局。您可以透過重複使用相同的佈局物件,僅調整一些主題選項來建立新的主題。對於更進階的設計,整個主題 LayoutDelegate 都可以自訂。例如,您可以覆寫 backgroundBuilder 以製作自訂背景,僅在大型螢幕上顯示。

@override
Widget backgroundBuilder(PuzzleState state) {
return Positioned(
bottom: 74,
right: 50,
child: ResponsiveLayoutBuilder(
small: (_, child) => const SizedBox(),
medium: (_, child) => const SizedBox(),
large: (_, child) => const DashatarThemePicker(),
),
);
}

實作動畫

動畫是您在滑動拼圖中探索的絕佳元素。雖然 Simple 主題不包含任何動畫,但 Dashatar 程式碼實作了一些動畫,其中一些是 [交錯](https://docs.flutter.dev/development/ui/animations/staggered-animations) 的。這些動畫由單一動畫控制器驅動,使用 [Interval](https://api.flutter.dev/flutter/animation/Interval-class.html) 調整以延遲動畫,並使用 [Tween](https://api.flutter.dev/flutter/animation/Tween-class.html) 定義動畫的數值範圍。這可以在 Dashatar 拼圖的成功狀態中看到,其中多個 Widget 透過動畫其偏移量和不透明度而逐漸出現。類似地,倒計時器的每個滴答都使用相同的技術,緩慢地增長然後淡出,就像下一個滴答即將出現一樣。

Dashatar slide puzzle mid-shuffle with a puzzle timer above

Dashatar 主題中的大多數動畫都是隱含的。這表示您無需自行撰寫整個動畫,因為 Widget 會自行對屬性更改進行動畫。舉例來說,請查看 DashatarPuzzleTile Widget,了解如何對使用者點擊磁磚時磁磚的移動進行動畫。每當點擊磁磚時,其目前的 position 會更新,並透過隱含動畫的 AnimatedAlign 在給定的 movementDuration 內轉場。

class DashatarPuzzleTile extends StatelessWidget {
...

final Tile tile;

@override
Widget build(BuildContext context) {
return AnimatedAlign(
alignment: FractionalOffset(
(tile.currentPosition.x - 1) / (size - 1),
(tile.currentPosition.y - 1) / (size - 1),
),
duration: movementDuration,
curve: Curves.easeInOut,
child: ResponsiveLayoutBuilder(...),
);
}
}

為網頁設計

樣本拼圖是為網頁而建的。它為三個螢幕尺寸實作了響應式設計:小型、中型和大型。此外,還有一個 ResponsiveLayoutBuilder,它使用 Flutter LayoutBuilder Widget 的包裝器,允許您根據不同的斷點指定不同的 Widget。

由於我們以網頁為目標,因此有一些額外的注意事項需要牢記。應用程式會預先快取圖片和一些音訊,以幫助優化遊戲期間的效能。當使用者到達預設的 Simple 拼圖遊戲時,Dashatar 版本的資產會在後台載入(我們對 [I/O 照片亭](https://github.com/flutter/photobooth) 載入所有道具的方式採取了類似的方法)。這將確保一旦使用者導航到 Dashatar 主題,大多數資產將已經載入,確保順暢的使用者體驗。

雖然應用程式在網頁上很方便,但您可以挑戰自己探索以創新方式讓拼圖擴展到多個平台的方法。您的拼圖在行動裝置和桌面上會是什麼樣子?您如何為多個平台調整您的想法?

無障礙性

滑動拼圖的設計考慮了無障礙性。使用者可以使用鍵盤與拼圖互動。這是透過 RawKeyboardListener 完成的,RawKeyboardListener 是一個在使用者按下或放開鍵盤上的鍵時會呼叫回呼的 Widget。使用者也可以使用螢幕閱讀器與應用程式互動。這是透過 [語義標籤](https://api.flutter.dev/flutter/widgets/Semantics-class.html) 完成的。還有一些提示,使用 Tooltip Widget 為某些操作顯示。如果您要從頭開始建立滑動拼圖提交,我們強烈建議使用上面類似的策略,使您的拼圖對所有使用者都具有無障礙性。

額外想法

您可以隨意使用演示程式碼庫作為您的提交的基礎。或者,您可以從頭開始實作一個新想法。重要的是您的提交是一個有效的滑動拼圖 - 但您如何實現它取決於您自己!

Simple 和 Dashatar 範例應該可以讓您了解您可以自訂的地方,或者您可以自行建立的酷炫事物。我們探索的一個有趣想法是將 [由 Felix Blaschke 建立的 Flutter Plasma](https://flutterplasma.dev/) 投影到拼圖磁磚上。電漿效果可以使用包裝在 Transform Widget 中的 CustomPaint Widget 實現,並使用 AnimationController 進行動畫。您可以在 [此處](https://github.com/felixblaschke/sa3_liquid/blob/main/lib/liquid/plasma/plasma.dart) 找到用在演示中的電漿渲染器的範例。

Slide puzzle with plasma gradient effect displayed on the tiles and rockstar Dash in the lower right corner

另一個想法是從 API 擷取圖片或其他資料。例如,您可以使用 [Google 照片 API](https://developers.google.com/photos) 使用您最喜歡的 Google 照片相簿中的照片製作滑動拼圖。這個挑戰的可能性是無限的!

在此查看樣本拼圖程式碼 [here](https://github.com/VGVentures/slide_puzzle)。在 Twitter 上使用 #FlutterPuzzleHack 與我們分享您的創作。我們迫不及待想看看您會建立什麼!


如何建立您自己的 Flutter 滑動拼圖 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。