この記事の内容は、上の次のコードの完了時にああする必要があります!
- 「フラッターはそれでゲームを開始します。」
- 「フラッターゲーム:重力の法則。」
- 「フラッターゲーム:ゴミが誕生モスキートを与えるだろう」
- 「フラッターゲーム:蚊が飛んで。」
- 「フラッターゲーム:起動時にWelcomeページ。」
ゲームの簡単なルール
ページは、障害のゲームのための条件を設定することができないあなたが作成する前に、最初のセットに、現在のプレイヤーが画面上でクリックして、蚊を逃した場合である条件です。ヒットかどうかは、蚊を打つかどうかを確認するためにクリックして、あなたは別のブール(作成する必要がbool
ヒットする前に定義するかどうかを持続します)変数を。
オープンhit-game.dart
や蚊をループする前に、didHitAFly
上の変数宣言onTapDown
ハンドラ。ループ・フィルタの蚊は、追加しながらif
ブロックを、それがクリック蚊かどうかがチェックされます。次にforEach
ループの後に、その後、ゲーム内の現在のページかどうかを確認し、クリックされた蚊場合。
void onTapDown(TapDownDetails d) {
bool isHandled = false;
if (!isHandled && startButton.rect.contains(d.globalPosition)) {
if (activeView == View.home || activeView == View.lost) {
startButton.onTapDown();
isHandled = true;
}
}
if (!isHandled) {
bool didHitAFly = false;
enemy.forEach((Fly fly) {
if (fly.flyRect.contains(d.globalPosition)) {
fly.onTapDown();
isHandled = true;
didHitAFly = true;
}
});
if (activeView == View.playing && !didHitAFly) {
activeView = View.lost;
}
}
}
上記のコードでの最初のif
ページはゲームであり、第二あれば蚊をヒットしない場合は、まず、二つのことで文をチェックします。これらの2つの条件が満たされている場合、それがされますactiveView
に設定されView.lost
、障害のページに対応する値。
今、プレイヤーが蚊をヒットしていない場合は、[スタート]ボタンが画面に表示されます、あなたは見つけるでしょう、ゲームを実行します。(レンダリングする前に覚えているrender
のウェルカムページまたはページは[スタート]ボタンを表示する際の方法が唯一の失敗しません)。だから今タイトル画像で何も表示がありません、どのページで確認できます。
ページを達成するために失敗
失敗ウェルカムページとページは基本的に同じである、唯一の違いは、表示画像はタイトルが、他の画像ではないです。新しい作成しviews/lost-view.dart
たファイルを、次のコードを入力してください。
import 'dart:ui';
import 'package:flame/sprite.dart';
import 'package:hello_flame/hit-game.dart';
class LostView {
final HitGame game;
Rect rect;
Sprite sprite;
LostView(this.game) {
rect = Rect.fromLTWH(
game.tileSize,
(game.screenSize.height / 2) - (game.tileSize * 5),
game.tileSize * 7,
game.tileSize * 5,
);
sprite = Sprite('bg/lose-splash.png');
}
void render(Canvas c) {
sprite.renderRect(c, rect);
}
void update(double t) {}
}
上記のコードと同じ基本的なウェルカムページ異なるスプライト(あるSprite
画像ファイルのファイル名、ならびに像高をロードする)である5
タイル。そしてウェルカムページ、ゲームクラス開く必要hit-game.dart
、ファイルを作成しLostView
たクラスのインスタンスを、それをレンダリングします。
hit-game.dart
インポートファイルのviews/lost-view.dart
ファイル、次に作成lostView
インスタンス変数およびインスタンス化LostView
オブジェクトを、そしてそれを割り当てるinitialize
方法のlostView
変数、そして最後に、レンダリング(render
それをレンダリングする)方法。
...
import 'package:hello_flame/views/lost-view.dart';
class HitGame extends Game {
...
LostView lostView;
...
void initialize() async {
...
lostView = LostView(this);
produceFly();
}
...
void render(Canvas canvas) {
...
if (activeView == View.home) homeView.render(canvas);
if (activeView == View.lost) lostView.render(canvas);
if (activeView == View.home || activeView == View.lost) {
startButton.render(canvas);
}
}
...
}
上記のコード、およびベースは同じゲームにWelcomeページのカテゴリに追加される前に。今すぐゲームを実行し、[スタート]ボタンをクリックし、位置に何の蚊の画面をクリックしていない、あなたはこのゲームがページを失敗し、画面に表示されるはずです。
ゲームコントローラ
前のセクションでは、いくつかの記載されたエラー現在のゲームがあり、蚊一の実施形態では、それは二つの側面を有し、技術の観点から、場合forEach
関数リストループ(List
)、コードリストがこれに、修正されるべきであるれていません項目を追加したり、項目を削除します。
使用して、ヒット蚊かどうかを確認するforEach
プレイヤーが蚊をヒットした場合、すべての蚊をループし、我々のコードは、別の蚊を生成します。我々はすでに蚊、追加したときので、forEach
非常に奇妙なエラーが発生し、同時変更リストの場合に登場循環を、。
これは蚊、蚊が時間通りにではなく、プレーヤーの手の速度の生産に基づくべきであるとき論理質問自体を生成することである、ミスのゲームではありません。だから、今、私たちは生産コントローラを作成する必要があり、コントローラは見えないコンポーネントです。
新しい作成しlib/controllers
たフォルダを、この中に新しいフォルダを作成しcontrollers/producer.dart
、ファイル、および以下のコードを記述します。
import 'package:hello_flame/hit-game.dart';
class FlyProducer {
final HitGame game;
FlyProducer(this.game) {}
void start() {}
void killAll() {}
void update(double t) {}
}
上面的代码,还是熟悉的组件结构,唯一的区别是没有渲染(render
)方法,因为这个组件是一个控制器,在屏幕上没有图形表示。与其他组件和页面一样,在最终(final
)变量game
中保留对HitGame
实例的引用,并且将此变量的值作为构造函数的参数。
首先编写killAll
方法,因为下面会访问Fly
类,所以需要先导入它。然后循环游戏enemy
列表中的所有蚊子,并将true
值分配到其isDead
属性,从而有效的干掉所有蚊子。先添加几个最终(final
)实例变量到类中,然后紧接着上面再添加两个变量。
然后开始编写start
方法的内容,每次玩家点击开始按钮时都会调用此方法。,。
class FlyProducer {
final HitGame game;
final int maxProducerInterval = 3000;
final int minProducerInterval = 250;
final int intervalChange = 3;
final int maxProducerOnScreen = 7;
int currentInterval;
int nextProducer;
FlyProducer(this.game) {}
void start() {
killAll();
currentInterval = maxProducerInterval;
nextProducer = DateTime.now().millisecondsSinceEpoch + currentInterval;
}
上面代码中,从第1个常量maxProducerInterval
开始,这个实例变量控制何时产生蚊子的上限,游戏开始时,currentInterval
设置为maxProducerInterval
的值,这是设置成3000
毫秒。第2个常量minProducerInterval
与此完全相反,每次产生蚊子时的时间下限,使currentInterval
变量最多也只会减少250
毫秒。
第3个常量intervalChange
是每次生成蚊子时,从实例变量currentInterval
中减少的量。因此,从3000
毫秒开始,每生成一个蚊子,产生的速度就越来越快,直到它下降到250
毫秒为止。
第4个常量maxProducerOnScreen
的作用是,即使游戏在产生蚊子的过程中达到最快的速度,只要当前屏幕上已经有7
只蚊子活着并飞来飞去,就不会再产生蚊子。
第5个实例变量currentInterval
存储的内容是下一个生成蚊子时,从当前添加的时间量。最后一个变量nextProducer
是为下一次生产蚊子的实际时间。
在start
方法中,首先通过调用killAll()
方法来杀死所有蚊子,然后将currentInterval
重置为最大值(maxProducerInterval
)并在下一行使用此值,最后使用DateTime.now().millisecondsSinceEpoch
和添加的currentInterval
值来安排下一次的生产。
接下来在构造函数中,添加以下代码。
FlyProducer(this.game) {
start();
game.produceFly();
}
上面代码中,第1行将安排在创建此控制器的实例3
秒后生成一个蚊子,第2行只产生一只蚊子。按照这个顺序完成是因为假如先产生一个Fly
对象,start()
将调用killAll()
并且只会杀死所生成的第一个Fly
对象。
接下来在更新(update
)方法中,将会添加大量的生产逻辑,将以下代码块添加到更新(update
)方法中。
void update(double t) {
int nowTimestamp = DateTime.now().millisecondsSinceEpoch;
int livingFly = 0;
game.enemy.forEach((Fly fly) {
if (!fly.isDead) livingFly += 1;
});
if (nowTimestamp >= nextProducer && livingFly < maxProducerOnScreen) {
game.produceFly();
if (currentInterval > minProducerInterval) {
currentInterval -= intervalChange;
currentInterval -= (currentInterval * .02).toInt();
}
nextProducer = nowTimestamp + currentInterval;
}
}
上面的代码中,第1行代码存储当前时间,单位是毫秒。下一个代码块计算列表(game.enemy
)中还有效的蚊子数量,代码只是循环遍历列表,如果蚊子没有死,就向livingFly
添加1
。
接下来是一个更大的代码块,进入if
块判断当前时间是否已经过了nextProducer
值,以及幸存蚊子的数量是否小于maxProducerOnScreen
常量。如果满足条件,就会产生一只蚊子。之后,只有当currentInterval
高于最小间隔(minProducerInterval
)时,才会将currentInterval
的值减去intervalChange
常量中的值,再加上currentInterval
值的2%
。
最后1行代码仍然在上面的代码快内,使用当前时间安排下一个生产时间,并添加currentInterval
的值。
到这里为止,我们的controllers/producer.dart
里面应该有以下代码。
import 'package:hello_flame/hit-game.dart';
import 'package:hello_flame/components/fly.dart';
class FlyProducer {
final HitGame game;
final int maxProducerInterval = 3000;
final int minProducerInterval = 250;
final int intervalChange = 3;
final int maxProducerOnScreen = 7;
int currentInterval;
int nextProducer;
FlyProducer(this.game) {
start();
game.produceFly();
}
void start() {
killAll();
currentInterval = maxProducerInterval;
nextProducer = DateTime.now().millisecondsSinceEpoch + currentInterval;
}
void killAll() {
game.enemy.forEach((Fly fly) => fly.isDead = true);
}
void update(double t) {
int nowTimestamp = DateTime.now().millisecondsSinceEpoch;
int livingFly = 0;
game.enemy.forEach((Fly fly) {
if (!fly.isDead) livingFly += 1;
});
if (nowTimestamp >= nextProducer && livingFly < maxProducerOnScreen) {
game.produceFly();
if (currentInterval > minProducerInterval) {
currentInterval -= intervalChange;
currentInterval -= (currentInterval * .02).toInt();
}
nextProducer = nowTimestamp + currentInterval;
}
}
}
集成游戏控制
私たちは、ゲームに統合され、トップクラスの生産コントローラに作成したい、最初のステップはであるhit-game.dart
、削除initialize
次の行法を削除する前に、produceFly
メソッドと呼ばれるが。
void initialize() async {
enemy = List<Fly>();
rnd = Random();
resize(await Flame.util.initialDimensions());
background = Backyard(this);
homeView = HomeView(this);
startButton = StartButton(this);
lostView = LostView(this);
// 删除内容
// produceFly();
}
その後、components/fly.dart
削除onTapDown
ハンドラの使用game. produceFly()
方法を。
void onTapDown() {
isDead = true;
// 删除内容
// game.produceFly();
}
戻るhit-game.dart
、生産コントローラのインスタンスを作成し、インスタンス変数に格納します。ファーストクラスを導入して、インスタンス変数を作成produce
し、次にinitialize
作成し、インスタンス変数に格納されたプロセス・インスタンス、そして最後に更新メソッドを呼び出すproduceFly
クラスの更新方法を。
...
import 'package:hello_flame/controllers/producer.dart';
class HitGame extends Game {
...
FlyProducer produce;
...
void initialize() async {
...
background = Backyard(this);
produce = FlyProducer(this);
homeView = HomeView(this);
...
}
void update(double t) {
produce.update(t);
enemy.forEach((Fly fly) => fly.update(t));
enemy.removeWhere((Fly fly) => fly.isOffScreen);
}
...
ゲームサイクル差のコンポーネントとコントローラの間で使用されるコントローラは、メインメソッドが(更新することである呼び出すことであるupdate
コントローラが、グラフィックをレンダリングする目的ではないためです)。今、私たちは、最後の部分を編集する必要が呼び出すメソッドを。オープンして、次のコードのハンドラ。produce
start
components/start-button.dart
onTapDown
void onTapDown() {
game.activeView = View.playing;
game.produce.start();
}
その後、ゲームを実行し、あなたは蚊が、我々が設定したルールに基づいて表示されるように見ることができます、だけでなく、故障のページになっている、あなたが正常にゲームを開始することができ、ゲームを失い、その後、ゲームを再起動します。