Adding PlayerMovement class to interpolate/extrapolate position along tests (installi...
authorDavid Négrier <d.negrier@thecodingmachine.com>
Tue, 2 Jun 2020 08:48:04 +0000 (10:48 +0200)
committerDavid Négrier <d.negrier@thecodingmachine.com>
Tue, 2 Jun 2020 08:48:04 +0000 (10:48 +0200)
.github/workflows/continuous_integration.yml
front/jasmine.json [new file with mode: 0644]
front/package.json
front/src/Enum/EnvironmentVariable.ts
front/src/Phaser/Game/PlayerMovement.ts [new file with mode: 0644]
front/src/Phaser/Game/PlayersPositionInterpolator.ts [new file with mode: 0644]
front/tests/Phaser/Game/PlayerMovementTest.ts [new file with mode: 0644]
front/tsconfig.json
front/yarn.lock

index a6c86baa8be45c1f9e267fece6bfee214a8eac05..a326bb1bfa5378fb651e8ca70ac93b0ac857fa1a 100644 (file)
@@ -36,6 +36,10 @@ jobs:
         run: yarn run lint
         working-directory: "front"
 
+      - name: "Jasmine"
+        run: yarn test
+        working-directory: "front"
+
   continuous-integration-back:
     name: "Continuous Integration Back"
 
diff --git a/front/jasmine.json b/front/jasmine.json
new file mode 100644 (file)
index 0000000..b51ed79
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "spec_dir": "tests",
+  "spec_files": ["**/*[tT]est.ts"],
+  "stopSpecOnExpectationFailure": false
+}
\ No newline at end of file
index 257126d03329caf7baf516abebfdaaa5931f7e1a..c05bd8ba54008debfb1d8444b7dc8dcba1c5eee5 100644 (file)
@@ -4,11 +4,14 @@
   "main": "index.js",
   "license": "AGPL",
   "devDependencies": {
+    "@types/jasmine": "^3.5.10",
     "@typescript-eslint/eslint-plugin": "^2.26.0",
     "@typescript-eslint/parser": "^2.26.0",
     "eslint": "^6.8.0",
     "html-webpack-plugin": "^4.3.0",
+    "jasmine": "^3.5.0",
     "ts-loader": "^6.2.2",
+    "ts-node": "^8.10.2",
     "typescript": "^3.8.3",
     "webpack": "^4.42.1",
     "webpack-cli": "^3.3.11",
@@ -25,6 +28,7 @@
   "scripts": {
     "start": "webpack-dev-server --open",
     "build": "webpack",
+    "test": "ts-node node_modules/jasmine/bin/jasmine --config=jasmine.json",
     "lint": "node_modules/.bin/eslint src/ . --ext .ts",
     "fix": "node_modules/.bin/eslint --fix src/ . --ext .ts"
   }
index b646d64bfe8a1f02fe043f0c6b8c43560570c655..2fbf797922b7a20b35a7bf0539ca31d30e59c735 100644 (file)
@@ -3,11 +3,13 @@ const API_URL = process.env.API_URL || "http://api.workadventure.localhost";
 const RESOLUTION = 3;
 const ZOOM_LEVEL = 1/*3/4*/;
 const POSITION_DELAY = 200; // Wait 200ms between sending position events
+const MAX_EXTRAPOLATION_TIME = 250; // Extrapolate a maximum of 250ms if no new movement is sent by the player
 
 export {
     DEBUG_MODE,
     API_URL,
     RESOLUTION,
     ZOOM_LEVEL,
-    POSITION_DELAY
+    POSITION_DELAY,
+    MAX_EXTRAPOLATION_TIME
 }
diff --git a/front/src/Phaser/Game/PlayerMovement.ts b/front/src/Phaser/Game/PlayerMovement.ts
new file mode 100644 (file)
index 0000000..aa7a2d4
--- /dev/null
@@ -0,0 +1,23 @@
+import {HasMovedEvent} from "./GameManager";
+import {MAX_EXTRAPOLATION_TIME} from "../../Enum/EnvironmentVariable";
+
+export class PlayerMovement {
+    public constructor(private startPosition: HasMovedEvent, private startTick: number, private endPosition: HasMovedEvent, private endTick: number) {
+    }
+
+    public isOutdated(tick: number): boolean {
+        return tick > this.endTick + MAX_EXTRAPOLATION_TIME;
+    }
+
+    public getPosition(tick: number): HasMovedEvent {
+        let x = (this.endPosition.x - this.startPosition.x) * ((tick - this.startTick) / (this.endTick - this.startTick)) + this.startPosition.x;
+        let y = (this.endPosition.y - this.startPosition.y) * ((tick - this.startTick) / (this.endTick - this.startTick)) + this.startPosition.y;
+
+        return {
+            x,
+            y,
+            direction: this.endPosition.direction,
+            moving: this.endPosition.moving
+        }
+    }
+}
diff --git a/front/src/Phaser/Game/PlayersPositionInterpolator.ts b/front/src/Phaser/Game/PlayersPositionInterpolator.ts
new file mode 100644 (file)
index 0000000..4cc4754
--- /dev/null
@@ -0,0 +1,7 @@
+/**
+ * This class is in charge of computing the position of all players.
+ * Player movement is delayed by 200ms so position depends on ticks.
+ */
+export class PlayersPositionInterpolator {
+
+}
diff --git a/front/tests/Phaser/Game/PlayerMovementTest.ts b/front/tests/Phaser/Game/PlayerMovementTest.ts
new file mode 100644 (file)
index 0000000..f317207
--- /dev/null
@@ -0,0 +1,40 @@
+import "jasmine";
+import {PlayerMovement} from "../../../src/Phaser/Game/PlayerMovement";
+
+describe("Interpolation / Extrapolation", () => {
+    it("should interpolate", () => {
+        let playerMovement = new PlayerMovement({
+            x: 100, y: 200, moving: true, direction: "right"
+        }, 42000,
+            {
+                x: 200, y: 100, moving: true, direction: "up"
+            },
+            42200
+            );
+
+
+        expect(playerMovement.isOutdated(42100)).toBe(false);
+        expect(playerMovement.isOutdated(43000)).toBe(true);
+
+        expect(playerMovement.getPosition(42100)).toEqual({
+            x: 150,
+            y: 150,
+            direction: 'up',
+            moving: true
+        });
+
+        expect(playerMovement.getPosition(42200)).toEqual({
+            x: 200,
+            y: 100,
+            direction: 'up',
+            moving: true
+        });
+
+        expect(playerMovement.getPosition(42300)).toEqual({
+            x: 250,
+            y: 50,
+            direction: 'up',
+            moving: true
+        });
+    });
+})
index e30c2f818e7f2eb777b454b051519072a9c1e2b6..c34c1dd252d6cba41373081c12c7aea788d3e6b0 100644 (file)
@@ -4,7 +4,7 @@
     "sourceMap": true,
     "moduleResolution": "node",
     "noImplicitAny": true,
-    "module": "es6",
+    "module": "CommonJS",
     "target": "es5",
     "jsx": "react",
     "allowJs": true
index b39a4caf8362f185f21ef280c8216564a03b4994..7ed8c19a8519009d643915c478006a8054c0931b 100644 (file)
   resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.0.tgz#551a4589b6ee2cc9c1dff08056128aec29b94880"
   integrity sha512-iYCgjm1dGPRuo12+BStjd1HiVQqhlRhWDOQigNxn023HcjnhsiFz9pc6CzJj4HwDCSQca9bxTL4PxJDbkdm3PA==
 
+"@types/jasmine@^3.5.10":
+  version "3.5.10"
+  resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.5.10.tgz#a1a41012012b5da9d4b205ba9eba58f6cce2ab7b"
+  integrity sha512-3F8qpwBAiVc5+HPJeXJpbrl+XjawGmciN5LgiO7Gv1pl1RHtjoMNqZpqEksaPJW05ViKe8snYInRs6xB25Xdew==
+
 "@types/json-schema@^7.0.3":
   version "7.0.4"
   resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339"
@@ -403,6 +408,11 @@ aproba@^1.1.1:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
 
+arg@^4.1.0:
+  version "4.1.3"
+  resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
+  integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
+
 argparse@^1.0.7:
   version "1.0.10"
   resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
@@ -1204,6 +1214,11 @@ detect-node@^2.0.4:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
 
+diff@^4.0.1:
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
+  integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
+
 diffie-hellman@^5.0.0:
   version "5.0.3"
   resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
@@ -2500,6 +2515,19 @@ isobject@^3.0.0, isobject@^3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
 
+jasmine-core@~3.5.0:
+  version "3.5.0"
+  resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.5.0.tgz#132c23e645af96d85c8bca13c8758b18429fc1e4"
+  integrity sha512-nCeAiw37MIMA9w9IXso7bRaLl+c/ef3wnxsoSAlYrzS+Ot0zTG6nU8G/cIfGkqpkjX2wNaIW9RFG0TwIFnG6bA==
+
+jasmine@^3.5.0:
+  version "3.5.0"
+  resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-3.5.0.tgz#7101eabfd043a1fc82ac24e0ab6ec56081357f9e"
+  integrity sha512-DYypSryORqzsGoMazemIHUfMkXM7I7easFaxAvNM3Mr6Xz3Fy36TupTrAOxZWN8MVKEU5xECv22J4tUQf3uBzQ==
+  dependencies:
+    glob "^7.1.4"
+    jasmine-core "~3.5.0"
+
 js-tokens@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
@@ -2629,6 +2657,11 @@ make-dir@^2.0.0:
     pify "^4.0.1"
     semver "^5.6.0"
 
+make-error@^1.1.1:
+  version "1.3.6"
+  resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
+  integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
+
 map-age-cleaner@^0.1.1:
   version "0.1.3"
   resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a"
@@ -3812,6 +3845,14 @@ source-map-resolve@^0.5.0:
     source-map-url "^0.4.0"
     urix "^0.1.0"
 
+source-map-support@^0.5.17:
+  version "0.5.19"
+  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
+  integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
+  dependencies:
+    buffer-from "^1.0.0"
+    source-map "^0.6.0"
+
 source-map-support@~0.5.12:
   version "0.5.16"
   resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042"
@@ -4169,6 +4210,17 @@ ts-loader@^6.2.2:
     micromatch "^4.0.0"
     semver "^6.0.0"
 
+ts-node@^8.10.2:
+  version "8.10.2"
+  resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d"
+  integrity sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==
+  dependencies:
+    arg "^4.1.0"
+    diff "^4.0.1"
+    make-error "^1.1.1"
+    source-map-support "^0.5.17"
+    yn "3.1.1"
+
 tslib@^1.10.0:
   version "1.13.0"
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
@@ -4605,3 +4657,8 @@ yeast@0.1.2:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
   integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk=
+
+yn@3.1.1:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
+  integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==