前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter版合成大西瓜

Flutter版合成大西瓜

原创
作者头像
乂乂又又
修改2021-02-22 10:25:13
1.9K0
修改2021-02-22 10:25:13
举报

背景

我一直想做个小游戏,正好年前合成大西瓜火了,所以趁着这次年假,自己在家写了个plus版的合成大西瓜,前后花了大概三天三夜的时间(没错,一直写到大年三十的晚上~),现在写下这篇文章记录下这个过程。

预览

老规矩,先上图,看下这个plus版的合成大西瓜究竟长啥样😊

里面的图片素材可以自己裁剪更换,很方便。

除此之外还支持

  • 自定义背景图
  • 重力感应操控
  • 反向合成小瓜
  • 只生成小/大瓜

并且还内置了多套游戏主题(水果/表情/校徽)

这次让你轻松魔改个够😁

下载地址

网页版:http://v.idoo.top/mix

安卓/iOS:https://www.pgyer.com/Dagua

PS:iOS版安装包需要自签才能使用

开发记录

技术选型

我曾经用Flutter+Flame写过一个Forge2D的开源小游戏:《坠落》

(PS:早期作品,代码写的比较不忍直视,大佬轻喷~)

所以这次,我选择继续使用Flutter+Flame+Forge2D来开发合成大瓜.

后来证明这个选择是非常明智的:

一次开发就可以打包出Web、Android、iOS、Windows、Mac、Linux全端的安装包,非常给力!

开发环境

因为一开始我就打算支持打包成Web应用(甚至是桌面应用),所以需要先把我本地的Flutter环境从stable分支切换到dev分支

在Flutter SDK根目录执行以下命令

代码语言:txt
复制
#首先把Flutter仓库地址换成清华源到镜像地址,加速下载
git remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/flutter-sdk.git

#切换分支
flutter channel dev

#更新sdk
flutter upgrade

#开启web,desktop支持
flutter config --enable-web
flutter config --enable-macos-desktop

OK,现在我们就可以用Flutter愉快的开发web跟桌面应用了^^

代码规范

为了规范自己的代码,第一件事就是把 pedantic 加入 dependency

代码语言:txt
复制
dependencies:
  flutter:
    sdk: flutter
  pedantic: ^1.9.2

#analysis_options.yaml
include: package:pedantic/analysis_options.yaml

pedantic是谷歌内部使用的Dart代码规范,它比 Effective Dart 还要严格一些,有了它就可以安心写代码了。

图片剪裁

这里我选用的图片裁剪插件是 crop,不过它的实现方式是 RepaintBoundary ,所以这丫在Web端不能用(PC上的浏览器可以用,但是在手机上的浏览器就不支持,很迷~),所以没办法,只能退而求其次使用 image 库直接操作图片像素点裁剪图片。

代码语言:txt
复制
/// Returns a round cropped copy of [src].
Image copyCropCircle(
  Image src, {
  int radius,
  Point center,
}) {
  int min(num x, num y) => (x < y ? x : y).toInt();
  final defaultRadius = min(src.width, src.height) ~/ 2;
  radius ??= defaultRadius;
  center ??= Point(src.width ~/ 2, src.height ~/ 2);
  // Make sure center point is within the range of the src image
  center.x = center.x.clamp(0, src.width - 1).toInt();
  center.y = center.y.clamp(0, src.height - 1).toInt();
  radius = radius < 1 ? defaultRadius : radius;

  final tlx = center.x.toInt() - radius; //topLeft.x
  final tly = center.y.toInt() - radius; //topLeft.y

  var dst = Image(
    radius * 2,
    radius * 2,
    channels: Channels.rgba,
    iccp: src.iccProfile,
  );

  for (var yi = 0, sy = tly; yi < radius * 2; ++yi, ++sy) {
    for (var xi = 0, sx = tlx; xi < radius * 2; ++xi, ++sx) {
      if ((xi - radius) * (xi - radius) + (yi - radius) * (yi - radius) <=
          radius * radius) {
        dst.setPixel(xi, yi, src.getPixelSafe(sx, sy));
      }
    }
  }

  return dst;
}

条件导包

由于dart:io在web端不受支持,所以我们需要使用其它实现来替代dart:io,这就涉及到了如何在dart中实现条件导包

一个简单的文件io的例子

代码语言:txt
复制
//file/file_io.dart
import 'dart:io';
import 'dart:typed_data';

import 'package:path_provider/path_provider.dart';

class FileTool {
  static Future<Uint8List> read(String path) async {
    final directory = await getApplicationDocumentsDirectory();
    var file = File(directory.path + path);
    if (!await file.exists()) return null;
    return await file.readAsBytes();
  }

  static Future<void> write(String path, Uint8List bytes) async {
    final directory = await getApplicationDocumentsDirectory();
    var file = File(directory.path + path);
    if (!await file.exists()) {
      file = await file.create(recursive: true);
    }
    await file.writeAsBytes(bytes, flush: true);
  }

  static Future<void> delete(String path) async {
    final directory = await getApplicationDocumentsDirectory();
    var file = File(directory.path + path);
    if (!await file.exists()) return;
    file.deleteSync();
  }
}

//file/file_web.dart
import 'dart:typed_data';

import '../hive_tool.dart';
import '../image/ui_image_tool.dart';

class FileTool {
  static Future<Uint8List> read(String path) async {
    if (!HiveTool().inited) await HiveTool().init();
    final value = await HiveTool().box.get(path);
    if (value == null) return null;
    return (value as String).toBytes();
  }

  static Future<void> write(String path, Uint8List bytes) async {
    if (!HiveTool().inited) await HiveTool().init();
    await HiveTool().box.put(path, bytes.toBase64());
  }

  static Future<void> delete(String path) async {
    if (!HiveTool().inited) await HiveTool().init();
    await HiveTool().box.delete(path);
  }
}

//file_tool.dart
export 'file/file_io.dart' if (dart.library.html) 'file/file_web.dart';

更新图标

在项目根目录放入1024x1024分辨率的APP图标,命名为 logo.png

代码语言:txt
复制
dependencies:
  ...
  flutter_launcher_icons: ^0.8.1

flutter_icons:
  image_path: "logo.png"
  android: true
  ios: true

然后运行 flutter pub run flutter_launcher_icons:main 即可

开源地址

本项目开源地址 https://github.com/idootop/watermelon , 欢迎🌟/PR ^^

Web端生成

代码语言:txt
复制
flutter build web --release

Android端生成

代码语言:txt
复制
flutter build apk --split-per-abi

PS:亦可支持iOS,Mac,Windows,Linux端,请自行打包

鸣谢

Flutter https://flutter.dev/

Flame https://flame-engine.org/

Forge2D https://github.com/flame-engine/forge2d

合成大西瓜 http://www.wesane.com/game/654/

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 预览
  • 下载地址
  • 开发记录
    • 技术选型
      • 开发环境
        • 代码规范
          • 图片剪裁
            • 条件导包
              • 更新图标
              • 开源地址
              • 鸣谢
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档