diff --git a/lib/src/Engine.dart b/lib/src/Engine.dart index 5653bb9..3319a06 100644 --- a/lib/src/Engine.dart +++ b/lib/src/Engine.dart @@ -1,5 +1,6 @@ import 'dart:html' as html; +import 'package:rules_of_living/src/Renderer.dart'; import 'package:rules_of_living/src/Simulation.dart'; class Engine { @@ -37,7 +38,12 @@ class Engine { /// be used if no canvas was defined at engine creation and it should be /// rendered later. html.CanvasElement canvas; + Simulation _simulation; + Map _lastSimulationUpdate = {}; + + Renderer _renderer; + bool running = false; Engine() { @@ -70,6 +76,7 @@ class Engine { } } + // TODO Should be renamed to something more intention revealing like hasReachedUpdateTimestepThreshold bool _shouldUpdate(int updateLag, int elapsed, int timeOut) { if (updateLag < _MS_PER_STEP) return false; if (elapsed > timeOut) throw StackOverflowError; @@ -85,10 +92,10 @@ class Engine { void update() { if (_simulation == null) return; - Map simulationUpdate = _simulation.update(); - _simulation.mergeStateChanges(simulationUpdate); + _lastSimulationUpdate = _simulation.update(); + _simulation.mergeStateChanges(_lastSimulationUpdate); - if (simulationUpdate.length == 0) running = false; + if (_lastSimulationUpdate.length == 0) running = false; } /// Advances Logic One Update @@ -107,9 +114,9 @@ class Engine { /// the internal engine processing. Does not do anything if no canvas is /// defined. void render([num interp]) { - if (canvas == null || _simulation == null) return; + if (canvas == null || _renderer == null) return; - _simulation.render(canvas, interp); + _renderer.render(canvas, _lastSimulationUpdate); } void set simulation(Simulation value) => _simulation = value; diff --git a/lib/src/Renderer.dart b/lib/src/Renderer.dart new file mode 100644 index 0000000..8dfc0e1 --- /dev/null +++ b/lib/src/Renderer.dart @@ -0,0 +1,40 @@ +import 'dart:html' as html; +import 'dart:math' as math; + +import 'package:rules_of_living/src/Grid.dart'; + +class Renderer { + bool _dirty = true; + + bool _renderEdges = true; + bool get renderEdges => _renderEdges; + void set renderEdges(bool value) { + _renderEdges = value; + _dirty = true; + } + + void render(html.CanvasElement canvas, Map map) { + // only renders if any cells changed between renders + if (!_dirty) return; + + html.CanvasRenderingContext2D ctx = canvas.getContext('2d'); + int brickW = (canvas.width ~/ map.width); + int brickH = (canvas.height ~/ map.height); + ctx.clearRect(0, 0, canvas.width, canvas.height); + for (int i = 0; i < map.length; i++) { + math.Point p = map.toCoordinates(i); + + if (_renderEdges) { + ctx.setStrokeColorRgb(100, 100, 100); + ctx.strokeRect(p.x * brickW, p.y * brickH, brickW, brickH); + } + + if (map[i] == true) + ctx.setFillColorRgb(155, 155, 255); + else + ctx.setFillColorRgb(0, 0, 0); + ctx.fillRect(p.x * brickW, p.y * brickH, brickW, brickH); + } + _dirty = false; + } +} diff --git a/lib/src/Simulation.dart b/lib/src/Simulation.dart index 0955c9a..fd92338 100644 --- a/lib/src/Simulation.dart +++ b/lib/src/Simulation.dart @@ -1,4 +1,3 @@ -import 'dart:html' as html; import 'dart:math' as math; import 'dart:math'; @@ -14,12 +13,6 @@ class Simulation { RuleSet rules = GameOfLife(); - bool _dirty = true; - bool get dirty => _dirty; - - bool _renderEdges = true; - bool get renderEdges => _renderEdges; - int _amount; int _dispersal; @@ -36,9 +29,9 @@ class Simulation { Simulation.fromGrid(Grid map) : this.map = map; + //TODO this needs to RETURN a changeSet, just like the others do Grid reset([Grid map]) { map ??= this.map; - _dirty = true; map.setAll(0, List.filled(map.length, false)); return map; } @@ -60,8 +53,6 @@ class Simulation { cx + rng.nextInt(_dispersal), cy + rng.nextInt(_dispersal), true); if (sanityCheck > 100 && sanityCheck > i * 3) break; } - - _dirty = true; } void setCellState(int x, int y, bool state) { @@ -91,7 +82,6 @@ class Simulation { void mergeStateChanges(Map stateChanges) { stateChanges.forEach((i, el) => map[i] = el); - if (stateChanges.length != 0) _dirty = true; } Map calculateNextState(Grid oldState) { @@ -125,39 +115,9 @@ class Simulation { return count; } - void render(html.CanvasElement canvas, [num interp]) { - // only renders if any cells changed between renders - if (!_dirty) return; - - html.CanvasRenderingContext2D ctx = canvas.getContext('2d'); - int brickW = (canvas.width ~/ map.width); - int brickH = (canvas.height ~/ map.height); - ctx.clearRect(0, 0, canvas.width, canvas.height); - for (int i = 0; i < map.length; i++) { - math.Point p = map.toCoordinates(i); - if (_renderEdges) { - ctx.setStrokeColorRgb(100, 100, 100); - ctx.strokeRect(p.x * brickW, p.y * brickH, brickW, brickH); - } - - if (map[i] == true) - ctx.setFillColorRgb(155, 155, 255); - else - ctx.setFillColorRgb(0, 0, 0); - ctx.fillRect(p.x * brickW, p.y * brickH, brickW, brickH); - } - _dirty = false; - } - - void set renderEdges(bool on) { - _renderEdges = on; - _dirty = true; - } - void saveSnapshot() => _snapshot = Grid.from(map); Grid loadSnapshot() { map = Grid.from(_snapshot); - _dirty = true; return map; } }