mirror of
				https://github.com/flame-engine/flame.git
				synced 2025-11-04 13:08:09 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			92 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			92 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
import 'dart:ui';
 | 
						|
 | 
						|
import 'package:flame/palette.dart';
 | 
						|
import 'package:flame/sprite.dart';
 | 
						|
 | 
						|
/// This allows you to create a rectangle textured with a 9-sliced image.
 | 
						|
///
 | 
						|
/// How it works is that you have a template image in a 3x3 grid, made up of 9 tiles,
 | 
						|
/// and a new rectangle can be draw by keeping the 4 corners, expanding the 4 sides only
 | 
						|
/// in the direction in which they are located and expanding the center in both directions.
 | 
						|
/// That allows you to have non distorted borders.
 | 
						|
class NineTileBox {
 | 
						|
  /// The sprite used to render the box, must be a 3x3 grid of square tiles.
 | 
						|
  Sprite sprite;
 | 
						|
 | 
						|
  /// The size of each tile in the source sprite image.
 | 
						|
  int tileSize;
 | 
						|
 | 
						|
  /// The size each tile becomes when rendered (optionally used to scale the src image).
 | 
						|
  int destTileSize;
 | 
						|
 | 
						|
  /// 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].
 | 
						|
  ///
 | 
						|
  /// 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.
 | 
						|
  ///
 | 
						|
  /// If [destTileSize] is not provided, the evaluated [tileSize] is used instead
 | 
						|
  /// (so no scaling happens).
 | 
						|
  NineTileBox(this.sprite, {int tileSize, int destTileSize}) {
 | 
						|
    this.tileSize = tileSize ?? sprite.src.width.toInt();
 | 
						|
    this.destTileSize = destTileSize ?? tileSize;
 | 
						|
  }
 | 
						|
 | 
						|
  /// Renders this nine box with the dimensions provided by [rect].
 | 
						|
  void drawRect(Canvas c, Rect rect) {
 | 
						|
    draw(c, rect.left, rect.top, rect.width, rect.height);
 | 
						|
  }
 | 
						|
 | 
						|
  /// Renders this nine box as a rectangle of coordinates ([x], [y]) and size ([width], [height]).
 | 
						|
  void draw(Canvas c, double x, double y, double width, double height) {
 | 
						|
    if (!sprite.loaded()) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    // corners
 | 
						|
    _drawTile(c, _getDest(x, y), 0, 0);
 | 
						|
    _drawTile(c, _getDest(x, y + height - destTileSize), 0, 2);
 | 
						|
    _drawTile(c, _getDest(x + width - destTileSize, y), 2, 0);
 | 
						|
    _drawTile(
 | 
						|
        c, _getDest(x + width - destTileSize, y + height - destTileSize), 2, 2);
 | 
						|
 | 
						|
    // horizontal sides
 | 
						|
    final mx = width - 2 * destTileSize;
 | 
						|
    _drawTile(c, _getDest(x + destTileSize, y, width: mx), 1, 0);
 | 
						|
    _drawTile(c,
 | 
						|
        _getDest(x + destTileSize, y + height - destTileSize, width: mx), 1, 2);
 | 
						|
 | 
						|
    // vertical sides
 | 
						|
    final my = height - 2 * destTileSize;
 | 
						|
    _drawTile(c, _getDest(x, y + destTileSize, height: my), 0, 1);
 | 
						|
    _drawTile(c,
 | 
						|
        _getDest(x + width - destTileSize, y + destTileSize, height: my), 2, 1);
 | 
						|
 | 
						|
    // center
 | 
						|
    _drawTile(
 | 
						|
        c,
 | 
						|
        _getDest(x + destTileSize, y + destTileSize, width: mx, height: my),
 | 
						|
        1,
 | 
						|
        1);
 | 
						|
  }
 | 
						|
 | 
						|
  Rect _getDest(double x, double y, {double width, double height}) {
 | 
						|
    final w = width ?? _destTileSizeDouble;
 | 
						|
    final h = height ?? _destTileSizeDouble;
 | 
						|
    return Rect.fromLTWH(x, 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, BasicPalette.white.paint);
 | 
						|
  }
 | 
						|
}
 |