RainVisitor Blog

RainVisitor

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

原文:https://medium.com/flutter/whats-new-in-flutter-3-8c74a5bc32d0

深入了解最新版本,包括 macOS 和 Linux 穩定版本、效能提升等等!

是時候再次發佈 Flutter 穩定版本了——我們非常自豪地宣布 Flutter 3!僅僅三個月前,我們宣布了 Flutter 對 Windows 的支援。今天,我們很高興地宣布,除了 Windows 之外,Flutter 現在也穩定支援 macOS 和 Linux!

閱讀全文 »

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

原文:https://medium.com/dartlang/dart-2-17-b216bfc80c5d

Dart 2.17:提升生產力和整合能力

今天在 Google I/O 上,我們宣布推出新的 Dart SDK,版本 2.17。此版本基於我們提升生產力和平台可攜性的核心主題而構建。它提供了新的語言特性:支援成員的列舉、改進了向父類別轉發參數的功能,以及更靈活的命名參數。我們改進了工具,推出了 package:lints 的一個新的主要版本——我們的工具支援根據我們的最佳實務檢查 Dart 程式碼——並廣泛更新了核心函式庫 API 文件,其中包含豐富的程式碼範例。為了改進平台整合,我們提供了在 Flutter 外掛中使用 dart:ffi(原生 C 互通性)的新範本、對 RISC-V 處理器的實驗性支援,以及對簽署 macOS 和 Windows 可執行檔的支援。

閱讀全文 »

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

原文:https://medium.com/flutter/i-o-pinball-powered-by-flutter-and-firebase-d22423f3f5d

將 Flutter 遊戲開發提升到新的境界

Flutter’s Dash, Android Jetpack, Chrome Dino, and Firebase’s Sparky gathering around a pinball machine.

為了 Google I/O,我們與 Flutter 團隊合作,重新構想了一款經典彈珠台遊戲,該遊戲使用 Flutter 和 Firebase 構建。以下是如何在 Flame 遊戲引擎的幫助下將 [I/O 彈珠台](https://pinball.flutter.dev/) 在網頁上呈現。

遊戲開發基礎

對於構建由使用者互動驅動的遊戲(例如益智遊戲和文字遊戲)來說,Flutter 架構是一個很好的選擇。當談到使用遊戲迴圈的遊戲時,[Flame](https://docs.flame-engine.org/)(一個建立在 Flutter 之上的二維遊戲引擎)可以成為一個有用的工具。I/O 彈珠台使用 Flame 的開箱即用功能,例如動畫、物理、碰撞偵測等等,同時也利用 Flutter 架構的基礎設施。如果您可以使用 Flutter 構建應用程式,那麼您已經擁有了使用 Flame 構建遊戲所需的基礎。

Flame engine logo

遊戲迴圈

在傳統應用程式中,螢幕通常在使用者發生事件或互動之前都是視覺上的靜態。對於遊戲來說,則相反 - UI 是持續渲染的,遊戲的狀態也在不斷變化。Flame 提供了一個遊戲 Widget,它在內部管理遊戲迴圈,以便 UI 能夠以高效能的方式持續渲染。`Game` 類別包含遊戲元件和邏輯的實作,這些實作傳遞給 Widget 樹中的 `GameWidget`。在 I/O 彈珠台中,遊戲迴圈會對彈珠在遊戲場上的位置和狀態做出反應,如果彈珠與物體發生碰撞或掉出了遊戲,則會應用必要的特效。

@override
void update(double dt) {
super.update(dt);
  final direction = -parent.body.linearVelocity.normalized();
angle = math.atan2(direction.x, -direction.y);
size = (_textureSize / 45) *
parent.body.fixtures.first.shape.radius;
}

使用二維元件渲染三維空間

構建 I/O 彈珠台的挑戰之一是弄清楚如何僅使用二維元素來建立三維效果。元件的順序決定了它們在螢幕上的渲染方式。例如,當彈珠向上發射到斜坡時,彈珠的順序會上升,因此它看起來像是位於斜坡的頂部。

I/O Pinball playfield featuring Flutter’s Dash, Android Jetpack, Chrome’s Dino, and Firebase’s Sparky, and other Google-themed elements. Toward the bottom of the board there are two flippers with two bumpers above and to the bottom right is the ball ready to be launched.

彈珠、彈射器、兩個彈射器和 Chrome 恐龍都是具有動態主體的元素,這些元素會受到世界物理的影響。彈珠的大小也會根據它在遊戲場上的位置而變化。當彈珠移動到遊戲場的頂部時,它的尺寸會縮小,從使用者的角度來看,它看起來離使用者更遠。此外,彈珠上的重力會根據彈珠台的角度進行調整,因此彈珠在斜坡上會下降得更快。

/// 根據彈珠在遊戲場上的位置縮放彈珠的主體和 Sprite。
class BallScalingBehavior extends Component with ParentIsA<Ball> {
@override
void update(double dt) {
super.update(dt);
final boardHeight = BoardDimensions.bounds.height;
const maxShrinkValue = BoardDimensions.perspectiveShrinkFactor;
    final standardizedYPosition = parent.body.position.y +   (boardHeight / 2);
final scaleFactor = maxShrinkValue +
((standardizedYPosition / boardHeight) * (1 - maxShrinkValue));
parent.body.fixtures.first.shape.radius = (Ball.size.x / 2) * scaleFactor;
final ballSprite = parent.descendants().whereType<SpriteComponent>();
if (ballSprite.isNotEmpty) {
ballSprite.single.scale.setValues(
scaleFactor,
scaleFactor,
);
}
}
}

使用 Forge 2D 實現物理

I/O 彈珠台很大程度上依賴於由 Flame 團隊維護的 [forge2d](https://pub.dev/packages/forge2d) 套件。此套件將開源 [Box2D 物理引擎](https://box2d.org/) 移植到 Dart 中,以便可以輕鬆地與 Flutter 整合。我們使用 forge2d 來為遊戲的物理提供動力,例如遊戲場上物體(Fixture)之間的碰撞偵測。

forge2D 允許我們監聽 Fixture 之間的碰撞事件。然後,我們為 Fixture 添加 `ContactCallbacks`,以便在兩個元素之間發生接觸時收到通知。例如,當彈珠(具有具有 `CircleShape` 的 Fixture)與彈珠台(具有具有 `EllipseShape` 的 Fixture)發生接觸時,得分會增加。在這些回呼函式中,我們可以精確設定接觸的開始和結束位置,因此當兩個元素與另一個元素發生接觸時,就會發生碰撞。

@override
Body createBody() {
final shape = CircleShape()..radius = size.x / 2;
final bodyDef = BodyDef(
position: initialPosition,
type: BodyType.dynamic,
userData: this,
);
  return world.createBody(bodyDef)
..createFixtureFromShape(shape, 1);
}

Sprite 表格動畫

彈珠台遊戲場上有一些元素,例如 Android、Dash、Sparky 和 Chrome 恐龍,它們是動畫的。對於這些元素,我們使用了 Sprite 表格,這些表格包含在 Flame 引擎中,並帶有 `SpriteAnimationComponent`。對於每個元素,我們都有一個檔案,其中包含圖像的不同方向、檔案中的幀數以及幀之間的時間。使用這些資料,Flame 中的 `SpriteAnimationComponent` 會將所有圖像在迴圈中編譯在一起,使元素看起來像動畫。

Sprite sheet showing the Android in various orientations so that if played on a loop, it will appear to be spinning in a circle.
Sprite sheet 範例
final spriteSheet = gameRef.images.fromCache(
Assets.images.android.spaceship.animatronic.keyName,
);
const amountPerRow = 18;
const amountPerColumn = 4;
final textureSize = Vector2(
spriteSheet.width / amountPerRow,
spriteSheet.height / amountPerColumn,
);
size = textureSize / 10;
animation = SpriteAnimation.fromFrameData(
spriteSheet,
SpriteAnimationData.sequenced(
amount: amountPerRow * amountPerColumn,
amountPerRow: amountPerRow,
stepTime: 1 / 24,
textureSize: textureSize,
),
);

更加深入地了解 I/O 彈珠台程式碼庫

Firebase 實時結果排行榜

I/O 彈珠台排行榜實時顯示世界各地玩家的最高分。使用者還可以將他們的得分分享到 Twitter 和 Facebook。我們使用 Firebase [Cloud Firestore](https://firebase.google.com/docs/firestore) 來追蹤前十名得分,並將其擷取以顯示在排行榜上。當新的得分寫入排行榜時,[Cloud Function](https://firebase.google.com/docs/functions) 會將得分按降序排序,並移除任何不在前十名的得分。

Leaderboard for I/O pinball with 10 top scores displayed.
/// 擷取前 10 個 [LeaderboardEntryData]。
Future<List<LeaderboardEntryData>> fetchTop10Leaderboard() async {
try {
final querySnapshot = await _firebaseFirestore
.collection(_leaderboardCollectionName)
.orderBy(_scoreFieldName, descending: true)
.limit(_leaderboardLimit)
.get();
final documents = querySnapshot.docs;
return documents.toLeaderboard();
} on LeaderboardDeserializationException {
rethrow;
} on Exception catch (error, stackTrace) {
throw FetchTop10LeaderboardException(error, stackTrace);
}
}

為網頁構建

與傳統應用程式相比,構建響應式的遊戲可能會更容易。彈珠台遊戲場只需要縮放到設備的大小即可。對於 I/O 彈珠台,我們根據設備的大小以固定比例進行縮放。這確保了無論顯示大小如何,座標系始終保持一致,這對於確保元件在設備之間一致地顯示和互動非常重要。

I/O 彈珠台還可以適應行動或桌面瀏覽器。在行動瀏覽器中,使用者可以點擊發射按鈕開始遊戲,也可以點擊螢幕的左右兩側來控制對應的彈射器。在桌面瀏覽器中,使用者可以使用鍵盤來發射彈珠和控制彈射器。

程式碼庫架構

彈珠台程式碼庫遵循分層架構,每個功能都在其自己的資料夾中。此專案中,遊戲邏輯也與視覺元件分開。這可以確保我們能夠輕鬆地獨立更新視覺元素,而與遊戲邏輯無關,反之亦然。

彈珠台的主題會根據使用者在開始遊戲之前選擇的角色而有所不同。主題由 `CharacterThemeCubit` 類別控制。根據角色選擇,彈珠顏色、背景和其他元素會更新。

Displays the different I/O Pinball themes. The top left shows Sparky, carpet with prominent flame decorations and neon orange lighting. The top right shows Dash, a carpet with prominent egg decorations and neon blue lighting. The bottom left shows Android, carpet with prominent Android Jetpack decorations and neon green lighting. The bottom right shows Chrome Dino, carpet with prominent cactus decorations, and neon white lighting.
/// {@template character_theme}
/// 用於建立角色主題的基類。
///
/// 角色特定的遊戲元件應在此處指定一個 getter,以
/// 載入其對應的遊戲資產。
/// {@endtemplate}
abstract class CharacterTheme extends Equatable {
/// {@macro character_theme}
const CharacterTheme();
/// 角色名稱。
String get name;
/// 彈珠的資產。
AssetGenImage get ball;
/// 背景的資產。
AssetGenImage get background;
/// 圖示資產。
AssetGenImage get icon;
/// 排行榜的圖示資產。
AssetGenImage get leaderboardIcon;
/// 閒置角色動畫的資產。
AssetGenImage get animation;
@override
List<Object> get props => [
name,
ball,
background,
icon,
leaderboardIcon,
animation,
];
}

I/O 彈珠台的遊戲狀態由 [flame_bloc](https://pub.dev/packages/flame_bloc) 處理,flame_bloc 是一個將 bloc 與 Flame 元件連接起來的套件。例如,我們使用 flame_bloc 來追蹤剩餘的遊戲回合數、透過遊戲獲得的任何獎金以及目前的遊戲得分。此外,Widget 樹的頂部還有一個 Widget,其中包含載入頁面的邏輯,包括如何玩遊戲的說明。我們還遵循 [行為模式](https://en.wikipedia.org/wiki/Behavioral_pattern) 來封裝和隔離遊戲功能的某些元素,這些元素基於其元件。例如,彈珠台在被彈珠擊中時會發出聲音,因此我們實作了 `BumperNoiseBehavior` 類別來處理此問題。

class BumperNoiseBehavior extends ContactBehavior {
@override
void beginContact(Object other, Contact contact) {
super.beginContact(other, contact);
readProvider<PinballPlayer>().play(PinballAudio.bumper);
}
}

程式碼庫還包含全面的單元、Widget 和黃金測試。有時,由於單個元件可能具有多個責任,這使得它們難以隔離測試,因此測試遊戲會帶來一些挑戰。結果,我們最終定義了一些模式來更好地隔離和測試元件。我們還將改進整合到 [flame_test](https://pub.dev/packages/flame_test) 套件中。

元件沙箱

此專案很大程度上依賴於 Flame 元件,以將彈珠台體驗呈現出來。程式碼庫附帶了一個元件沙箱,它類似於 [UI 元件庫](https://gallery.flutter.dev/#/)。這是在開發遊戲時的一個有用的工具,因為它允許您隔離開發遊戲元件,並確保它們在整合到遊戲中之前,看起來和行為符合預期。

Chrome Dino is animated, moving left to right and opening its mouth to shoot out the pinball ball.

接下來要做什麼

看看您是否可以在 [I/O 彈珠台](https://pinball.flutter.dev/) 中獲得高分!程式碼在 [這個 GitHub 儲存庫](https://github.com/flutter/pinball) 中是開源的。請關注排行榜,並在社交媒體上分享您的得分!

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

一步修復多個分析問題

快速修復分析問題中,我們探討了在編輯時自動修復個別診斷的支持。有時即使這樣也太慢了,您真的希望一次修復多個診斷。幸運的是,也有支持這樣做的,我們將在本文中介紹。

閱讀全文 »

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

原文:https://medium.com/flutter/does-flutter-boost-developer-productivity-475f713724b3

Flutter 是否提升了開發人員的生產力?

Flutter 團隊持續進行每季一次的使用者調查,以收集您,也就是 Flutter 開發人員的意見。2022 年的第一份調查於 2 月 22 日至 3 月 3 日進行,並透過 Flutter IDE 外掛、docs.flutter.dev 網站和 Twitter 進行訪問,超過 8,000 人參與了調查。

閱讀全文 »

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

原文:https://medium.com/dartlang/dart-asynchronous-programming-streams-dab952023ed7

Dart 非同步程式設計:串流

一個顯示來自串流資料的簡單 Flutter 應用程式

本文涵蓋了反應式程式設計的基礎之一:串流,它們是 Stream 類型的物件。

如果您已閱讀我們先前關於 Futures 的文章,您可能記得 每個 Future 代表一個單一值(錯誤或資料),以非同步方式傳遞。串流的工作方式類似,只是它不是單一物件,串流可以隨著時間傳遞零個或多個值和錯誤

閱讀全文 »

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

原文:https://medium.com/dartlang/contributors-for-google-summer-of-code-2022-17e777f043f0

徵求 Google Summer of Code 2022 貢獻者

Google Summer of Code (GSoC) 是一個全球性的計畫,旨在讓學生開發者參與開源軟體開發。Google 贊助學生在夏季與一個指導性的開源組織合作進行一個 12 週以上的程式設計專案。在過去的 17 年裡,已有超過 18,000 名學生參與了 Google Summer of Code。

閱讀全文 »

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

原文:https://medium.com/dartlang/gradual-null-safety-migration-for-large-dart-projects-85acb10b64a9

大型 Dart 專案的漸進式空安全遷移

對於一個簡單的小套件來說,Dart 空安全遷移 需要 1-2 個小時的工作量,但對於一個大型專案來說,這可能是一場長達數月的馬拉松。理想情況下,您希望逐步遷移您的專案——在馬拉松期間,您希望保持您的專案可擴展、可維護且易於發佈。

閱讀全文 »

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

原文:https://medium.com/dartlang/hosting-a-private-dart-package-repository-774c3c51dff9

託管私有的 Dart 套件庫

我們最近發布的 Dart 2.15 版本增加了對私有套件庫的支援。套件庫是一個託管 Dart 套件的伺服器,供 dart pub 客戶端使用。這篇文章討論了如何將私有套件庫與 pub.dev 一起使用,並利用 Dart 2.15 中引入的新的權杖驗證機制。

閱讀全文 »
0%