From 8d7575eaf7619becf56078eced5e4200be83bda7 Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Fri, 24 Aug 2018 20:01:36 +0200 Subject: [PATCH 01/12] Disable superfluous tests In preparation for first test of the app. --- test/{app_test.dart => app_test_disable.dart} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{app_test.dart => app_test_disable.dart} (100%) diff --git a/test/app_test.dart b/test/app_test_disable.dart similarity index 100% rename from test/app_test.dart rename to test/app_test_disable.dart From 6c9179b833886f81f77bc503e876af255547dc37 Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Fri, 24 Aug 2018 20:02:43 +0200 Subject: [PATCH 02/12] make canvas argument optional on instantiating engine --- lib/src/Engine.dart | 11 +++++++---- test/src/engine_test.dart | 12 ++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 test/src/engine_test.dart diff --git a/lib/src/Engine.dart b/lib/src/Engine.dart index 6f7ff16..a52df66 100644 --- a/lib/src/Engine.dart +++ b/lib/src/Engine.dart @@ -6,7 +6,7 @@ class Engine { // Elapsed Time Counter - useful for Safety Timeout Stopwatch _elapsed = new Stopwatch(); - // Game Tick Rate - *does* impact game speed + // Game Tick Rate - *does* impact game speed TODO add configurable option int _MS_PER_STEP = 1000 ~/ 3; // Max Frame (i.e. Rendering) rate - does *not* impact game speed @@ -15,14 +15,18 @@ class Engine { // ms stuck in updateloop after which game will declare itself unresponsive final int SAFETY_TIMEOUT = 2000; + // Grid Size TODO add as configurable option + static final GRID_X = 100; + static final GRID_Y = 100; + num _updateLag = 0.0; num _drawLag = 0.0; final html.CanvasElement canvas; - Grid _grid = new Grid(100, 100); + Grid _grid = new Grid(GRID_X, GRID_Y); bool _running = false; - Engine(this.canvas) { + Engine([this.canvas]) { _elapsed.start(); _grid.addPattern(amount: 15, dispersal: 5); } @@ -59,7 +63,6 @@ class Engine { } void update() { -// print("updating"); if (!_grid.update()) running = false; } diff --git a/test/src/engine_test.dart b/test/src/engine_test.dart new file mode 100644 index 0000000..92794ff --- /dev/null +++ b/test/src/engine_test.dart @@ -0,0 +1,12 @@ +@TestOn('browser') + +import 'dart:html'; + +import 'package:rules_of_living/src/Engine.dart'; +import 'package:test/test.dart'; + +void main() { + test("Engine can be instantiated without canvas", () { + expect(Engine(), isNot(throwsA(anything))); + }); +} \ No newline at end of file From bbf61f875d7e819eabc12bee795320fced6b7466 Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Sat, 25 Aug 2018 09:33:15 +0200 Subject: [PATCH 03/12] Separate Engine Service Functionality from Component --- lib/components/controls_component.dart | 12 +++----- lib/components/simulation_component.dart | 10 +------ lib/service/engine_service.dart | 37 ++++++++++++++++++++++-- lib/src/Engine.dart | 11 ++++--- 4 files changed, 47 insertions(+), 23 deletions(-) diff --git a/lib/components/controls_component.dart b/lib/components/controls_component.dart index 1f2a65d..511a7d4 100644 --- a/lib/components/controls_component.dart +++ b/lib/components/controls_component.dart @@ -1,8 +1,6 @@ import 'package:angular/angular.dart'; import 'package:angular_components/angular_components.dart'; -import 'package:rules_of_living/service/configuration_service.dart'; import 'package:rules_of_living/service/engine_service.dart'; -import 'package:rules_of_living/src/Engine.dart'; @Component( selector: 'sim-controls', @@ -17,13 +15,12 @@ import 'package:rules_of_living/src/Engine.dart'; styleUrls: const ["controls_component.css"], ) class ControlsComponent { - final EngineService engineService; + final EngineService engine; - Engine get engine => engineService.engine; - ControlsComponent(this.engineService); + ControlsComponent(this.engine); void onStartClicked() { - engine.running = !engine.running; + engine.toggleRunning(); } void onStepClicked() { @@ -35,8 +32,7 @@ class ControlsComponent { } void onRandomClicked() { - engine.running = false; - engine.addPattern(); + engine.addRandomPattern(); } void onClearClicked() { diff --git a/lib/components/simulation_component.dart b/lib/components/simulation_component.dart index e64fa82..c372026 100644 --- a/lib/components/simulation_component.dart +++ b/lib/components/simulation_component.dart @@ -8,7 +8,6 @@ import 'package:rules_of_living/service/engine_service.dart'; templateUrl: "simulation_component.html", directives: [coreDirectives], providers: [], -// styleUrls: const ['package:angular_components/app_layout/layout.scss.css'], ) class SimulationComponent implements OnInit { final EngineService engineService; @@ -29,13 +28,6 @@ class SimulationComponent implements OnInit { If you see this\n the app is broken :( ''', canvas.width / 2 - 50, canvas.height / 2); - engineService.create(canvas); - - html.window.animationFrame.then(animFrame); - } - - void animFrame(num now) { - engineService.engine.process(now); - html.window.animationFrame.then(animFrame); +// engineService.create(canvas); } } diff --git a/lib/service/engine_service.dart b/lib/service/engine_service.dart index 5107f3c..6384f5f 100644 --- a/lib/service/engine_service.dart +++ b/lib/service/engine_service.dart @@ -5,7 +5,40 @@ import 'package:rules_of_living/src/Engine.dart'; class EngineService { Engine _engine; - Engine get engine => _engine; + Engine get engine => _engine ?? create(null); + + Engine create(html.CanvasElement canvas) { + _engine = Engine(canvas); + return _engine; + } + + void run() { + engine.running = true; + } + + void stop() { + engine.running = false; + } + + void toggleRunning() { + engine.running = !engine.running; + } + + void step() { + engine.step(); + } + + void reset() { + engine.reset(); + } + + void addRandomPattern() { + engine.running = false; + engine.addPattern(); + } + + void clear() { + engine.clear(); + } - void create(html.CanvasElement canvas) => _engine = Engine(canvas); } diff --git a/lib/src/Engine.dart b/lib/src/Engine.dart index a52df66..9b1814e 100644 --- a/lib/src/Engine.dart +++ b/lib/src/Engine.dart @@ -24,11 +24,17 @@ class Engine { final html.CanvasElement canvas; Grid _grid = new Grid(GRID_X, GRID_Y); - bool _running = false; + bool running = false; Engine([this.canvas]) { _elapsed.start(); _grid.addPattern(amount: 15, dispersal: 5); + html.window.animationFrame.then(animFrame); + } + + void animFrame(num now) { + process(now); + html.window.animationFrame.then(animFrame); } void reset() { @@ -95,7 +101,4 @@ class Engine { void toggleEdgeRendering() { _grid.renderEdges = !_grid.renderEdges; } - - void set running(bool on) => _running = on; - bool get running => _running; } From 1bd324a4066ab49170baaef9079e612f468f6963 Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Fri, 24 Aug 2018 20:01:36 +0200 Subject: [PATCH 04/12] Disable superfluous tests In preparation for first test of the app. --- test/{app_test.dart => app_test_disable.dart} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{app_test.dart => app_test_disable.dart} (100%) diff --git a/test/app_test.dart b/test/app_test_disable.dart similarity index 100% rename from test/app_test.dart rename to test/app_test_disable.dart From 842cbeca1f9ab5313efb10bbbd9409240a485f30 Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Fri, 24 Aug 2018 20:02:43 +0200 Subject: [PATCH 05/12] make canvas argument optional on instantiating engine --- lib/src/Engine.dart | 11 +++++++---- test/src/engine_test.dart | 12 ++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 test/src/engine_test.dart diff --git a/lib/src/Engine.dart b/lib/src/Engine.dart index 6f7ff16..a52df66 100644 --- a/lib/src/Engine.dart +++ b/lib/src/Engine.dart @@ -6,7 +6,7 @@ class Engine { // Elapsed Time Counter - useful for Safety Timeout Stopwatch _elapsed = new Stopwatch(); - // Game Tick Rate - *does* impact game speed + // Game Tick Rate - *does* impact game speed TODO add configurable option int _MS_PER_STEP = 1000 ~/ 3; // Max Frame (i.e. Rendering) rate - does *not* impact game speed @@ -15,14 +15,18 @@ class Engine { // ms stuck in updateloop after which game will declare itself unresponsive final int SAFETY_TIMEOUT = 2000; + // Grid Size TODO add as configurable option + static final GRID_X = 100; + static final GRID_Y = 100; + num _updateLag = 0.0; num _drawLag = 0.0; final html.CanvasElement canvas; - Grid _grid = new Grid(100, 100); + Grid _grid = new Grid(GRID_X, GRID_Y); bool _running = false; - Engine(this.canvas) { + Engine([this.canvas]) { _elapsed.start(); _grid.addPattern(amount: 15, dispersal: 5); } @@ -59,7 +63,6 @@ class Engine { } void update() { -// print("updating"); if (!_grid.update()) running = false; } diff --git a/test/src/engine_test.dart b/test/src/engine_test.dart new file mode 100644 index 0000000..92794ff --- /dev/null +++ b/test/src/engine_test.dart @@ -0,0 +1,12 @@ +@TestOn('browser') + +import 'dart:html'; + +import 'package:rules_of_living/src/Engine.dart'; +import 'package:test/test.dart'; + +void main() { + test("Engine can be instantiated without canvas", () { + expect(Engine(), isNot(throwsA(anything))); + }); +} \ No newline at end of file From 976ec8097da4de1fb302088100de7689c53e7bea Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Sat, 25 Aug 2018 09:33:15 +0200 Subject: [PATCH 06/12] Separate Engine Service Functionality from Component --- lib/components/controls_component.dart | 12 +++----- lib/components/simulation_component.dart | 10 +------ lib/service/engine_service.dart | 37 ++++++++++++++++++++++-- lib/src/Engine.dart | 11 ++++--- 4 files changed, 47 insertions(+), 23 deletions(-) diff --git a/lib/components/controls_component.dart b/lib/components/controls_component.dart index 1f2a65d..511a7d4 100644 --- a/lib/components/controls_component.dart +++ b/lib/components/controls_component.dart @@ -1,8 +1,6 @@ import 'package:angular/angular.dart'; import 'package:angular_components/angular_components.dart'; -import 'package:rules_of_living/service/configuration_service.dart'; import 'package:rules_of_living/service/engine_service.dart'; -import 'package:rules_of_living/src/Engine.dart'; @Component( selector: 'sim-controls', @@ -17,13 +15,12 @@ import 'package:rules_of_living/src/Engine.dart'; styleUrls: const ["controls_component.css"], ) class ControlsComponent { - final EngineService engineService; + final EngineService engine; - Engine get engine => engineService.engine; - ControlsComponent(this.engineService); + ControlsComponent(this.engine); void onStartClicked() { - engine.running = !engine.running; + engine.toggleRunning(); } void onStepClicked() { @@ -35,8 +32,7 @@ class ControlsComponent { } void onRandomClicked() { - engine.running = false; - engine.addPattern(); + engine.addRandomPattern(); } void onClearClicked() { diff --git a/lib/components/simulation_component.dart b/lib/components/simulation_component.dart index e64fa82..c372026 100644 --- a/lib/components/simulation_component.dart +++ b/lib/components/simulation_component.dart @@ -8,7 +8,6 @@ import 'package:rules_of_living/service/engine_service.dart'; templateUrl: "simulation_component.html", directives: [coreDirectives], providers: [], -// styleUrls: const ['package:angular_components/app_layout/layout.scss.css'], ) class SimulationComponent implements OnInit { final EngineService engineService; @@ -29,13 +28,6 @@ class SimulationComponent implements OnInit { If you see this\n the app is broken :( ''', canvas.width / 2 - 50, canvas.height / 2); - engineService.create(canvas); - - html.window.animationFrame.then(animFrame); - } - - void animFrame(num now) { - engineService.engine.process(now); - html.window.animationFrame.then(animFrame); +// engineService.create(canvas); } } diff --git a/lib/service/engine_service.dart b/lib/service/engine_service.dart index 5107f3c..6384f5f 100644 --- a/lib/service/engine_service.dart +++ b/lib/service/engine_service.dart @@ -5,7 +5,40 @@ import 'package:rules_of_living/src/Engine.dart'; class EngineService { Engine _engine; - Engine get engine => _engine; + Engine get engine => _engine ?? create(null); + + Engine create(html.CanvasElement canvas) { + _engine = Engine(canvas); + return _engine; + } + + void run() { + engine.running = true; + } + + void stop() { + engine.running = false; + } + + void toggleRunning() { + engine.running = !engine.running; + } + + void step() { + engine.step(); + } + + void reset() { + engine.reset(); + } + + void addRandomPattern() { + engine.running = false; + engine.addPattern(); + } + + void clear() { + engine.clear(); + } - void create(html.CanvasElement canvas) => _engine = Engine(canvas); } diff --git a/lib/src/Engine.dart b/lib/src/Engine.dart index a52df66..9b1814e 100644 --- a/lib/src/Engine.dart +++ b/lib/src/Engine.dart @@ -24,11 +24,17 @@ class Engine { final html.CanvasElement canvas; Grid _grid = new Grid(GRID_X, GRID_Y); - bool _running = false; + bool running = false; Engine([this.canvas]) { _elapsed.start(); _grid.addPattern(amount: 15, dispersal: 5); + html.window.animationFrame.then(animFrame); + } + + void animFrame(num now) { + process(now); + html.window.animationFrame.then(animFrame); } void reset() { @@ -95,7 +101,4 @@ class Engine { void toggleEdgeRendering() { _grid.renderEdges = !_grid.renderEdges; } - - void set running(bool on) => _running = on; - bool get running => _running; } From 572406b963d029884db7898a080372b9d8863664 Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Sat, 25 Aug 2018 14:10:19 +0200 Subject: [PATCH 07/12] Fix undefined running access --- lib/components/controls_component.html | 2 +- lib/service/engine_service.dart | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/components/controls_component.html b/lib/components/controls_component.html index 30ddf55..42e79f7 100644 --- a/lib/components/controls_component.html +++ b/lib/components/controls_component.html @@ -1,7 +1,7 @@
- + diff --git a/lib/service/engine_service.dart b/lib/service/engine_service.dart index 6384f5f..f6c7304 100644 --- a/lib/service/engine_service.dart +++ b/lib/service/engine_service.dart @@ -41,4 +41,6 @@ class EngineService { engine.clear(); } + bool get isRunning => engine.running; + } From 4c6dff35c3c29b1db70b8aeef33d2602bcfcb9df Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Sat, 25 Aug 2018 14:10:56 +0200 Subject: [PATCH 08/12] Add Canvas nullcheck to render function --- lib/components/simulation_component.dart | 5 +++-- lib/src/Engine.dart | 7 +++---- test/src/engine_test.dart | 16 +++++++++++++--- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/lib/components/simulation_component.dart b/lib/components/simulation_component.dart index c372026..b7e817c 100644 --- a/lib/components/simulation_component.dart +++ b/lib/components/simulation_component.dart @@ -25,8 +25,9 @@ class SimulationComponent implements OnInit { canvas.context2D.fillRect(0, 0, canvas.width, canvas.height); canvas.context2D.setFillColorRgb(0, 255, 0); canvas.context2D.fillText(''' - If you see this\n - the app is broken :( + If you see this + + the canvas did not load correctly :( ''', canvas.width / 2 - 50, canvas.height / 2); // engineService.create(canvas); } diff --git a/lib/src/Engine.dart b/lib/src/Engine.dart index 9b1814e..601e5ac 100644 --- a/lib/src/Engine.dart +++ b/lib/src/Engine.dart @@ -22,7 +22,7 @@ class Engine { num _updateLag = 0.0; num _drawLag = 0.0; - final html.CanvasElement canvas; + html.CanvasElement canvas; Grid _grid = new Grid(GRID_X, GRID_Y); bool running = false; @@ -43,7 +43,7 @@ class Engine { } void clear() { - _grid = new Grid(100, 100); + _grid = new Grid(GRID_X, GRID_Y); running = false; } @@ -78,8 +78,7 @@ class Engine { } void render([num interp]) { -// print("rendering"); - _grid.render(canvas, interp); + if(canvas != null) _grid.render(canvas, interp); } void addPattern( diff --git a/test/src/engine_test.dart b/test/src/engine_test.dart index 92794ff..72f8b0d 100644 --- a/test/src/engine_test.dart +++ b/test/src/engine_test.dart @@ -1,12 +1,22 @@ @TestOn('browser') -import 'dart:html'; - import 'package:rules_of_living/src/Engine.dart'; import 'package:test/test.dart'; void main() { test("Engine can be instantiated without canvas", () { - expect(Engine(), isNot(throwsA(anything))); + expect(Engine(), isNot(throwsNoSuchMethodError)); + }); + + test("Engine does not throw errors when calling render directly", () { + Engine sut = new Engine(); + // anonymous function necessary since throws can not use functions with args + expect(() => sut.render(), isNot(throwsNoSuchMethodError)); + }); + + test("Engine does not throw errors when processing without attached canvas", () { + Engine sut = new Engine(); + // anonymous function necessary since throws can not use functions with args + expect(() => sut.process(1000), isNot(throwsNoSuchMethodError)); }); } \ No newline at end of file From 66bf87d9d875409b2fc4e74707268f9098a5ab68 Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Sat, 25 Aug 2018 14:36:50 +0200 Subject: [PATCH 09/12] Allow setting a canvas for an engine at any point --- lib/src/Engine.dart | 20 ++++++++++++++++++++ test/src/engine_test.dart | 16 +++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/lib/src/Engine.dart b/lib/src/Engine.dart index 601e5ac..539e6d2 100644 --- a/lib/src/Engine.dart +++ b/lib/src/Engine.dart @@ -22,6 +22,11 @@ class Engine { num _updateLag = 0.0; num _drawLag = 0.0; + /// The Canvas to Paint on + /// + /// Manually define or change the canvas the engine should render to. Should + /// be used if no canvas was defined at engine creation and it should be + /// rendered later. html.CanvasElement canvas; Grid _grid = new Grid(GRID_X, GRID_Y); bool running = false; @@ -68,15 +73,30 @@ class Engine { } } + /// Update Engine Logic + /// + /// Updates the logic of the engine by one tick. Should usually not be called + /// directly, since it is automatically taken care of by the processing function. + /// If simulation should be advanced manually one time, prefer using step(). void update() { if (!_grid.update()) running = false; } + /// Advances Logic One Update + /// + /// Moves logic of the engine one step forward and pauses the + /// simulation. Does not automatically re-render the new state + /// (though this should usually not pose a problem). void step() { running = false; _grid.update(); } + /// Renders the Current Simulation State + /// + /// Renders the simulation once. Will usually automatically be called by + /// the internal engine processing. Does not do anything if no canvas is + /// defined. void render([num interp]) { if(canvas != null) _grid.render(canvas, interp); } diff --git a/test/src/engine_test.dart b/test/src/engine_test.dart index 72f8b0d..0712ba8 100644 --- a/test/src/engine_test.dart +++ b/test/src/engine_test.dart @@ -1,22 +1,32 @@ +import 'dart:html' as html; + @TestOn('browser') import 'package:rules_of_living/src/Engine.dart'; import 'package:test/test.dart'; void main() { + Engine sut; + setUp(() { + sut = Engine(); + }); + test("Engine can be instantiated without canvas", () { - expect(Engine(), isNot(throwsNoSuchMethodError)); + expect(sut, isNot(throwsNoSuchMethodError)); }); test("Engine does not throw errors when calling render directly", () { - Engine sut = new Engine(); // anonymous function necessary since throws can not use functions with args expect(() => sut.render(), isNot(throwsNoSuchMethodError)); }); test("Engine does not throw errors when processing without attached canvas", () { - Engine sut = new Engine(); // anonymous function necessary since throws can not use functions with args expect(() => sut.process(1000), isNot(throwsNoSuchMethodError)); }); + + test("setCanvas allows setting a canvas for an engine at any point", () { + sut.canvas = new html.CanvasElement(); + expect(sut.canvas, isNotNull); + }); } \ No newline at end of file From cc33628e5fd81e0702a48ecb20677b97adb3ae58 Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Sat, 25 Aug 2018 14:51:28 +0200 Subject: [PATCH 10/12] Enable cached engine returns for EngineService --- lib/service/engine_service.dart | 6 ++++-- test/service/engine_service_test.dart | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 test/service/engine_service_test.dart diff --git a/lib/service/engine_service.dart b/lib/service/engine_service.dart index f6c7304..69f4699 100644 --- a/lib/service/engine_service.dart +++ b/lib/service/engine_service.dart @@ -5,13 +5,15 @@ import 'package:rules_of_living/src/Engine.dart'; class EngineService { Engine _engine; - Engine get engine => _engine ?? create(null); + Engine get engine => _engine ?? createEngine(null); - Engine create(html.CanvasElement canvas) { + Engine createEngine(html.CanvasElement canvas) { _engine = Engine(canvas); return _engine; } + void setCanvas(html.CanvasElement canvas) => engine.canvas = canvas; + void run() { engine.running = true; } diff --git a/test/service/engine_service_test.dart b/test/service/engine_service_test.dart new file mode 100644 index 0000000..9d4a226 --- /dev/null +++ b/test/service/engine_service_test.dart @@ -0,0 +1,19 @@ +@TestOn('browser') + +import 'package:test/test.dart'; +import 'package:rules_of_living/service/engine_service.dart'; + +void main() { + EngineService sut; + setUp(() { + sut = EngineService(); + }); + + test("EngineService creates an engine on demand", () { + expect(sut.engine, isNotNull); + }); + + test("EngineService returns the cached engine on subsequent requests", () { + expect(sut.engine, allOf(isNotNull, equals(sut.engine))); + }); +} From 71023de49a68e27a8cd07c361a1d8588eda53760 Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Sat, 25 Aug 2018 15:00:46 +0200 Subject: [PATCH 11/12] Make canvas virtual variable on EngineService --- lib/service/engine_service.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/service/engine_service.dart b/lib/service/engine_service.dart index 69f4699..d7b0bed 100644 --- a/lib/service/engine_service.dart +++ b/lib/service/engine_service.dart @@ -12,7 +12,8 @@ class EngineService { return _engine; } - void setCanvas(html.CanvasElement canvas) => engine.canvas = canvas; + void set canvas(html.CanvasElement canvas) => engine.canvas = canvas; + html.CanvasElement get canvas => engine.canvas; void run() { engine.running = true; From 3c27f5ef38f76ccc6dfaee5cd4d45e9d58554a8c Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Sat, 25 Aug 2018 15:01:00 +0200 Subject: [PATCH 12/12] Re-Add Canvas to Simulation component --- lib/components/simulation_component.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/components/simulation_component.dart b/lib/components/simulation_component.dart index b7e817c..12b7844 100644 --- a/lib/components/simulation_component.dart +++ b/lib/components/simulation_component.dart @@ -29,6 +29,6 @@ class SimulationComponent implements OnInit { the canvas did not load correctly :( ''', canvas.width / 2 - 50, canvas.height / 2); -// engineService.create(canvas); + engineService.canvas = canvas; } }