-
-
Notifications
You must be signed in to change notification settings - Fork 899
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Customise grid of NineTileBox (#2495)
The previous implementation of the NineTileBox calculates identically sized tiles in a 3x3 grid and does not allow the user to customise this. For example, a 60x60 pixel sprite will be cut into 20x20 pixel tiles. This MR allows the user to specify the sizes of the fixed-width and fixed-height rows and columns so that a completely custom grid is possible. Example with the following sprite and custom grid sizes. Note that the stretchable row and column are only 1 pixel wide/high in this example.
- Loading branch information
1 parent
87b8a06
commit a25b0a0
Showing
8 changed files
with
270 additions
and
4 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 46 additions & 0 deletions
46
examples/lib/stories/rendering/nine_tile_box_custom_grid_example.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import 'package:flame/components.dart'; | ||
import 'package:flame/game.dart'; | ||
import 'package:flame/input.dart'; | ||
|
||
class NineTileBoxCustomGridExample extends FlameGame | ||
with TapDetector, DoubleTapDetector { | ||
static const String description = ''' | ||
If you want to create a background for something that can stretch you can | ||
use the `NineTileBox` which is showcased here. In this example a custom | ||
grid is used.\n\n | ||
Tap to make the box bigger and double tap to make it smaller. | ||
'''; | ||
|
||
late NineTileBoxComponent nineTileBoxComponent; | ||
|
||
@override | ||
Future<void> onLoad() async { | ||
final sprite = Sprite(await images.load('speech-bubble.png')); | ||
final boxSize = Vector2.all(300); | ||
final nineTileBox = NineTileBox.withGrid( | ||
sprite, | ||
leftWidth: 31, | ||
rightWidth: 5, | ||
topHeight: 5, | ||
bottomHeight: 21, | ||
); | ||
add( | ||
nineTileBoxComponent = NineTileBoxComponent( | ||
nineTileBox: nineTileBox, | ||
position: size / 2, | ||
size: boxSize, | ||
anchor: Anchor.center, | ||
), | ||
); | ||
} | ||
|
||
@override | ||
void onTap() { | ||
nineTileBoxComponent.scale.scale(1.2); | ||
} | ||
|
||
@override | ||
void onDoubleTap() { | ||
nineTileBoxComponent.scale.scale(0.8); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import 'dart:ui'; | ||
|
||
import 'package:flame/components.dart'; | ||
import 'package:flame_test/flame_test.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_test/flutter_test.dart'; | ||
|
||
import '_resources/load_image.dart'; | ||
|
||
void main() { | ||
group('NineTileBox', () { | ||
testGolden( | ||
'Render with default grid', | ||
(game) async { | ||
game.add(_MyComponent1()); | ||
}, | ||
size: Vector2(300, 200), | ||
goldenFile: '_goldens/nine_tile_box_test_1.png', | ||
); | ||
|
||
testGolden( | ||
'Render with specified grid', | ||
(game) async { | ||
game.add(_MyComponent2()); | ||
}, | ||
size: Vector2(300, 200), | ||
goldenFile: '_goldens/nine_tile_box_test_2.png', | ||
); | ||
|
||
test('default tile sizes calculated correctly', () async { | ||
final sprite = Sprite(await loadImage('speech-bubble-1.png')); | ||
final nineTileBox = NineTileBox(sprite); | ||
|
||
expect(nineTileBox.tileSize, equals(30)); | ||
expect(nineTileBox.destTileSize, equals(30)); | ||
}); | ||
|
||
test('tile sizes set correctly', () async { | ||
final sprite = Sprite(await loadImage('speech-bubble-1.png')); | ||
final nineTileBox = NineTileBox(sprite, tileSize: 20, destTileSize: 25); | ||
|
||
expect(nineTileBox.tileSize, equals(20)); | ||
expect(nineTileBox.destTileSize, equals(25)); | ||
}); | ||
|
||
test('grid sizes set correctly', () async { | ||
final sprite = Sprite(await loadImage('speech-bubble-2.png')); | ||
final nineTileBox = NineTileBox.withGrid( | ||
sprite, | ||
leftWidth: 31, | ||
rightWidth: 5, | ||
topHeight: 5, | ||
bottomHeight: 21, | ||
); | ||
|
||
expect(nineTileBox.center.left, equals(31.0)); | ||
expect(nineTileBox.center.right, equals(34.0)); | ||
expect(nineTileBox.center.top, equals(5.0)); | ||
expect(nineTileBox.center.bottom, equals(18.0)); | ||
}); | ||
}); | ||
} | ||
|
||
class _MyComponent1 extends PositionComponent { | ||
_MyComponent1() : super(size: Vector2(300, 200)); | ||
late final Sprite sprite; | ||
late final NineTileBox nineTileBox; | ||
final bgPaint = Paint()..color = const Color.fromARGB(255, 57, 113, 158); | ||
|
||
@override | ||
Future<void> onLoad() async { | ||
sprite = Sprite(await loadImage('speech-bubble-1.png')); | ||
nineTileBox = NineTileBox(sprite); | ||
} | ||
|
||
@override | ||
void render(Canvas canvas) { | ||
canvas.drawRect( | ||
size.toRect(), | ||
bgPaint, | ||
); | ||
nineTileBox.draw(canvas, Vector2(25, 25), Vector2(250, 150)); | ||
} | ||
} | ||
|
||
class _MyComponent2 extends PositionComponent { | ||
_MyComponent2() : super(size: Vector2(300, 200)); | ||
late final Sprite sprite; | ||
late final NineTileBox nineTileBox; | ||
final bgPaint = Paint()..color = const Color.fromARGB(255, 57, 113, 158); | ||
|
||
@override | ||
Future<void> onLoad() async { | ||
sprite = Sprite(await loadImage('speech-bubble-2.png')); | ||
nineTileBox = NineTileBox.withGrid( | ||
sprite, | ||
leftWidth: 31, | ||
rightWidth: 5, | ||
topHeight: 5, | ||
bottomHeight: 21, | ||
); | ||
} | ||
|
||
@override | ||
void render(Canvas canvas) { | ||
canvas.drawRect( | ||
size.toRect(), | ||
bgPaint, | ||
); | ||
nineTileBox.draw(canvas, Vector2(25, 25), Vector2(250, 150)); | ||
} | ||
} |