import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:wolf_3d_engine/wolf_3d_engine.dart'; // 1. The widget now only requires the engine! abstract class BaseWolfRenderer extends StatefulWidget { final WolfEngine engine; const BaseWolfRenderer({ required this.engine, super.key, }); } abstract class BaseWolfRendererState extends State with SingleTickerProviderStateMixin { late final Ticker gameLoop; final FocusNode focusNode = FocusNode(); Duration _lastTick = Duration.zero; @override void initState() { super.initState(); // DO NOT initialize the engine here. Just start the loop! gameLoop = createTicker(_tick)..start(); focusNode.requestFocus(); } void _tick(Duration elapsed) { if (!widget.engine.isInitialized) return; Duration delta = elapsed - _lastTick; _lastTick = elapsed; // Tick the shared engine widget.engine.tick(delta); performRender(); } @override void dispose() { gameLoop.dispose(); focusNode.dispose(); super.dispose(); } void performRender(); Widget buildViewport(BuildContext context); Color get scaffoldColor; @override Widget build(BuildContext context) { return Scaffold( backgroundColor: scaffoldColor, body: KeyboardListener( focusNode: focusNode, autofocus: true, onKeyEvent: (_) {}, child: Center( child: buildViewport(context), ), ), ); } }