diff --git a/lib/service/configuration_service.dart b/lib/service/configuration_service.dart index 7da2ca6..93b89d7 100644 --- a/lib/service/configuration_service.dart +++ b/lib/service/configuration_service.dart @@ -4,7 +4,19 @@ class ConfigurationService { final EngineService engineService; bool showGrid; - int simSpeed; + + int _simSpeed; + + /// Simulation Speed + /// + /// Sets the number of updates the simulation takes per second. Can range from + /// 1 to arbitrarily high numbers (though setting it too high can potentially + /// make the app brittle). + int get simSpeed => _simSpeed; + void set simSpeed(int val) { + _simSpeed = val; + engineService.engine.stepsPerSecond = simSpeed; + } ConfigurationService(this.engineService) { showGrid = false; diff --git a/lib/src/Engine.dart b/lib/src/Engine.dart index 539e6d2..be3f31f 100644 --- a/lib/src/Engine.dart +++ b/lib/src/Engine.dart @@ -6,9 +6,22 @@ class Engine { // Elapsed Time Counter - useful for Safety Timeout Stopwatch _elapsed = new Stopwatch(); - // Game Tick Rate - *does* impact game speed TODO add configurable option + /// Game Tick Rate + /// + /// *does* impact game speed; dictates how long each logic step takes. Only + /// interesting for engine internal calculations, to set simulation speed + /// from the outside use stepsPerSecond instead. int _MS_PER_STEP = 1000 ~/ 3; + /// Set Logic Updates per Second + /// + /// Dictates simulation speed. Sets the amount of (logic) updates per second. + /// Translations between number of updates and their timings is not exact so + /// comparing this variable to fixed ints might not yield the expected results. + /// Does not affect render frequency, which is handled by framesPerSecond. + int get stepsPerSecond => 1000 ~/ _MS_PER_STEP; + set stepsPerSecond(int val) => _MS_PER_STEP = 1000 ~/ val; + // Max Frame (i.e. Rendering) rate - does *not* impact game speed final int _MS_PER_FRAME = 1000 ~/ 30; diff --git a/pubspec.yaml b/pubspec.yaml index 4cc6f88..a63ea9a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,3 +17,4 @@ dev_dependencies: build_test: ^0.10.3+1 build_web_compilers: ^0.4.0 test: ^1.3.0 + mockito: ^3.0.0 diff --git a/test/service/configuration_service_test.dart b/test/service/configuration_service_test.dart new file mode 100644 index 0000000..1afa50a --- /dev/null +++ b/test/service/configuration_service_test.dart @@ -0,0 +1,30 @@ +import 'package:rules_of_living/src/Engine.dart'; +@TestOn('browser') + +import 'package:test/test.dart'; +import 'package:rules_of_living/service/configuration_service.dart'; +import 'package:rules_of_living/service/engine_service.dart'; +import 'package:mockito/mockito.dart'; + +class MockEngine extends Mock implements Engine {} +class MockEngineService extends Mock implements EngineService { + MockEngine _engine = MockEngine(); + @override + Engine get engine => _engine; +} + +void main() { + group("simulation speed", () { + ConfigurationService sut; + MockEngineService mes; + setUp(() { + mes = MockEngineService(); + sut = ConfigurationService(mes); + }); + + test("speed changes propagate to engine", () { + sut.simSpeed = 312; + verify(mes.engine.stepsPerSecond=312); + }); + }); +} diff --git a/test/src/engine_test.dart b/test/src/engine_test.dart index 0712ba8..43ea13e 100644 --- a/test/src/engine_test.dart +++ b/test/src/engine_test.dart @@ -17,12 +17,12 @@ void main() { test("Engine does not throw errors when calling render directly", () { // anonymous function necessary since throws can not use functions with args - expect(() => sut.render(), isNot(throwsNoSuchMethodError)); + expect(() => sut.render, isNot(throwsNoSuchMethodError)); }); test("Engine does not throw errors when processing without attached canvas", () { // anonymous function necessary since throws can not use functions with args - expect(() => sut.process(1000), isNot(throwsNoSuchMethodError)); + expect(() => sut.process, isNot(throwsNoSuchMethodError)); }); test("setCanvas allows setting a canvas for an engine at any point", () {