From afe55c68381b42adffb01085663d4eccb80768de Mon Sep 17 00:00:00 2001
From: Himanshu Jangid
Date: Tue, 19 Sep 2023 21:43:34 +0530
Subject: [PATCH] add object specific update method example
This will help modularize the framework and write object specific code in different files.
---
.github/labeler.yml | 23 +++++-----
.huskyrc | 12 +++++
examples/index.html | 1 +
examples/mouse-inputs/index.html | 7 +--
examples/update/index.html | 73 +++++++++++++++++++++++++++++++
examples/update/script.ts | 34 ++++++++++++++
examples/vite.config.js | 3 +-
lib/render/engine.ts | 11 +++--
lib/render/objects/base-object.ts | 9 ++++
lib/render/renderer.ts | 11 ++++-
10 files changed, 159 insertions(+), 25 deletions(-)
create mode 100644 .huskyrc
create mode 100644 examples/update/index.html
create mode 100644 examples/update/script.ts
diff --git a/.github/labeler.yml b/.github/labeler.yml
index dac8303..e11deaf 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -1,29 +1,32 @@
Examples:
-- 'examples/**'
+ - 'examples/**'
Library:
-- 'lib/**'
+ - 'lib/**'
ReadMe:
-- 'readme.md'
+ - 'readme.md'
CodeEditor:
-- '.vscode/**'
+ - '.vscode/**'
Tests:
-- any: ['test/**', '**/*.test.ts', '**/*.test.js']
+ - any: ['test/**', '**/*.test.ts', '**/*.test.js']
Core:
-- 'lib/core/**'
+ - 'lib/core/**'
CoreWithTests:
-- all: ['lib/core/**', 'test/**']
+ - all: ['lib/core/**', 'test/**']
Actions:
-- '.github/**'
+ - '.github/**'
Docs:
-- 'Docs/**'
+ - 'Docs/**'
Types:
-- 'lib/types/**'
+ - 'lib/types/**'
+
+Packages:
+ - '**/**/package*.json'
diff --git a/.huskyrc b/.huskyrc
new file mode 100644
index 0000000..40f4484
--- /dev/null
+++ b/.huskyrc
@@ -0,0 +1,12 @@
+# First load nvm and provide access to the nvm command.
+export NVM_DIR="$HOME/.nvm"
+ [ -s "/usr/local/opt/nvm/nvm.sh" ] && . "/usr/local/opt/nvm/nvm.sh"
+
+# Use the nvm ls command to detect the version being used.
+export NVM_DIR="$HOME/.nvm"
+a=$(nvm ls | grep 'node')
+b=${a#*(-> }
+v=${b%%[)| ]*}
+
+# Export the current version in your path for husky to find.
+export PATH="$NVM_DIR/versions/node/$v/bin:$PATH"
\ No newline at end of file
diff --git a/examples/index.html b/examples/index.html
index c9d3606..1e0342c 100644
--- a/examples/index.html
+++ b/examples/index.html
@@ -20,6 +20,7 @@ We got examples for you
Drawing
Colors
Mouse Inputs
+ Update
-
diff --git a/examples/update/index.html b/examples/update/index.html
new file mode 100644
index 0000000..54d7586
--- /dev/null
+++ b/examples/update/index.html
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MiniPoint Colors
+
+
+ Single Objects also have their own update method
+
+
+
+ import { Engine, Point } from '../../lib';
+
+const engine = new Engine(
+ document.getElementById('canvas') as HTMLCanvasElement,
+ {
+ engineOptions: {
+ width: 600,
+ height: 400,
+ },
+ },
+);
+
+const { renderer, input } = engine;
+
+// we will always get the engine as parameter for any use.
+engine.update = (_engine) => {
+ if (input.mouse.click) {
+ const p1 = new Point({
+ x: input.mouse.position.x,
+ y: input.mouse.position.y,
+ radius: 6,
+ color: `rgb(${Math.random() * 255}, ${Math.random() * 255}, ${
+ Math.random() * 255
+ })`,
+ });
+
+ // this is object specific update method, it could be conditional as well.
+ p1.update = () => {
+ p1.options.radius = (p1.options.radius ?? 0) + 0.1;
+ };
+
+ renderer.addObject(p1);
+ }
+};
+
+
+
+
+
+
+
diff --git a/examples/update/script.ts b/examples/update/script.ts
new file mode 100644
index 0000000..dff8084
--- /dev/null
+++ b/examples/update/script.ts
@@ -0,0 +1,34 @@
+import { Engine, Point } from '../../lib';
+
+const engine = new Engine(
+ document.getElementById('canvas') as HTMLCanvasElement,
+ {
+ engineOptions: {
+ width: 600,
+ height: 400,
+ },
+ },
+);
+
+const { renderer, input } = engine;
+
+// we will always get the engine as parameter for any use.
+engine.update = (_engine) => {
+ if (input.mouse.click) {
+ const p1 = new Point({
+ x: input.mouse.position.x,
+ y: input.mouse.position.y,
+ radius: 6,
+ color: `rgb(${Math.random() * 255}, ${Math.random() * 255}, ${
+ Math.random() * 255
+ })`,
+ });
+
+ // this is object specific update method, it could be conditional as well.
+ p1.update = () => {
+ p1.options.radius = (p1.options.radius ?? 0) + 0.1;
+ };
+
+ renderer.addObject(p1);
+ }
+};
diff --git a/examples/vite.config.js b/examples/vite.config.js
index 81b2457..c445fd8 100644
--- a/examples/vite.config.js
+++ b/examples/vite.config.js
@@ -10,7 +10,8 @@ export default defineConfig({
point: resolve(__dirname, 'point/index.html'),
drawing: resolve(__dirname, 'drawing/index.html'),
colors: resolve(__dirname, 'colors/index.html'),
- colors: resolve(__dirname, 'mouse-inputs/index.html'),
+ mouse_inputs: resolve(__dirname, 'mouse-inputs/index.html'),
+ update: resolve(__dirname, 'update/index.html'),
},
},
},
diff --git a/lib/render/engine.ts b/lib/render/engine.ts
index f732667..0813190 100644
--- a/lib/render/engine.ts
+++ b/lib/render/engine.ts
@@ -72,10 +72,10 @@ export class Engine {
}
this.input = new Input(this);
- this.start();
+ this.start(this);
const render = () => {
- this.update();
+ this.update(this);
if (options.engineOptions!.clearEachFrame) {
this.context?.clearRect(0, 0, this.width, this.height);
}
@@ -84,7 +84,7 @@ export class Engine {
requestAnimationFrame(render);
};
- this.renderer = new Renderer(this.context);
+ this.renderer = new Renderer(this);
render();
// Set useful options to window
@@ -94,9 +94,8 @@ export class Engine {
window.MiniPointDefaultRenderer = this.renderer;
}
- // two methods that can be overridden
- start() {}
- update() {}
+ update: (engine: Engine) => void = (_engine: Engine) => {};
+ start: (engine: Engine) => void = (_engine: Engine) => {};
// reset single frame events
resetEvent() {
diff --git a/lib/render/objects/base-object.ts b/lib/render/objects/base-object.ts
index 340abba..b6c6462 100644
--- a/lib/render/objects/base-object.ts
+++ b/lib/render/objects/base-object.ts
@@ -1,6 +1,7 @@
import { v4 } from 'uuid';
import { DrawableObjectOptions, BaseObjectInterface } from '../../types';
import { Renderer } from '../renderer';
+import { Engine } from '../engine';
/**
* The Base Object Class
@@ -10,6 +11,8 @@ export abstract class BaseObject implements BaseObjectInterface {
options: T & DrawableObjectOptions;
context: CanvasRenderingContext2D;
renderer: Renderer;
+ // TODO: Later add support for child elements
+ children: (T & BaseObject)[];
constructor(options: DrawableObjectOptions, renderer?: Renderer) {
this.options = options;
this.id = v4();
@@ -20,15 +23,21 @@ export abstract class BaseObject implements BaseObjectInterface {
this.renderer = renderer;
}
+ this.children = [];
// add the object to default or provided renderer
this.renderer.addObject(this);
this.context = this.renderer.context;
+ this.start(this.renderer.engine);
this.checkDrawConditionAndDraw();
}
abstract draw(): K;
+ update: (engine: Engine) => void = (_engine: Engine) => {};
+ start: (engine: Engine) => void = (_engine: Engine) => {};
+
checkDrawConditionAndDraw() {
+ this.update(this.renderer.engine);
if (this.options.show) {
this.draw();
}
diff --git a/lib/render/renderer.ts b/lib/render/renderer.ts
index 69163ab..97b6d25 100644
--- a/lib/render/renderer.ts
+++ b/lib/render/renderer.ts
@@ -2,12 +2,19 @@ import { forEach } from 'lodash';
import { DefaultPointOptions } from '../constants';
import { BaseObjectInterface, BaseRenderer, PointOptions } from '../types';
import { Point } from './objects';
+import { Engine } from './engine';
/**
* The class that is responsible for drawing
*/
export class Renderer extends BaseRenderer {
- constructor(context: CanvasRenderingContext2D) {
- super(context);
+ engine: Engine;
+ constructor(engine: Engine) {
+ if (!engine.context)
+ throw new Error(
+ "Context wan't found while initializing renderer, please check your code",
+ );
+ super(engine.context);
+ this.engine = engine;
}
render() {