LCOV - code coverage report
Current view: top level - lib/src/components - isometric_tile_map_component.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 48 0.0 %
Date: 2021-08-10 15:50:53 Functions: 0 0 -

          Line data    Source code
       1             : import 'dart:ui';
       2             : 
       3             : import '../extensions/vector2.dart';
       4             : import '../spritesheet.dart';
       5             : import 'position_component.dart';
       6             : 
       7             : /// This is just a pair of <int, int>.
       8             : ///
       9             : /// Represents a position in a matrix, or in this case, on the tilemap.
      10             : class Block {
      11             :   /// x and y coordinates on the matrix
      12             :   int x, y;
      13             : 
      14           0 :   Block(this.x, this.y);
      15             : 
      16           0 :   @override
      17           0 :   String toString() => '($x, $y)';
      18             : }
      19             : 
      20             : /// This component renders a tilemap, represented by an int matrix, given a
      21             : /// tileset, in which the integers are the block ids.
      22             : ///
      23             : /// It can change the scale of each block by using the optional destTileSize
      24             : /// property.
      25             : class IsometricTileMapComponent extends PositionComponent {
      26             :   /// This is the tileset that will be used to render this map.
      27             :   SpriteSheet tileset;
      28             : 
      29             :   /// The positions of each block will be placed respecting this matrix.
      30             :   List<List<int>> matrix;
      31             : 
      32             :   /// Optionally provide a new tile size to render it scaled.
      33             :   Vector2? destTileSize;
      34             : 
      35             :   /// This is the vertical height of each block in the tile set.
      36             :   ///
      37             :   /// Note: this must be measured in the destination space.
      38             :   double? tileHeight;
      39             : 
      40           0 :   IsometricTileMapComponent(
      41             :     this.tileset,
      42             :     this.matrix, {
      43             :     this.destTileSize,
      44             :     this.tileHeight,
      45             :     Vector2? position,
      46             :     int? priority,
      47           0 :   }) : super(position: position, priority: priority);
      48             : 
      49             :   /// This is the size the tiles will be drawn (either original or overwritten).
      50           0 :   Vector2 get effectiveTileSize => destTileSize ?? tileset.srcSize;
      51             : 
      52             :   /// This is the vertical height of each block; by default it's half the tile size.
      53           0 :   double get effectiveTileHeight => tileHeight ?? (effectiveTileSize.x / 2);
      54             : 
      55           0 :   @override
      56             :   void render(Canvas c) {
      57           0 :     super.render(c);
      58             : 
      59           0 :     final size = effectiveTileSize;
      60           0 :     for (var i = 0; i < matrix.length; i++) {
      61           0 :       for (var j = 0; j < matrix[i].length; j++) {
      62           0 :         final element = matrix[i][j];
      63           0 :         if (element != -1) {
      64           0 :           final sprite = tileset.getSpriteById(element);
      65           0 :           final p = getBlockPositionInts(j, i);
      66           0 :           sprite.render(c, position: p, size: size);
      67             :         }
      68             :       }
      69             :     }
      70             :   }
      71             : 
      72             :   /// Get the position in which a block must be in the isometric space.
      73             :   ///
      74             :   /// This does not include the (x,y) PositionComponent offset!
      75           0 :   Vector2 getBlockPosition(Block block) {
      76           0 :     return getBlockPositionInts(block.x, block.y);
      77             :   }
      78             : 
      79           0 :   Vector2 getBlockPositionInts(int i, int j) {
      80           0 :     final halfTile = effectiveTileSize / 2;
      81           0 :     final pos = Vector2(i.toDouble(), j.toDouble())..multiply(halfTile);
      82           0 :     return cartToIso(pos) - halfTile;
      83             :   }
      84             : 
      85             :   /// Converts a coordinate from the isometric space to the cartesian space.
      86           0 :   Vector2 isoToCart(Vector2 p) {
      87           0 :     final x = (2 * p.y + p.x) / 2;
      88           0 :     final y = (2 * p.y - p.x) / 2;
      89           0 :     return Vector2(x, y);
      90             :   }
      91             : 
      92             :   /// Converts a coordinate from the cartesian space to the isometric space.
      93           0 :   Vector2 cartToIso(Vector2 p) {
      94           0 :     final x = p.x - p.y;
      95           0 :     final y = (p.x + p.y) / 2;
      96           0 :     return Vector2(x, y);
      97             :   }
      98             : 
      99             :   /// Get what block is at isometric position p.
     100             :   ///
     101             :   /// This can be used to handle clicks or hovers.
     102           0 :   Block getBlock(Vector2 p) {
     103           0 :     final halfTile = effectiveTileSize / 2;
     104           0 :     final multiplier = 1 - halfTile.y / (2 * effectiveTileHeight);
     105           0 :     final delta = halfTile.clone()..multiply(Vector2(1, multiplier));
     106           0 :     final cart = isoToCart(p - position + delta);
     107           0 :     final px = (cart.x / halfTile.x - 1).ceil();
     108           0 :     final py = (cart.y / halfTile.y).ceil();
     109           0 :     return Block(px, py);
     110             :   }
     111             : 
     112           0 :   void setBlockValue(Block pos, int block) {
     113           0 :     matrix[pos.y][pos.x] = block;
     114             :   }
     115             : 
     116           0 :   int blockValue(Block pos) {
     117           0 :     return matrix[pos.y][pos.x];
     118             :   }
     119             : 
     120             :   /// Return whether the matrix contains a block in its bounds.
     121           0 :   bool containsBlock(Block block) {
     122           0 :     return block.y >= 0 &&
     123           0 :         block.y < matrix.length &&
     124           0 :         block.x >= 0 &&
     125           0 :         block.x < matrix[block.y].length;
     126             :   }
     127             : }

Generated by: LCOV version 1.15