フラッターゲーム:単純なルールとページの最後

免責事項:この記事はブロガーオリジナル記事です、続くBY-SAのCC 4.0を著作権契約、複製、元のソースのリンクと、この文を添付してください。
このリンク: https://blog.csdn.net/hekaiyou/article/details/99103768

この記事の内容は、上の次のコードの完了時にああする必要があります!

ゲームの簡単なルール

ページは、障害のゲームのための条件を設定することができないあなたが作成する前に、最初のセットに、現在のプレイヤーが画面上でクリックして、蚊を逃した場合である条件です。ヒットかどうかは、蚊を打つかどうかを確認するためにクリックして、あなたは別のブール(作成する必要が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コントローラが、グラフィックをレンダリングする目的ではないためです)。今、私たちは、最後の部分を編集する必要が呼び出すメソッドを。オープンして、次のコードのハンドラ。producestartcomponents/start-button.dartonTapDown

  void onTapDown() {
    game.activeView = View.playing;
    game.produce.start();
  }

その後、ゲームを実行し、あなたは蚊が、我々が設定したルールに基づいて表示されるように見ることができます、だけでなく、故障のページになっている、あなたが正常にゲームを開始することができ、ゲームを失い、その後、ゲームを再起動します。

ここに画像を挿入説明

おすすめ

転載: blog.csdn.net/hekaiyou/article/details/99103768