flutter能开发游戏吗_Flutter Flame游戏开发上手(1)

背景

收到一个游戏开发的需求,因为双端上线所以需要支持iOS Android两端.

3个Android RD,没有接触过游戏开发,快速学习上手Flutter支持双端.

计划游戏使用Flame框架,先大题熟悉下环境然后在开发的过程中学习和解决问题.

知识点

GameLoop是什么

游戏循环就是搭建一个游戏的脚手架.大部分游戏只需要2个方法即:

render方法

用来绘制

update方法

用来更新绘制参数. update当前帧和上一帧的差异.

比如表现一个正在下坠的圆

圆的坐标用y表示. render方法负责拿着y值去绘制圆, update方法负责更新y的变化. 互相配合完成了一个圆的下坠动画

如何把一个Flutter组件展示在Frame引擎上

利用 HasWidgetsOverlay 接口.

用removeWidgetOverlay方法移出Flutter组件

用addWidgetOverlay方法添加Flutter组件

class MyGame extends BaseGame with HasWidgetsOverlay, TapDetector {

Size size;

SpriteC spriteC;

bool isPaused = false;

MyGame(this.size) {

spriteC = SpriteC.create();

}

@override

void onTap() {

super.onTap();

if (isPaused) {

removeWidgetOverlay('pausemenu');

isPaused = false;

} else {

addWidgetOverlay(

'pausemenu',

Center(

child: Container(

width: 100,

height: 100,

color: Colors.blue[300],

child: const Center(child: const Text('Pause')),

),

));

isPaused = true;

}

}

}

复制代码

如何把游戏展示在Flutter的一个组件上

Game提供一个Widget对象,可以直接获取最为Flutter的一个Widget使用.

final game = MyGame(size);

runApp(game.widget);

复制代码

Debug功能是什么

@override

bool debugMode() => true;

@override

bool recordFps() => true;

复制代码

开启Debug.

Debug就是允许调试,会自动打印组件的位置.

recordFps就是输出当前运行游戏的FPS.

组件(Components)

必要性:

就跟在Android/iOS上糊页面一样. 所有的页面,动画,特效都可以用Canvas来画, 实际上开发一般情况下用的却是ImageView,TextView,ListView这样的组件来完成. 没有人喜欢刀耕火种

组件重要方法:

除了render 和 update这种通用方法.

// 初始化

@override

void onMount() {

super.onMount();

}

// 回收前

@override

void onDestroy() {

super.onDestroy();

}

// 还没搞清楚...? 好像在说绘制的位置跟设备之间的关系

@override

bool isHud() {

return true;

}

// 标记可回收

@override

bool destroy() {

return false;

}

复制代码

怎么画帧动画

即把

变成

游戏里面的人都是会动的,所以这是一个重要知识点.

在游戏里面展示 AnimationComponent

const textureWidth = 96.0;

const textureHeight = 96.0;

add(AnimationComponent.sequenced(

textureWidth * 2,

textureHeight * 2,

'minotaur.png',

19,

textureWidth: textureWidth,

textureHeight: textureHeight,

loop: true,

stepTime: 0.15,

));

复制代码

其中函数 AnimationComponent.sequenced 的参数说明如下:

AnimationComponent.sequenced(

double width, // 展示的宽度

double height, // 展示的高度

String imagePath,

int amount, { // Sprit Sheet的帧数

int amountPerRow, // 多行切图 两行之间的间隔

double textureX = 0.0, // 展示的偏移值

double textureY = 0.0,

double textureWidth, // 切图一帧的宽度

double textureHeight, // 切图一帧的高度

double stepTime, // 播放间隔时间

bool loop = true, // 是否循环播放

this.destroyOnFinish = false, // 播放完了是否销毁

})

复制代码

提供给Flutter组件展示 AnimationWidget

await Flame.images.load('minotaur.png');

final _animationSpriteSheet = SpriteSheet(

imageName: 'minotaur.png',

columns: 19,

rows: 1,

textureWidth: 96,

textureHeight: 96,

);

_animation = _animationSpriteSheet.createAnimation(

0,

stepTime: 0.2,

to: 5,

);

// 使用

Container(

width: 200,

height: 200,

child: AnimationWidget(animation: _animation),

),

复制代码

怎么画SVG动画 SvgComponent

Svg svg = Svg('android.svg');

SvgComponent android = SvgComponent.fromSvg(100, 100, svg);

android.x = 100;

android.y = 100;

复制代码

怎么画组合控件 ComposedComponent

和原生组合控件相似的做法.

class GameOverPanel extends PositionComponent

with Resizable, HasGameRef, Tapable, ComposedComponent {

GameOverPanel(Image spriteImage) : super() {

gameOverText = GameOverText(spriteImage);

gameOverRestart = GameOverRestart(spriteImage);

components..add(gameOverText)..add(gameOverRestart);

}

bool visible = false;

GameOverText gameOverText;

GameOverRestart gameOverRestart;

@override

void render(Canvas canvas) {

if (visible) {

super.render(canvas);

}

}

}

class GameOverText extends SpriteComponent with Resizable {

GameOverText(Image spriteImage)

: super.fromSprite(

GameOverConfig.textWidth,

GameOverConfig.textHeight,

Sprite.fromImage(

spriteImage,

x: 955.0,

y: 26.0,

width: GameOverConfig.textWidth,

height: GameOverConfig.textHeight,

),

);

@override

void resize(Size size) {

if (width > size.width * 0.8) {

width = size.width * 0.8;

}

y = size.height * .25;

x = (size.width / 2) - width / 2;

}

}

class GameOverRestart extends SpriteComponent with Resizable {

GameOverRestart(Image spriteImage)

: super.fromSprite(

GameOverConfig.restartWidth,

GameOverConfig.restartHeight,

Sprite.fromImage(

spriteImage,

x: 2.0,

y: 2.0,

width: GameOverConfig.restartWidth,

height: GameOverConfig.restartHeight,

),

);

@override

void resize(Size size) {

y = size.height * .75;

x = (size.width / 2) - GameOverConfig.restartWidth / 2;

![](https://user-gold-cdn.xitu.io/2020/6/19/172c89c8d5d4aff0?w=304&h=640&f=gif&s=3257550)

}

}

复制代码

怎么绘制视差动画 ParallaxComponent

简单来说就是怎么把

组合起来生成

final images = [

ParallaxImage("bg.png"),

ParallaxImage("mountain-far.png"),

ParallaxImage("mountains.png"),

ParallaxImage("trees.png"),

ParallaxImage("foreground-trees.png"),

];

final parallaxComponent = ParallaxComponent(images,

baseSpeed: const Offset(20, 0), layerDelta: const Offset(100, 0));

复制代码

月亮&天空离我们远所以移动得慢一些

树木离我们近所以移动得快一些

组合起来很神奇,这个效果我很喜欢.TOT

怎么画可拉伸图片(Android的.9.png图) NineTileBox

如下例:

// 定义

final sprite = Sprite('nine-box.png');

nineTileBox = NineTileBox(sprite, tileSize: 8, destTileSize: 24);

// 使用

nineTileBox.draw(canvas, x, y, 200, 500);

复制代码

两个角各占4个像素,合起来就是8个像素, 图片总共24个像素. 这就是上面得参数得含义.

UE切图的话需要保持图片尺寸是3的倍数,另外这里比起.9.png有个缺点是他必须保证4个角是对称的. 对于非对称,比如上面8个像素 下面只需要4个像素的图片不支持.

物理引擎 Box2DComponent

Flame支持Box2D.即组件 Box2DComponent.我理解就是可以实现物理体积 和 碰撞的能力.

这是一个很Powerful得组件,应该会有些深度,需要后面花时间仔细研究下.这里先熟悉他的作用范围就行.

网站:box2d.org/

Box2D是一款免费的开源二维物理引擎,由Erin Catto使用C++编写,在zlib授权下发布。它已被用于蜡笔物理学、愤怒的小鸟、地狱边境、Rolando、Fantastic ...

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[Flutter Flame游戏开发上手(1)]http://www.zyiz.net/tech/detail-140359.html

你可能感兴趣的:(flutter能开发游戏吗)