mirror of
https://github.com/flame-engine/flame.git
synced 2025-10-30 00:17:20 +08:00
refactor: Use canvas.drawImageNine in NineTileBox (#1314)
`canvas.drawImageNine` is built-in now a lot of logic was removed from NineTileBox.
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 205 B After Width: | Height: | Size: 460 B |
@ -1,7 +1,6 @@
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:flame/game.dart';
|
||||
import 'package:flame/input.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class NineTileBoxExample extends FlameGame with TapDetector, DoubleTapDetector {
|
||||
static const String description = '''
|
||||
@ -10,30 +9,31 @@ class NineTileBoxExample extends FlameGame with TapDetector, DoubleTapDetector {
|
||||
Tap to make the box bigger and double tap to make it smaller.
|
||||
''';
|
||||
|
||||
late NineTileBox nineTileBox;
|
||||
final Vector2 boxSize = Vector2.all(300);
|
||||
late NineTileBoxComponent nineTileBoxComponent;
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
await super.onLoad();
|
||||
final sprite = Sprite(await images.load('nine-box.png'));
|
||||
nineTileBox = NineTileBox(sprite, tileSize: 8, destTileSize: 24);
|
||||
}
|
||||
|
||||
@override
|
||||
void render(Canvas canvas) {
|
||||
super.render(canvas);
|
||||
final position = (size - boxSize) / 2;
|
||||
nineTileBox.draw(canvas, position, boxSize);
|
||||
final boxSize = Vector2.all(300);
|
||||
final nineTileBox = NineTileBox(sprite, destTileSize: 148);
|
||||
add(
|
||||
nineTileBoxComponent = NineTileBoxComponent(
|
||||
nineTileBox: nineTileBox,
|
||||
position: size / 2,
|
||||
size: boxSize,
|
||||
anchor: Anchor.center,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onTap() {
|
||||
boxSize.scale(1.2);
|
||||
nineTileBoxComponent.scale.scale(1.2);
|
||||
}
|
||||
|
||||
@override
|
||||
void onDoubleTap() {
|
||||
boxSize.scale(0.8);
|
||||
nineTileBoxComponent.scale.scale(0.8);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,9 +6,9 @@ Widget nineTileBoxBuilder(DashbookContext ctx) {
|
||||
return Container(
|
||||
width: ctx.numberProperty('width', 200),
|
||||
height: ctx.numberProperty('height', 200),
|
||||
child: NineTileBox.asset(
|
||||
child: NineTileBoxWidget.asset(
|
||||
path: 'nine-box.png',
|
||||
tileSize: 8,
|
||||
tileSize: 22,
|
||||
destTileSize: 50,
|
||||
child: const Center(
|
||||
child: Text(
|
||||
|
||||
@ -15,19 +15,22 @@ class NineTileBox {
|
||||
static final _whitePaint = BasicPalette.white.paint();
|
||||
|
||||
/// The sprite used to render the box, must be a 3x3 grid of square tiles.
|
||||
Sprite sprite;
|
||||
final Sprite sprite;
|
||||
|
||||
/// The size of each tile in the source sprite image.
|
||||
int tileSize;
|
||||
final int tileSize;
|
||||
|
||||
/// The size each tile becomes when rendered
|
||||
/// (optionally used to scale the src image).
|
||||
late int destTileSize;
|
||||
|
||||
late final Rect _center;
|
||||
late final Rect _dst;
|
||||
|
||||
/// Creates a nine-box instance.
|
||||
///
|
||||
/// [sprite] is the 3x3 grid and [tileSize] is the size of each tile.
|
||||
/// The src sprite must a square of size 3*[tileSize].
|
||||
/// The src sprite must be a square of size 3*[tileSize].
|
||||
///
|
||||
/// If [tileSize] is not provided, the width of the sprite is assumed as the
|
||||
/// size. Otherwise the width and height properties of the sprite are ignored.
|
||||
@ -35,61 +38,25 @@ class NineTileBox {
|
||||
/// If [destTileSize] is not provided, the evaluated [tileSize] is used
|
||||
/// instead (so no scaling happens).
|
||||
NineTileBox(this.sprite, {int? tileSize, int? destTileSize})
|
||||
: tileSize = tileSize ?? sprite.src.width.toInt() {
|
||||
: tileSize = tileSize ?? sprite.src.width ~/ 3 {
|
||||
this.destTileSize = destTileSize ?? this.tileSize;
|
||||
final centerEdge = this.tileSize.toDouble();
|
||||
_center = Rect.fromLTWH(centerEdge, centerEdge, centerEdge, centerEdge);
|
||||
_dst = Rect.fromLTWH(0, 0, this.destTileSize * 3, this.destTileSize * 3);
|
||||
}
|
||||
|
||||
/// Renders this nine box with the dimensions provided by [rect].
|
||||
void drawRect(Canvas c, Rect rect) {
|
||||
final position = Vector2(rect.left, rect.top);
|
||||
final size = Vector2(rect.width, rect.height);
|
||||
draw(c, position, size);
|
||||
/// Renders this nine box with the dimensions provided by [dst].
|
||||
void drawRect(Canvas c, [Rect? dst]) {
|
||||
c.drawImageNine(sprite.image, _center, dst ?? _dst, _whitePaint);
|
||||
}
|
||||
|
||||
/// Renders this nine box as a rectangle at [position] with size [size].
|
||||
void draw(Canvas c, Vector2 position, Vector2 size) {
|
||||
// corners
|
||||
_drawTile(c, _getDest(position), 0, 0);
|
||||
final bottomLeft = position + Vector2(0, size.y - destTileSize);
|
||||
_drawTile(c, _getDest(bottomLeft), 0, 2);
|
||||
final topRight = position + Vector2(size.x - destTileSize, 0);
|
||||
_drawTile(c, _getDest(topRight), 2, 0);
|
||||
final bottomRight = Vector2(topRight.x, bottomLeft.y);
|
||||
_drawTile(c, _getDest(bottomRight), 2, 2);
|
||||
|
||||
// horizontal sides
|
||||
final mx = size.x - 2 * destTileSize;
|
||||
final middleLeft = position + Vector2Extension.fromInts(destTileSize, 0);
|
||||
_drawTile(c, _getDest(middleLeft, width: mx), 1, 0);
|
||||
final middleRight = middleLeft + Vector2(0, size.y - destTileSize);
|
||||
_drawTile(c, _getDest(middleRight, width: mx), 1, 2);
|
||||
|
||||
// vertical sides
|
||||
final my = size.y - 2 * destTileSize;
|
||||
final topCenter = position + Vector2Extension.fromInts(0, destTileSize);
|
||||
_drawTile(c, _getDest(topCenter, height: my), 0, 1);
|
||||
final bottomCenter = topCenter + Vector2(size.x - destTileSize, 0);
|
||||
_drawTile(c, _getDest(bottomCenter, height: my), 2, 1);
|
||||
|
||||
// center
|
||||
final center = position + Vector2.all(destTileSize.toDouble());
|
||||
_drawTile(c, _getDest(center, width: mx, height: my), 1, 1);
|
||||
}
|
||||
|
||||
Rect _getDest(Vector2 position, {double? width, double? height}) {
|
||||
final w = width ?? _destTileSizeDouble;
|
||||
final h = height ?? _destTileSizeDouble;
|
||||
return Rect.fromLTWH(position.x, position.y, w, h);
|
||||
}
|
||||
|
||||
double get _tileSizeDouble => tileSize.toDouble();
|
||||
|
||||
double get _destTileSizeDouble => destTileSize.toDouble();
|
||||
|
||||
void _drawTile(Canvas c, Rect dest, int i, int j) {
|
||||
final xSrc = sprite.src.left + _tileSizeDouble * i;
|
||||
final ySrc = sprite.src.top + _tileSizeDouble * j;
|
||||
final src = Rect.fromLTWH(xSrc, ySrc, _tileSizeDouble, _tileSizeDouble);
|
||||
c.drawImageRect(sprite.image, src, dest, _whitePaint);
|
||||
c.drawImageNine(
|
||||
sprite.image,
|
||||
_center,
|
||||
Rect.fromLTWH(position.x, position.y, size.x, size.y),
|
||||
_whitePaint,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import '../../assets.dart';
|
||||
import '../../flame.dart';
|
||||
import '../extensions/vector2.dart';
|
||||
import '../nine_tile_box.dart' as non_widget;
|
||||
import '../sprite.dart';
|
||||
import 'base_future_builder.dart';
|
||||
|
||||
@ -15,117 +16,32 @@ class _Painter extends CustomPainter {
|
||||
final ui.Image image;
|
||||
final double tileSize;
|
||||
final double destTileSize;
|
||||
late final non_widget.NineTileBox _nineTileBox;
|
||||
|
||||
_Painter({
|
||||
required this.image,
|
||||
required this.tileSize,
|
||||
required this.destTileSize,
|
||||
});
|
||||
|
||||
Sprite _getSpriteTile(double x, double y) =>
|
||||
Sprite(image, srcPosition: Vector2(x, y), srcSize: Vector2.all(tileSize));
|
||||
}) : _nineTileBox = non_widget.NineTileBox(
|
||||
Sprite(image),
|
||||
tileSize: tileSize.toInt(),
|
||||
destTileSize: destTileSize.toInt(),
|
||||
);
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final topLeftCorner = _getSpriteTile(0, 0);
|
||||
final topRightCorner = _getSpriteTile(tileSize * 2, 0);
|
||||
|
||||
final bottomLeftCorner = _getSpriteTile(0, 2 * tileSize);
|
||||
final bottomRightCorner = _getSpriteTile(tileSize * 2, 2 * tileSize);
|
||||
|
||||
final topSide = _getSpriteTile(tileSize, 0);
|
||||
final bottomSide = _getSpriteTile(tileSize, tileSize * 2);
|
||||
|
||||
final leftSide = _getSpriteTile(0, tileSize);
|
||||
final rightSide = _getSpriteTile(tileSize * 2, tileSize);
|
||||
|
||||
final middle = _getSpriteTile(tileSize, tileSize);
|
||||
|
||||
final horizontalWidget = size.width - destTileSize * 2;
|
||||
final verticalHeight = size.height - destTileSize * 2;
|
||||
|
||||
void render(Sprite sprite, double x, double y, double w, double h) {
|
||||
sprite.render(canvas, position: Vector2(x, y), size: Vector2(w, h));
|
||||
}
|
||||
|
||||
// Middle
|
||||
render(
|
||||
middle,
|
||||
destTileSize,
|
||||
destTileSize,
|
||||
horizontalWidget,
|
||||
verticalHeight,
|
||||
);
|
||||
|
||||
// Top and bottom side
|
||||
render(
|
||||
topSide,
|
||||
destTileSize,
|
||||
0,
|
||||
horizontalWidget,
|
||||
destTileSize,
|
||||
);
|
||||
render(
|
||||
bottomSide,
|
||||
destTileSize,
|
||||
size.height - destTileSize,
|
||||
horizontalWidget,
|
||||
destTileSize,
|
||||
);
|
||||
|
||||
// Left and right side
|
||||
render(
|
||||
leftSide,
|
||||
0,
|
||||
destTileSize,
|
||||
destTileSize,
|
||||
verticalHeight,
|
||||
);
|
||||
render(
|
||||
rightSide,
|
||||
size.width - destTileSize,
|
||||
destTileSize,
|
||||
destTileSize,
|
||||
verticalHeight,
|
||||
);
|
||||
|
||||
// Corners
|
||||
render(
|
||||
topLeftCorner,
|
||||
0,
|
||||
0,
|
||||
destTileSize,
|
||||
destTileSize,
|
||||
);
|
||||
render(
|
||||
topRightCorner,
|
||||
size.width - destTileSize,
|
||||
0,
|
||||
destTileSize,
|
||||
destTileSize,
|
||||
);
|
||||
render(
|
||||
bottomLeftCorner,
|
||||
0,
|
||||
size.height - destTileSize,
|
||||
destTileSize,
|
||||
destTileSize,
|
||||
);
|
||||
render(
|
||||
bottomRightCorner,
|
||||
size.width - destTileSize,
|
||||
size.height - destTileSize,
|
||||
destTileSize,
|
||||
destTileSize,
|
||||
);
|
||||
_nineTileBox.drawRect(canvas, Offset.zero & size);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(_) => false;
|
||||
}
|
||||
|
||||
@Deprecated('Renamed to [NineTileBoxWidget]')
|
||||
typedef NineTileBox = NineTileBoxWidget;
|
||||
|
||||
/// A [StatelessWidget] that renders NineTileBox
|
||||
class NineTileBox extends StatelessWidget {
|
||||
class NineTileBoxWidget extends StatelessWidget {
|
||||
final Future<ui.Image> Function() _imageFuture;
|
||||
|
||||
/// The size of the tile on the image
|
||||
@ -144,7 +60,7 @@ class NineTileBox extends StatelessWidget {
|
||||
/// A builder function that is called while the loading is on the way
|
||||
final WidgetBuilder? loadingBuilder;
|
||||
|
||||
NineTileBox({
|
||||
NineTileBoxWidget({
|
||||
required ui.Image image,
|
||||
required this.tileSize,
|
||||
required this.destTileSize,
|
||||
@ -157,7 +73,7 @@ class NineTileBox extends StatelessWidget {
|
||||
}) : _imageFuture = (() => Future.value(image)),
|
||||
super(key: key);
|
||||
|
||||
NineTileBox.asset({
|
||||
NineTileBoxWidget.asset({
|
||||
required String path,
|
||||
required this.tileSize,
|
||||
required this.destTileSize,
|
||||
|
||||
Reference in New Issue
Block a user