From 30d589395f3edabbc088277317891f934e2453ef Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Sun, 4 Feb 2024 17:48:49 +0100 Subject: [PATCH 1/3] refactor: Minimize `Vector2` creation in `IsometricTileMapComponent` --- .../isometric_tile_map_component.dart | 56 +++++++++++++------ .../flame/lib/src/extensions/vector2.dart | 6 ++ 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/packages/flame/lib/src/components/isometric_tile_map_component.dart b/packages/flame/lib/src/components/isometric_tile_map_component.dart index 4c1a3cbae9a..728fc001c2a 100644 --- a/packages/flame/lib/src/components/isometric_tile_map_component.dart +++ b/packages/flame/lib/src/components/isometric_tile_map_component.dart @@ -90,10 +90,10 @@ class IsometricTileMapComponent extends PositionComponent { final element = matrix[i][j]; if (element != -1) { _renderSprite = tileset.getSpriteById(element); - final p = getBlockRenderPositionInts(j, i); + final blockPosition = getBlockRenderPositionInts(j, i); _renderSprite.render( canvas, - position: p, + position: blockPosition, size: size, ); } @@ -110,15 +110,21 @@ class IsometricTileMapComponent extends PositionComponent { return getBlockRenderPositionInts(block.x, block.y); } + final Vector2 _blockRenderPositionCache = Vector2.zero(); + final Vector2 _cartesianPositionCache = Vector2.zero(); + /// Same as getBlockRenderPosition but the arguments are exploded as integers. Vector2 getBlockRenderPositionInts(int i, int j) { - final halfTile = Vector2( - effectiveTileSize.x / 2, - (effectiveTileSize.y / 2) / scalingFactor, - )..multiply(scale); - final cartesianPosition = Vector2(i.toDouble(), j.toDouble()) + final halfTile = _blockRenderPositionCache + ..setValues( + effectiveTileSize.x / 2, + (effectiveTileSize.y / 2) / scalingFactor, + ) + ..multiply(scale); + final cartesianPosition = _cartesianPositionCache + ..setValues(i.toDouble(), j.toDouble()) ..multiply(halfTile); - return cartToIso(cartesianPosition) - halfTile; + return cartToIso(cartesianPosition)..sub(halfTile); } /// Get the position of the center of the surface of the isometric tile in @@ -127,10 +133,11 @@ class IsometricTileMapComponent extends PositionComponent { /// This is the opposite of [getBlock]. Vector2 getBlockCenterPosition(Block block) { final tile = effectiveTileSize; - final result = getBlockRenderPosition(block) + - (Vector2(tile.x / 2, tile.y - effectiveTileHeight - tile.y / 4) - ..multiply(scale)); - return result; + return getBlockRenderPosition(block) + ..addValues( + (tile.x / 2) * scale.x, + (tile.y - effectiveTileHeight - tile.y / 4) * scale.y, + ); } /// Converts a coordinate from the isometric space to the cartesian space. @@ -147,29 +154,42 @@ class IsometricTileMapComponent extends PositionComponent { return Vector2(x, y); } + final Vector2 _getBlockCache = Vector2.zero(); + final Vector2 _getBlockIsoCache = Vector2.zero(); + /// Get which block's surface is at isometric position [p]. /// /// This can be used to handle clicks or hovers. /// This is the opposite of [getBlockCenterPosition]. Block getBlock(Vector2 p) { - final halfTile = (effectiveTileSize / 2)..multiply(scale); + final halfTile = _getBlockCache + ..setFrom(effectiveTileSize) + ..multiply(scale / 2); final multiplier = 1 - halfTile.y / (2 * effectiveTileHeight * scale.x); - final delta = halfTile.clone()..multiply(Vector2(1, multiplier)); - final cart = isoToCart(p - position + delta); + final iso = _getBlockIsoCache + ..setFrom(p) + ..sub(position) + ..addValues(halfTile.x, halfTile.y * multiplier); + final cart = isoToCart(iso); final px = (cart.x / halfTile.x - 1).ceil(); final py = (cart.y / halfTile.y).ceil(); return Block(px, py); } + final Vector2 _blockPositionCache = Vector2.zero(); + /// Get which block should be rendered on position [p]. /// /// This is the opposite of [getBlockRenderPosition]. Block getBlockRenderedAt(Vector2 p) { final tile = effectiveTileSize; return getBlock( - p + - (Vector2(tile.x / 2, tile.y - effectiveTileHeight - tile.y / 4) - ..multiply(scale)), + _blockPositionCache + ..setFrom(p) + ..addValues( + (tile.x / 2) * scale.x, + (tile.y - effectiveTileHeight - tile.y / 4) * scale.y, + ), ); } diff --git a/packages/flame/lib/src/extensions/vector2.dart b/packages/flame/lib/src/extensions/vector2.dart index a7265e18c90..adfb2b9697a 100644 --- a/packages/flame/lib/src/extensions/vector2.dart +++ b/packages/flame/lib/src/extensions/vector2.dart @@ -175,6 +175,12 @@ extension Vector2Extension on Vector2 { } } + /// Adds [x] and [y] to the current [Vector2]. + void addValues(double x, double y) { + this.x += x; + this.y += y; + } + /// Signed angle in a coordinate system where the Y-axis is flipped. /// /// Since on a canvas/screen y is smaller the further up you go, instead of From 6e578a310894c141c4743b51961f6007a98befb8 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Sun, 4 Feb 2024 17:53:41 +0100 Subject: [PATCH 2/3] Add test for addValues --- packages/flame/test/extensions/vector2_test.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/flame/test/extensions/vector2_test.dart b/packages/flame/test/extensions/vector2_test.dart index 5cba3ea1bce..7042098a600 100644 --- a/packages/flame/test/extensions/vector2_test.dart +++ b/packages/flame/test/extensions/vector2_test.dart @@ -472,6 +472,12 @@ void main() { expect(p1.hashCode == p2.hashCode, false); }); + test('addValues', () { + final p = Vector2(1.0, 0.0); + p.addValues(2.0, 3.0); + expect(p, Vector2(3.0, 3.0)); + }); + test('limit', () { final p1 = Vector2(1.0, 0.0); p1.clampScalar(0, 0.75); From 696ac47edb4790dd4637f6ebc573f0e5e25c233c Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Mon, 5 Feb 2024 12:03:03 +0100 Subject: [PATCH 3/3] Apply suggestions from code review --- .../lib/src/components/isometric_tile_map_component.dart | 6 +++--- packages/flame/lib/src/extensions/vector2.dart | 6 ------ packages/flame/test/extensions/vector2_test.dart | 6 ------ 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/packages/flame/lib/src/components/isometric_tile_map_component.dart b/packages/flame/lib/src/components/isometric_tile_map_component.dart index 728fc001c2a..2a7668a9603 100644 --- a/packages/flame/lib/src/components/isometric_tile_map_component.dart +++ b/packages/flame/lib/src/components/isometric_tile_map_component.dart @@ -134,7 +134,7 @@ class IsometricTileMapComponent extends PositionComponent { Vector2 getBlockCenterPosition(Block block) { final tile = effectiveTileSize; return getBlockRenderPosition(block) - ..addValues( + ..translate( (tile.x / 2) * scale.x, (tile.y - effectiveTileHeight - tile.y / 4) * scale.y, ); @@ -169,7 +169,7 @@ class IsometricTileMapComponent extends PositionComponent { final iso = _getBlockIsoCache ..setFrom(p) ..sub(position) - ..addValues(halfTile.x, halfTile.y * multiplier); + ..translate(halfTile.x, halfTile.y * multiplier); final cart = isoToCart(iso); final px = (cart.x / halfTile.x - 1).ceil(); final py = (cart.y / halfTile.y).ceil(); @@ -186,7 +186,7 @@ class IsometricTileMapComponent extends PositionComponent { return getBlock( _blockPositionCache ..setFrom(p) - ..addValues( + ..translate( (tile.x / 2) * scale.x, (tile.y - effectiveTileHeight - tile.y / 4) * scale.y, ), diff --git a/packages/flame/lib/src/extensions/vector2.dart b/packages/flame/lib/src/extensions/vector2.dart index adfb2b9697a..a7265e18c90 100644 --- a/packages/flame/lib/src/extensions/vector2.dart +++ b/packages/flame/lib/src/extensions/vector2.dart @@ -175,12 +175,6 @@ extension Vector2Extension on Vector2 { } } - /// Adds [x] and [y] to the current [Vector2]. - void addValues(double x, double y) { - this.x += x; - this.y += y; - } - /// Signed angle in a coordinate system where the Y-axis is flipped. /// /// Since on a canvas/screen y is smaller the further up you go, instead of diff --git a/packages/flame/test/extensions/vector2_test.dart b/packages/flame/test/extensions/vector2_test.dart index 7042098a600..5cba3ea1bce 100644 --- a/packages/flame/test/extensions/vector2_test.dart +++ b/packages/flame/test/extensions/vector2_test.dart @@ -472,12 +472,6 @@ void main() { expect(p1.hashCode == p2.hashCode, false); }); - test('addValues', () { - final p = Vector2(1.0, 0.0); - p.addValues(2.0, 3.0); - expect(p, Vector2(3.0, 3.0)); - }); - test('limit', () { final p1 = Vector2(1.0, 0.0); p1.clampScalar(0, 0.75);