Created
September 25, 2024 03:12
-
-
Save jonahwilliams/9b73ebb7fde76478ef98ddb6d45f1aee to your computer and use it in GitHub Desktop.
draw atlas painter
This file contains hidden or 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
diff --git a/bench_flutter/lib/game/game_screen.dart b/bench_flutter/lib/game/game_screen.dart | |
index 16843e0..87da9d4 100644 | |
--- a/bench_flutter/lib/game/game_screen.dart | |
+++ b/bench_flutter/lib/game/game_screen.dart | |
@@ -1,3 +1,5 @@ | |
+import 'dart:ui' as ui; | |
+ | |
import 'package:bench_flutter/audio/audio_controller.dart'; | |
import 'package:bench_flutter/game/button.dart'; | |
import 'package:bench_flutter/game/game_world.dart'; | |
@@ -22,7 +24,7 @@ class GameScreen extends StatelessWidget { | |
'assets/images/wood-background.jpg', | |
fit: BoxFit.cover, | |
), | |
- const GameWorldWidget(), | |
+ const RepaintBoundary(child: GameWorldWidget()), | |
const RepaintBoundary(child: LogoWidget()), | |
const _DisappearingButtons(), | |
Positioned( | |
diff --git a/bench_flutter/lib/game/game_world.dart b/bench_flutter/lib/game/game_world.dart | |
index 4516bdc..4da2dff 100644 | |
--- a/bench_flutter/lib/game/game_world.dart | |
+++ b/bench_flutter/lib/game/game_world.dart | |
@@ -1,6 +1,8 @@ | |
import 'dart:math'; | |
+import 'dart:ui' as ui; | |
import 'package:bench_flutter/game/wanderer.dart'; | |
+import 'package:flutter/scheduler.dart'; | |
import 'package:flutter/widgets.dart'; | |
import 'package:logging/logging.dart'; | |
import 'package:provider/provider.dart'; | |
@@ -63,31 +65,88 @@ class GameWorldWidget extends StatefulWidget { | |
State<GameWorldWidget> createState() => _GameWorldWidgetState(); | |
} | |
+Future<ui.Image> loadAsset(String asset) async { | |
+ ui.ImmutableBuffer buffer = await ui.ImmutableBuffer.fromAsset(asset); | |
+ ui.ImageDescriptor descriptor = await ui.ImageDescriptor.encoded(buffer); | |
+ ui.Codec codec = await descriptor.instantiateCodec(); | |
+ ui.FrameInfo info = await codec.getNextFrame(); | |
+ | |
+ buffer.dispose(); | |
+ descriptor.dispose(); | |
+ codec.dispose(); | |
+ | |
+ return info.image; | |
+} | |
+ | |
class _GameWorldWidgetState extends State<GameWorldWidget> | |
with SingleTickerProviderStateMixin { | |
- late AnimationController _controller; | |
+ late Ticker _ticker; | |
+ ui.Image? sprite; | |
@override | |
Widget build(BuildContext context) { | |
+ if (sprite == null) { | |
+ return const Placeholder(); | |
+ } | |
+ | |
final world = context.watch<GameWorld>(); | |
+ return CustomPaint(painter: WandererPainter(sprite!, world.wanderers)); | |
+ } | |
- return Stack( | |
- children: [ | |
- for (final wanderer in world.wanderers) | |
- PairedWandererWidget(wanderer: wanderer), | |
- ], | |
- ); | |
+ @override | |
+ void initState() { | |
+ super.initState(); | |
+ loadAsset('assets/images/sprite.png').then((ui.Image image) { | |
+ setState(() { | |
+ sprite = image; | |
+ }); | |
+ }); | |
+ _ticker = createTicker(_onTick); | |
+ _ticker.start(); | |
} | |
@override | |
void dispose() { | |
- _controller.dispose(); | |
+ _ticker.dispose(); | |
super.dispose(); | |
} | |
+ void _onTick(Duration elapsed) { | |
+ final world = Provider.of<GameWorld>(context, listen: false); | |
+ | |
+ for (final wanderer in world.wanderers) { | |
+ final dt = (elapsed - wanderer.lastElapsed).inMicroseconds / 1000000; | |
+ wanderer.update(dt); | |
+ wanderer.lastElapsed = elapsed; | |
+ } | |
+ | |
+ setState(() { | |
+ // | |
+ }); | |
+ } | |
+} | |
+ | |
+class WandererPainter extends CustomPainter { | |
+ const WandererPainter(this.sprite, this.wanderers); | |
+ | |
+ final ui.Image sprite; | |
+ final List<PairedWanderer> wanderers; | |
+ | |
+ @override | |
+ void paint(ui.Canvas canvas, ui.Size size) { | |
+ var wholeImage = Rect.fromLTWH(0, 0, sprite.width.toDouble(), sprite.height.toDouble()); | |
+ canvas.drawAtlas(sprite, [ | |
+ for (var wanderer in wanderers) | |
+ ui.RSTransform.fromComponents(rotation: 0, scale: 1, anchorX: 0, anchorY: 0, translateX: wanderer.position.x - 128 / 4, translateY: wanderer.position.y - 128 / 4) | |
+ ], [ | |
+ for (var _ in wanderers) | |
+ wholeImage | |
+ ], null, null, Offset.zero & size, Paint()); | |
+ } | |
+ | |
@override | |
- void initState() { | |
- super.initState(); | |
- _controller = AnimationController(vsync: this); | |
+ bool shouldRepaint(covariant CustomPainter oldDelegate) { | |
+ return true; | |
} | |
+ | |
} | |
diff --git a/bench_flutter/lib/game/wanderer.dart b/bench_flutter/lib/game/wanderer.dart | |
index cc35ce2..6bc9270 100644 | |
--- a/bench_flutter/lib/game/wanderer.dart | |
+++ b/bench_flutter/lib/game/wanderer.dart | |
@@ -1,5 +1,4 @@ | |
import 'package:flutter/cupertino.dart'; | |
-import 'package:flutter/scheduler.dart'; | |
import 'package:vector_math/vector_math_64.dart'; | |
class PairedWanderer { | |
@@ -11,6 +10,8 @@ class PairedWanderer { | |
final Size worldSize; | |
+ Duration lastElapsed = Duration.zero; | |
+ | |
PairedWanderer({ | |
required this.position, | |
required this.velocity, | |
@@ -35,48 +36,3 @@ class PairedWanderer { | |
} | |
} | |
} | |
- | |
-class PairedWandererWidget extends StatefulWidget { | |
- final PairedWanderer wanderer; | |
- | |
- const PairedWandererWidget({required this.wanderer, super.key}); | |
- | |
- @override | |
- State<PairedWandererWidget> createState() => _PairedWandererWidgetState(); | |
-} | |
- | |
-class _PairedWandererWidgetState extends State<PairedWandererWidget> | |
- with SingleTickerProviderStateMixin { | |
- late Ticker _ticker; | |
- | |
- Duration _lastElapsed = Duration.zero; | |
- | |
- @override | |
- void initState() { | |
- super.initState(); | |
- _ticker = createTicker(_onTick); | |
- _ticker.start(); | |
- } | |
- | |
- @override | |
- void dispose() { | |
- _ticker.dispose(); | |
- super.dispose(); | |
- } | |
- | |
- @override | |
- Widget build(BuildContext context) { | |
- return Positioned( | |
- left: widget.wanderer.position.x - 128 / 4, | |
- top: widget.wanderer.position.y - 128 / 4, | |
- child: Image.asset('assets/images/sprite.png', scale: 2), | |
- ); | |
- } | |
- | |
- void _onTick(Duration elapsed) { | |
- final dt = (elapsed - _lastElapsed).inMicroseconds / 1000000; | |
- widget.wanderer.update(dt); | |
- _lastElapsed = elapsed; | |
- setState(() {}); | |
- } | |
-} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment