From e8daaf5fd381ff70fb9d82616a76de5c52d92d35 Mon Sep 17 00:00:00 2001 From: Eugene Serb <46799701+eugene-serb@users.noreply.github.com> Date: Sat, 10 Jun 2023 21:27:02 +0300 Subject: [PATCH 1/4] #87 up version --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index dafd798..707f4b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "aurora-game-engine", - "version": "1.0.16", + "version": "1.0.17", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "aurora-game-engine", - "version": "1.0.16", + "version": "1.0.17", "license": "GNU GPL v3", "devDependencies": { "@babel/core": "^7.22.5", diff --git a/package.json b/package.json index 1684008..1386155 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aurora-game-engine", - "version": "1.0.16", + "version": "1.0.17", "description": "Aurora game engine for creating 1D and 2D games in JavaScript", "keywords": [ "game-engine", From 79b31a249bf1b84f174e5b895bcf56a744da77f5 Mon Sep 17 00:00:00 2001 From: Eugene Serb <46799701+eugene-serb@users.noreply.github.com> Date: Sat, 10 Jun 2023 21:27:22 +0300 Subject: [PATCH 2/4] #87 Add JSDoc comments --- src/drawer.js | 29 +++++++++++++++++++++++------ src/gameloop.js | 10 ++++++++++ src/gamepad.js | 21 +++++++++++++++++++++ src/helpers.js | 6 ++++++ src/keyboard.js | 8 ++++++++ src/map.js | 29 +++++++++++++++++++++++++++++ src/matrix.js | 37 +++++++++++++++++++++++++++++++++++++ src/rating.js | 27 +++++++++++++++++++++++++++ src/score.js | 22 ++++++++++++++++++++++ src/timer.js | 15 +++++++++++++++ src/touchscreen.js | 10 ++++++++++ 11 files changed, 208 insertions(+), 6 deletions(-) diff --git a/src/drawer.js b/src/drawer.js index 85566cd..f308179 100644 --- a/src/drawer.js +++ b/src/drawer.js @@ -1,6 +1,12 @@ 'use strict'; +/** Class Drawer for painting on canvas. */ export class Drawer { + /** + * Create Drawer class instance. + * @param {HTMLElement} container HTML container for HTML Canvas. + * @param {Array>>} matrix Matrix representing the map. + */ constructor(container, matrix) { if (!container || !matrix) { this.error = 'Error on construct'; @@ -12,6 +18,7 @@ export class Drawer { this.#init(); } + /** Draw matrix on canvas. */ draw() { if (!this.$container || !this.matrix) return this.error; @@ -30,6 +37,10 @@ export class Drawer { } } + /** + * Initialize Drawer class instance. + * @private + */ #init() { this.$container.innerHTML = ''; @@ -40,18 +51,19 @@ export class Drawer { this.#updateSizes(); - window.addEventListener('resize', () => { - this.#updateSizes(); - }); + window.addEventListener('resize', () => this.#updateSizes()); this.media = window.matchMedia('(prefers-color-scheme: dark)'); + this.#updateColours(this.media); - this.media.addEventListener('change', () => { - this.#updateColours(this.media); - }); + this.media.addEventListener('change', () => this.#updateColours(this.media)); } + /** + * Update sizes of the canvas. + * @private + */ #updateSizes() { const width = this.matrix.length; const height = this.matrix[0].length; @@ -69,6 +81,11 @@ export class Drawer { this.draw(); } + /** + * Update sizes of the canvas. + * @param {MediaQueryList} media + * @private + */ #updateColours(media) { if (media.matches) { this.theme = 'dark'; diff --git a/src/gameloop.js b/src/gameloop.js index be2563f..ea87a7f 100644 --- a/src/gameloop.js +++ b/src/gameloop.js @@ -1,10 +1,13 @@ 'use strict'; +/** Class Gameloop to represent game event loop. */ export class Gameloop { + /** Create Gameloop class instance. */ constructor() { this.#init(); } + /** Start the game. */ start() { if (this.isGameOver) { this.clear(); @@ -13,22 +16,29 @@ export class Gameloop { this.canMove = true; } + /** Stop the game. */ stop() { this.isPaused = true; this.canMove = false; clearTimeout(this.interval); } + /** Set game over. */ setGameOver() { this.isGameOver = true; this.stop(); } + /** Reset the game. */ clear() { this.stop(); this.#init(); } + /** + * Initialize Gameloop class instance. + * @private + */ #init() { this.interval = null; this.isGameOver = false; diff --git a/src/gamepad.js b/src/gamepad.js index ca2824b..3f330f7 100644 --- a/src/gamepad.js +++ b/src/gamepad.js @@ -1,11 +1,20 @@ 'use strict'; +/** Class Gamepad for handle gamepad controls. */ export class Gamepad { + /** + * Create Gamepad instance. + * @param {any} context Context object for controls. + */ constructor(context) { this._context = context; this.#init(); } + /** + * Initialize Gamepad class instance. + * @private + */ #init() { if (!this.#checkGamepadSupport()) { return; @@ -20,6 +29,10 @@ export class Gamepad { this.#connectGamepad(); } + /** + * Connect gamepad and listen controls. + * @private + */ #connectGamepad() { window.addEventListener('gamepadconnected', () => { const update = () => { @@ -48,6 +61,10 @@ export class Gamepad { }); } + /** + * Handle controls of the gamepad. + * @private + */ #handle(button) { if (button === 0) { this._context.moveToUp(); @@ -88,6 +105,10 @@ export class Gamepad { } } + /** + * Check gamepad's support. + * @private + */ #checkGamepadSupport() { return 'getGamepads' in window.navigator; } diff --git a/src/helpers.js b/src/helpers.js index 859720d..c0854cc 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -1,5 +1,11 @@ 'use strict'; +/** + * Get a random integer number. + * @param {number} min Minimum. + * @param {number} max Maximum. + * @returns {number} Random integer number. + */ export function getRandomInteger(min, max) { const i = min && typeof min === 'number' ? min : 0; const j = max && typeof max === 'number' ? max : 0; diff --git a/src/keyboard.js b/src/keyboard.js index 1bfbb66..236657e 100644 --- a/src/keyboard.js +++ b/src/keyboard.js @@ -1,11 +1,19 @@ 'use strict'; +/** Class Keyboard for handle keyboard controls. */ export class Keyboard { + /** Create Keyboard class instance. + * @param {any} context Context object for controls. + */ constructor(context) { this._context = context; this.#handle(); } + /** + * Handle controls of the keyboard. + * @private + */ #handle() { window.addEventListener('keydown', (e) => { if (!this._context.isGameOver) { diff --git a/src/map.js b/src/map.js index 3f6bc4c..c829ed5 100644 --- a/src/map.js +++ b/src/map.js @@ -2,7 +2,19 @@ import Matrix from './matrix.js'; +/** + * Class map to represent the map. + * @extends Matrix + */ export class Map extends Matrix { + /** + * Create Map class instance. + * @param {number} width Matrix width. + * @param {number} height Matrix height. + * @param {any} emptyValue Default empty value. + * @param {Array>} matrix Another matrix for fill new Matrix instance. + * @param {object<{x: boolean, y: boolean}>} transfer Explain on which axes the map is closed. + */ constructor(width, height, emptyValue, matrix, transfer) { super(width, height, emptyValue, matrix); @@ -10,6 +22,12 @@ export class Map extends Matrix { this.transferY = typeof transfer?.y === 'boolean' ? transfer.y : false; } + /** + * Get new coordinates based on start position and difference. + * @param {object<{x: number, y: number}>} start Point object with key 'x': number and 'y': number. + * @param {object<{x: number, y: number}>} delta Point object with key 'x': number and 'y': number. + * @returns {object<{x: number, y: number}>} New position. + */ getCoords(start, delta) { const sx = start?.x && typeof start?.x === 'number' ? Math.abs(Math.trunc(start.x)) : 0; @@ -28,6 +46,11 @@ export class Map extends Matrix { return { x, y }; } + /** + * Get X position. + * @param {number} x Position on x-axe. + * @returns {number} New x-axe position. + */ #getX(x) { let result = null; @@ -42,6 +65,12 @@ export class Map extends Matrix { return result; } + /** + * Get Y position. + * @param {number} x Position on x-axe. + * @param {number} y Position on y-axe. + * @returns {number} New y-axe position. + */ #getY(x, y) { let result = null; diff --git a/src/matrix.js b/src/matrix.js index 85d51e2..3018c65 100644 --- a/src/matrix.js +++ b/src/matrix.js @@ -1,6 +1,14 @@ 'use strict'; +/** Class Matrix for representing matrix */ export class Matrix { + /** + * Create Matrix class instance. + * @param {number} width Matrix width. + * @param {number} height Matrix height. + * @param {any} emptyValue Default empty value. + * @param {Array>} matrix Another matrix for fill new Matrix instance. + */ constructor(width, height, emptyValue, matrix) { this.EMPTY_VALUE = typeof emptyValue !== 'undefined' ? emptyValue : 0; @@ -12,6 +20,13 @@ export class Matrix { } } + /** + * Generate new matrix. + * @param {number} width Matrix width. + * @param {number} height Matrix height. + * @param {any} emptyValue Default empty value. + * @returns {Array>} New matrix value. + */ generate(width, height, emptyValue) { const w = width && typeof width === 'number' ? Math.abs(Math.trunc(width)) : 1; const h = height && typeof height === 'number' ? Math.abs(Math.trunc(height)) : 1; @@ -29,10 +44,18 @@ export class Matrix { return result; } + /** + * Clone Matrix instance. + * @returns {Matrix} Cloned matrix instance. + */ clone() { return new Matrix(null, null, this.EMPTY_VALUE, this.copy()); } + /** + * Get the copy of the Matrix instance value. + * @returns {Array>} A copy of the value of the Matrix instance. + */ copy() { const result = this.generate(this.value.length, this.value[0].length, this.EMPTY_VALUE); @@ -45,6 +68,11 @@ export class Matrix { return result; } + /** + * Crop the Matrix value at specified coordinates. + * @param {object<{x: boolean, y: boolean}>} start Start position. + * @param {object<{x: boolean, y: boolean}>} end End position. + */ crop(start, end) { const width = Math.abs(end.x - start.x); const height = Math.abs(end.y - start.y); @@ -62,6 +90,11 @@ export class Matrix { this.value = result; } + /** + * Insert figure into Matrix. + * @param {Array>} matrix Figure for insert into Matrix value. + * @param {object<{x: boolean, y: boolean}>} start Start position. + */ insert(matrix, start) { const result = this.copy(); @@ -82,16 +115,19 @@ export class Matrix { this.value = result; } + /** Flip matrix on x-axis */ reflectX() { this.value.reverse(); } + /** Flip matrix on y-axis */ reflectY() { this.value.forEach((column) => { column.reverse(); }); } + /** Rotate matrix left */ rotateLeft() { const result = this.generate(this.value[0].length, this.value.length, this.EMPTY_VALUE); @@ -106,6 +142,7 @@ export class Matrix { this.value = result; } + /** Rotate matrix right */ rotateRight() { const result = this.generate(this.value[0].length, this.value.length, this.EMPTY_VALUE); diff --git a/src/rating.js b/src/rating.js index 206b97c..c716013 100644 --- a/src/rating.js +++ b/src/rating.js @@ -1,17 +1,31 @@ 'use strict'; +/** Class Rating for rating. */ export class Rating { + /** + * Create Rating class instance. + * @param {string} key Unique key to use in local storage. + */ constructor(key) { this._key = key; this._value = []; this.#getLocalStorage(); } + /** + * Get the current rating state. + * @returns {Array>} Rating state. + */ get value() { this.#getLocalStorage(); return this._value; } + /** + * Add new record to the rating. + * @param {number} score Score of the record. + * @param {string} time Time of the record. + */ add(score, time) { if (!score || typeof score !== 'number') return; if (!time || typeof time !== 'string') return; @@ -23,11 +37,18 @@ export class Rating { this.#setLocalStorage(); } + /** + * Delete all records. + */ clean() { this._value = []; this.#setLocalStorage(); } + /** + * Sort records. + * @private + */ #sort() { this._value.sort(function (a, b) { if (a.score < b.score) return 1; @@ -35,10 +56,16 @@ export class Rating { }); } + /** + * Set record state to the local storage. + */ #setLocalStorage() { localStorage.setItem(this._key, JSON.stringify(this._value)); } + /** + * Get record state from the local storage. + */ #getLocalStorage() { localStorage[this._key] ? (this._value = JSON.parse(localStorage[this._key])) diff --git a/src/score.js b/src/score.js index f58d55a..d0bc80e 100644 --- a/src/score.js +++ b/src/score.js @@ -1,14 +1,27 @@ 'use strict'; +/** Class Score for scoring. */ export class Score { + /** + * Create Score class instance. + * @param {number} value + */ constructor(value) { this._value = value && typeof value === 'number' ? value : 0; } + /** + * Get the current score. + * @returns {number} Score. + */ get value() { return this._value; } + /** + * Set new score. + * @param {number} value New score. + */ set value(value) { if (value && typeof value === 'number') { this._value = value; @@ -17,14 +30,23 @@ export class Score { } } + /** + * Increase the score by a value, or by one if the value is empty. + * @param {number} value The value by which to increase the score. + */ increase(value) { this._value += value && typeof value === 'number' ? value : 1; } + /** + * Decrease the score by a value, or by one if the value is empty. + * @param {number} value The value by which to decrease the score. + */ decrease(value) { this._value -= value && typeof value === 'number' ? value : 1; } + /** Reset the score to zero. */ reset() { this._value = 0; } diff --git a/src/timer.js b/src/timer.js index 1b2e247..4a22ac6 100644 --- a/src/timer.js +++ b/src/timer.js @@ -1,25 +1,40 @@ 'use strict'; +/** Class Timer for counting time from the beginning of the measurement. */ export class Timer { + /** Create Timer class instance. */ constructor() { this.#init(); } + /** + * Get the current time. + * @returns {string} Time. + */ get value() { this.#update(); return this._value; } + /** Reset time. */ reset() { this.#init(); } + /** + * Initialize Timer class instance. + * @private + */ #init() { this._timeStart = Date.now(); this._timeNow = this._timeStart; this._value = '00:00'; } + /** + * Update the timer state. + * @private + */ #update() { this._timeNow = Date.now(); diff --git a/src/touchscreen.js b/src/touchscreen.js index 2b1e298..0bb6ecf 100644 --- a/src/touchscreen.js +++ b/src/touchscreen.js @@ -1,12 +1,22 @@ 'use strict'; +/** Class Touchscreen for handle touch controls. */ export class Touchscreen { + /** + * Create Touchscreen class instance. + * @param {any} context Context object for controls. + * @param {HTMLElement} container HTML element to receive touches on it. + */ constructor(context, container) { this._context = context; this._container = container; this.#handle(); } + /** + * Handle controls of the touchscreen. + * @private + */ #handle() { let startX = 0; let startY = 0; From cd497871982b1f15cdb903083f83136ffb62d9ac Mon Sep 17 00:00:00 2001 From: Eugene Serb <46799701+eugene-serb@users.noreply.github.com> Date: Sat, 10 Jun 2023 21:28:23 +0300 Subject: [PATCH 3/4] #87 new build --- docs/index.html | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/docs/index.html b/docs/index.html index f754bc8..80d66e0 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,16 +1,26 @@ Aurora Game Engine

Eugene Serb – Aurora Game Engine

Aurora Game Engine

Let's have fun!
Score: 0 Time: 00:00
Rotate
W and and A
Down
S and and
Left
A and and
Rigth
D and and
Restart
R and START
Pause
P and BACK

Your records:

#ScoreTimeDate
\ No newline at end of file + ym(79722217, 'init', { + clickmap: true, + trackLinks: true, + accurateTrackBounce: true, + webvisor: true, + });

Eugene Serb – Aurora Game Engine

Aurora Game Engine

Let's have fun!
Score: 0 Time: 00:00
Rotate
W and and A
Down
S and and
Left
A and and
Rigth
D and and
Restart
R and START
Pause
P and BACK

Your records:

#ScoreTimeDate
\ No newline at end of file From 55fe90f5e18fd572e44d9e85ac40b9e7c8d5e376 Mon Sep 17 00:00:00 2001 From: Eugene Serb <46799701+eugene-serb@users.noreply.github.com> Date: Sat, 10 Jun 2023 21:34:14 +0300 Subject: [PATCH 4/4] #87 update README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2d9e34d..f18c9db 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Based on game engines from these games and using them for implementation and tes ![](https://img.shields.io/badge/ESLint-informational?style=flat-square&logo=eslint&logoColor=FFFFFF&color=8181F2) ![](https://img.shields.io/badge/Prettier-informational?style=flat-square&logo=prettier&logoColor=FFFFFF&color=1A2B34) ![](https://img.shields.io/badge/Jest-informational?style=flat-square&logo=jest&logoColor=FFFFFF&color=15C213) +![](https://img.shields.io/badge/📝-JSDoc-informational?style=flat-square&logo=jsdoc&logoColor=FFFFFF&color=006FBB&labelColor=006FBB) ![](https://img.shields.io/badge/npm-informational?style=flat-square&logo=npm&logoColor=FFFFFF&color=CB0000) ![](https://img.shields.io/badge/GitHub-informational?style=flat-square&logo=github&logoColor=FFFFFF&color=24292F) ![](https://img.shields.io/badge/GitHub%20Actions-informational?style=flat-square&logo=github&logoColor=FFFFFF&color=24292F)