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/mouse-inputs/index.html b/examples/mouse-inputs/index.html index 1191bc8..e7f0cfb 100644 --- a/examples/mouse-inputs/index.html +++ b/examples/mouse-inputs/index.html @@ -26,12 +26,7 @@ MiniPoint Colors -
    - Various Mouse Input Examples -
    - - -
    +
    Mouse Click Event Examples
    
    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() {