Flutter game: Welcome page at startup

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/hekaiyou/article/details/96916442

The content of this article needs to be oh Upon completion of the following codes on!

Load More Resources

First, download the following to use the game resource files, as part of previously downloaded, so Here to talk about what the added content.

  • branding / title.png: game title picture, Recommendation 7: 4 size, namely 7x4 tiles
  • ui / start-button.png: button to start the game, Recommendation 2: 1 size, ie 6x3 block
  • bg / lose-splash.png: Game Over image, Recommendation 7: 5 size, namely 7x5 tiles
  • ui / dialog-credits.png: About dialog box recommendation 3: 2 size, i.e. 12x8 tile
  • ui / dialog-help.png: Help dialog box with about the same size
  • ui / icon-credits.png: About icon, it is recommended to square a block size
  • ui / icon-help.png: Help icon, the icon size on the same

Understanding of these resources are doing, they began to add the following code to the pubspec.yamlfile assetssection.

flutter:
  uses-material-design: true

  assets:
    ...
    - assets/images/bg/lose-splash.png
    - assets/images/branding/title.png
    - assets/images/ui/dialog-credits.png
    - assets/images/ui/dialog-help.png
    - assets/images/ui/icon-credits.png
    - assets/images/ui/icon-help.png
    - assets/images/ui/start-button.png

Open the main.dartfile, and just in pubspec.yamlpassing resource file to add Flame.images.loadAllthe string called ( Stringthe list).

  Flame.images.loadAll(<String>[
    ...
    'bg/lose-splash.png',
    'branding/title.png',
    'ui/dialog-credits.png',
    'ui/dialog-help.png',
    'ui/icon-credits.png',
    'ui/icon-help.png',
    'ui/start-button.png',
  ]);

This completes the pre-loading part of the game resources.

Preparation game page

A good game should have a welcome page and a page of the game, after a long game, victory or defeat but also the result of a given page, and click the Start button when the player should switch from the welcome page to the game page . So, our game should have the following three pages.

  • Welcome Page: The first time you open the game, welcome page, or call the main page, the view will be displayed in the middle of a game title, and then the bottom of the page will display the Start button.
  • Game page: This is when players play the game see page that hides the title game, and focus on the random motion of mosquitoes.
  • Failure page: When a player fails, there will be a splash page, the specific situation is when a player fails, the middle of the screen there will be a prompt splash image player game of failure, and with a start button, players can start again.

For the above three pages, display the same background, and mosquitoes are also visible, which makes players feel the game page is the main page, and welcome page is the real home page, welcome to the real guide players into the game, the last game failure after the end of the page is the player fails, the rest of the page and then start again.

To this end, we need to record the current page, where you can do this using an integer, and the page number or page can also be a string to record from 0-2.

In the Dart language, there is an enumeration ( enum) data type, just can be used to deal with this situation, we will see a page in which the player of the game enumerate or tell when the page changes to the page. Create a new lib/view.dartfile and add the following code.

enum View {
  home,
  playing,
  lost,
}

Now you need to add an instance variable for the game, it will save the value of the current page for us. So, to use it to import before the page Viewenumeration, and then add the instance variables. We named it the active page ( activeView), set the type Viewenumerated type.

Open the hit-game.dartfile and submit the following code.

...
import 'package:hello_flame/view.dart';

class HitGame extends Game {
  ...
  View activeView = View.home;

So we are ready to process each page of.

Realization welcome page

Have already simply said welcome page, and in the code, the page is just another logical similar components, can have their own sub-assemblies. It can also be virtual, no matter what the player really see the page, it is always visible.

If the welcome page, we will use the component class when defining the page, just like other components, we simply call render its instances (from the game loop render) and update ( update) method.

First, libcreate a directory viewsfolder in the directory and create views/home-view.darta file and write the following code.

import 'dart:ui';
import 'package:flame/sprite.dart';
import 'package:hello_flame/hit-game.dart';

class HomeView {
  final HitGame game;
  Rect titleRect;
  Sprite titleSprite;

  HomeView(this.game) {}

  void render(Canvas c) {}

  void update(double t) {}
}

The above code, first class and import the definition file to be used, then we define a named HomeViewclass, which has three instance variables, one of which is final, you need to transfer and assign when you create an instance of this class. Meanwhile class has a constructor and a further two methods, namely, rendering the game loop ( render) and Update ( update) method.

In the constructor initializes titleRectand titleSpritevariables so that they may render ( renderuse) method.

  HomeView(this.game) {
    titleRect = Rect.fromLTWH(
      game.tileSize,
      (game.screenSize.height / 2) - (game.tileSize * 4),
      game.tileSize * 7,
      game.tileSize * 4,
    );
    titleSprite = Sprite('branding/title.png');
  }

The above two lines, the first behavior titleRectvariable assignment, the second behavior titleSpritevariable. Wherein the titleRectvalue of a variable is a rectangle ( Rectdefined), 4 lines correspond to a plant constructor .fromLTWHparameters required.

Because we want to determine a 7×4display picture in the header of the tile, it will be game.tileSize * 7, and game.tileSize * 4transmitted to the last two parameters, these two parameters correspond to the width and height of the rectangle.

For the left ( left) parameter, from the 9width of the screen size of the tiles, the title image by subtracting the 7width of the rectangle the size of tiles can be obtained 2tiles extra space. In order to center the title image, where these 2additional tiles distributed to the left and right sides of the image shift 1tiles. So, here we introduced to game.tileSize * 1or simply pass game.tileSize.

Top ( top) parameter is different, because we do not want the title of the image in the center of the screen. To calculate the position of the center of the screen, simply by dividing the screen height 2to, subtracted from 4a tile size of the title image height, you can get the appropriate offset position of the center.

Now we initialized titleRectand titleSpritecan start writing code for displaying the actual image, rendering ( render) method, add the following code.

  void render(Canvas c) {
    titleSprite.renderRect(c, titleRect);
  }

Now open hit-game.dartthe file, and import HomeViewthe class file, and then add a HomeViewtype homeViewinstance variables. Next, the need to initialize instance variables in determining the screen size, so the call resizeafter, will initializeadd the following code methods.

...
import 'package:hello_flame/views/home-view.dart';

class HitGame extends Game {
  ...
  View activeView = View.home;
  HomeView homeView;

  ...

  void initialize() async {
    ...
    homeView = HomeView(this);
    produceFly();
  }

Finally, use on-screen rendering HomeViewrender ( render), and therefore, rendering the game class ( render) method, the last call to HomeViewrender (instance render) method, so that the final rendering.

Because the rendering of the same order of display order, because we want the background first, then the mosquito, the last is the title of the image, which will ensure that the title picture on the screen all the content is located.

  void render(Canvas canvas) {
    background.render(canvas);
    enemy.forEach((Fly fly) => fly.render(canvas));

    if (activeView == View.home) homeView.render(canvas);
  }

The above code, the first active view is determined ( activeView) is currently the main view, and if so, the rendering HomeViewinstance, if not, rendering ( render) method skips this line of code, and therefore does not present HomeViewexample.

Now run the game, you can see the results as shown in the following figure.

Here Insert Picture Description

But then, when the game was still within the page, the player still can click and get rid of mosquitoes, but that's okay, it does not have any impact on the game. Next, the player to start the game, so there must be a start button. First, create another component named StartButton, put the new components/start-button.dartfile.

import 'dart:ui';
import 'package:flame/sprite.dart';
import 'package:hello_flame/hit-game.dart';

class StartButton {
  final HitGame game;
  Rect rect;
  Sprite sprite;

  StartButton(this.game) {}

  void render(Canvas c) {}

  void update(double t) {}

  void onTapDown() {}
}

这个类定义与其他组件类大致相同,不同的是它有一个onTapDown处理程序,我们将在这里编写“开始”游戏的代码。首先在构造函数中初始化rectsprite变量。

  StartButton(this.game) {
    rect = Rect.fromLTWH(
      game.tileSize * 1.5,
      (game.screenSize.height * .75) - (game.tileSize * 1.5),
      game.tileSize * 6,
      game.tileSize * 3,
    );
    sprite = Sprite('ui/start-button.png');
  }

上面的代码与HomeView类构造函数中,标题图像的初始化基本相同。不同的是,除了6×3个图块大小外,还有左侧(left)和顶部(top)偏移。

开始按钮的宽度为6个图块,这意味着在屏幕的9个图块宽度上有3个额外的图块,这样的话,每侧都有1.5个图块,所以这里将game.tileSize * 1.5提供给左侧(left)参数。对于顶部(top)参数,这样就可以让按钮的垂直位置恰好位于屏幕高度的四分之三即0.75的位置。

在初始化rectsprite变量之后,需要渲染图像,所以要下面代码添加到render函数中。

  void render(Canvas c) {
    sprite.renderRect(c, rect);
  }

接下来需要在游戏类中添加一个StartButton组件的实例,打开hit-game.dart文件,导入依赖,然后将实例变量与其他实例变量一起添加。同时在确定屏幕大小后,使用StartButton类的新实例初始化startButton变量,并在render方法中增加下面代码。

...
import 'package:hello_flame/components/start-button.dart';

class HitGame extends Game {
  ...
  HomeView homeView;
  StartButton startButton;

  ...

  void initialize() async {
    ...
    startButton = StartButton(this);
    produceFly();
  }

  ...

  void render(Canvas canvas) {
    ...
    if (activeView == View.home || activeView == View.lost) {
      startButton.render(canvas);
    }
  }

上面代码中,我们添加的这4行代码,分别是导入StartButton类、创建StartButton类的实例并将其存储在实例变量中、最后展示StartButton到屏幕上。

现在运行游戏,可以看到开始按钮会在欢迎页面和失败页面上呈现,这样玩家就可以从欢迎页面或失败页面重新开始游戏了。

Here Insert Picture Description

处理开始按钮

在上一步中,我们让开始按钮显示在屏幕上,但是点击没有反应,不用急,接下来就开始处理开始按钮的响应逻辑。首先,需要确保点击不会穿过物体,例如在点击开始按钮(startButton)时,同一位置的蚊子不应该接收到点击事件。

在游戏类的onTapDown处理程序中创建一个isHandled变量,用于保存当前是否已调用了点击处理程序,在onTapDown处理程序的开始处创建它,并将初始值设置为false。在检查点击是否命中矩形(Rect)组件之前,先检查isHandled是否仍为false值,然后再调用组件的点击处理程序。

  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;
      }
    }

    enemy.forEach((Fly fly) {
      if (fly.flyRect.contains(d.globalPosition)) {
        fly.onTapDown();
      }
    });
  }

上面代码中,首先对isHandled进行检查,确保尚未处理点击事件,这个检查项与检查点击是否在开始按钮(startButton)的rect属性内是一起的。如果通过了这些条件的检查,再额外检查玩家是否当前处于欢迎页面或失败页面中。

只有满足所有条件,游戏才会调用开始按钮的onTapDown处理程序,变量isHandled也被设置为true,让下面的代码知道已经处理了这次的点击。接下来要做的是,使用isHandled检查把之前的蚊子点击处理程序包装起来。

  void onTapDown(TapDownDetails d) {
    ...

    if (!isHandled) {
      enemy.forEach((Fly fly) {
        if (fly.flyRect.contains(d.globalPosition)) {
          fly.onTapDown();
          isHandled = true;
        }
      });
    }
  }

上面的代码基本上与上面类似,首先包含了对isHandled的检查,这使得代码块只会没有处理开始按钮的情况下运行,其次,如果至少有一个蚊子被点击,则将isHandled变量设置为true

Next, open the components/start-button.dartfile, start coding the actual processing of the Start button click. In calling the start button onTapHandler, the game needs to be activeViewset View.playing, so here first import the definition of Viewenumeration documents. Then onTapDownthere will be the game's activeViewset to the desired value.

...
import 'package:hello_flame/view.dart';

class StartButton {
  ...

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

After running the game now, you can see clicking the Start button, header image, and the Start button are gone, into our previous game page.

Here Insert Picture Description

Guess you like

Origin blog.csdn.net/hekaiyou/article/details/96916442
Recommended