Skip to content
/ FlyJs Public

simple open source library for game development

Notifications You must be signed in to change notification settings

alle0017/FlyJs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

56 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

This engine is all open source, feel free to take it, change it and use it as you wish. if you want, contact me, I'm a beginner in the world of rendering, so all suggestions are welcome. if this library was useful, please, consider making a donation. Thanks and good use.

INTENTION

this engine is intended to be more like a library, very lightweight, without the use of any additional external libraries. Also, the engine's purpose is to be beginner friendly, something like microsoft make code arcade (see here). This repository is intended to be either a documentation and a sort of book of journeys (check here), for the once who wants to learn how to program an engine, from how webgl and webgpu works to the game algorithms.

TABLE OF CONTENTS

ARCHITECTURE

-architecture

PROJECT TREE

-tree

API

GAME CLASS

-get
-debug
-renderer

RENDERER

-interface
-clearColor
-culling
-append
-setAttributes
-remove
-draw

DEBUG

-drawXYGrid
-drawXZGrid
-drawYZGrid
-removeGrids
-globalCamera

TYPES

-DrawOpt
-DrawableImageOptions
-SkeletalAnimationOptions
-BonesOpt
-Point3D
-Point2D

NEXT STEPS

-Next step

DOCUMENTATION

-Documentation

ARCHITECTURE IDEA

graph TD;
WEBGL-->RENDERER
WEBGPU-->RENDERER
indexDB_SAVING_SYSTEM --> GAME
MOBILE_SUPPORT --> GAME
RENDERER --> GAME
PHYSICS_ENGINE --> GAME
OBSERVABLE --> GAME
EVENT_SYSTEM --> GAME
GAME --> SAVINGS
GAME --> MOBILE_API
GAME --> ENTITIES
GAME --> EVENT_HANDLER
ENTITIES --> PARTICLES_SYSTEM
ENTITIES --> SPRITE_3D
ENTITIES --> TILES
TILES --> TILE_MAP
SPRITE_3D --> SPRITE_2D
EVENT_SYSTEM --> OBSERVABLE

FOLDER STRUCTURE

game library
├─ .DS_Store
├─ .vscode
│  └─ settings.json
├─ controller
│  ├─ canvasDelegate.ts
│  ├─ debug.ts
│  ├─ gameController.ts
│  ├─ loadData.ts
│  └─ loopController.ts
├─ entities
├─ icon.webp
├─ index.d.ts
├─ index.html
├─ main.ts
├─ material for getting started.md
├─ pipeline.jpg
├─ prova.png
├─ readme.md
├─ rendering
│  ├─ .DS_Store
│  ├─ GLRenderer.ts
│  ├─ GPURenderer.ts
│  ├─ codeDelegates
│  │  ├─ GLcode.ts
│  │  └─ GPUcode.ts
│  ├─ matrix
│  │  ├─ camera.ts
│  │  ├─ matrices.ts
│  │  └─ viewMatrix.ts
│  ├─ programSetterDelegate.ts
│  ├─ rendererModel.ts
│  ├─ shaders
│  │  ├─ GLShaders.ts
│  │  ├─ GPUShader.ts
│  │  └─ shaderModel.ts
│  ├─ shapes.ts
│  ├─ tree.ts
│  └─ types.ts
├─ src
│  ├─ controller
│  │  ├─ canvasDelegate.js
│  │  ├─ debug.js
│  │  ├─ gameController.js
│  │  ├─ loadData.js
│  │  └─ loopController.js
│  ├─ entities
│  │  └─ entity.js
│  ├─ main.js
│  └─ rendering
│     ├─ GLRenderer.js
│     ├─ GPUrenderer.js
│     ├─ codeDelegates
│     │  ├─ GLcode.js
│     │  └─ GPUcode.js
│     ├─ generics.js
│     ├─ matrix
│     │  ├─ camera.js
│     │  ├─ matrices.js
│     │  └─ viewMatrix.js
│     ├─ programSetterDelegate.js
│     ├─ rendererModel.js
│     ├─ shaders
│     │  ├─ GLShaders.js
│     │  ├─ GPUShader.js
│     │  └─ shaderModel.js
│     ├─ shapes.js
│     ├─ tree.js
│     └─ types.js
├─ tsconfig.json
└─ vertex.txt

GAME CLASS

import { Load } from './controller/loadData.js';
import { GameController } from './controller/gameController.js';


const game = await GameController.get();
const img = await Load.image( 'pipeline.jpg' );
const image =  game.$renderer.create({
      indices: [
            0,1,2,
            0,2,3,
       ],
      vertices: [ 
            -1,  1, 0,
            -1, -1, 0,
            1, -1, 0,
            1,  1, 0,
      ],
      imageData: {
            image: img,
            textureCoords: [

                  1,  1,
                  0,  1, 
                  0, 0,
                  1, 0, 
            ]
      },,
      perspective: true
})
 game.$renderer.append( 'img', image ).setAttributes('img', { 
      translation: {x: 0, y: 0, z: -5}, 
      scale: 0.5
})
const f = ()=>{
       game.$renderer.draw();
      requestAnimationFrame(f)
}
f();

get

get(): Promise<GameController>


this method returns the instance of the class (singleton). it creates (and append to the dom) the canvas in which all will be rendered

renderer

public readonly renderer: Renderer


is used to create and draw objects ( see the example or renderer methods). can be an instance of WebGLRenderer or WebGPURenderer (if available)

debug

public readonly debug: Debug


instance of class Debug. it contains utility methods for debugging.

RENDERER

import { Shapes } from './rendering/shapes.js';
import { Renderer } from './rendering/GPURenderer.js'; // './rendering/GLRenderer.js'; 
const color = [...] //your colors data
const renderer = new Renderer( myCanvas );
await renderer.init(); // initialize the renderer
const myCube = renderer.create({
      ...Shapes.cube( 0.1 ),
      color,
      perspective: true // use Perspective in your object
});
renderer.append( 'cube', myCube );
const f = ()=>{
      // if you want to make dynamic your object use renderer.setAttributes('myCube', { opt... })
      renderer.draw();
      requestAnimationFrame(f);
}
f();

interface

interface Renderer {
      clearColor: Color;
      culling: boolean;
      init(): Promise<Renderer>;
      create( opt: DrawableElementAttributes ): RenderFunction;
      append( name: string, func: RenderFunction ): Renderer;
      remove( name: string ): RenderFunction | undefined;
      setAttributes( name: string, attributes: DrawOpt ): Renderer;
      draw(): void;
}

clearColor

public clearColor: Color;


color used to clear the screen

culling

public culling: boolean;


set culling if enabled

create

create( DrawableElementAttributes ): RenderFunction


accept DrawableElementAttributes as parameter and create new instance of RenderFunction, that represents the way in which the render will draw your object on the canvas.

append

append( string, RenderFunction ): Renderer;


accept string and RenderFunction as parameter. Start rendering what RenderFunction represents. the string is an identifier for that specific object.

setAttributes

setAttributes( string, DrawOpt ): Renderer;


accept string and DrawOpt as parameter. Changes the values of the object (specified by the string accepted as first argument) attributes on rendering. if not necessary, don't call this function.

remove

remove( string ): RenderFunction | undefined;


remove the object named with the string passed as first argument. return the RenderFunction deleted.

draw

draw(): void;


draw all the objects actually attached to the renderer

DEBUG

constructor( GameController ): Debug

drawXYGrid

drawXYGrid( Color ): void


draw a grid of the color specified (default to red) parallel to the z axis

drawXZGrid

drawXZGrid( Color ): void


draw a grid of the color specified (default to red) parallel to the y axis

drawYZGrid

drawYZGrid( Color ): void


draw a grid of the color specified (default to red) parallel to the x axis

removeGrids

removeGrids(): void


remove all the grids currently on the screen

globalCamera

globalCamera(): void


add commands to move a debug camera

TYPES

DrawOpt

type DrawOpt = Partial<{
      angle: number;
      /**
       * 'x' 'y' or 'z'
       * @use Axis in generics.ts as enum to represent the different axis
       */
      axis: Axis;
      /**
       * whether or not to convert angle to radiants
       */
      toRad: boolean;
      /**
       * the rotation matrix 3d, so a 4x4 matrix ( you can use Matrix.rotate to get once)
       * @see Matrix in matrix.ts
       */
      rotationMatrix: number[];
      /**
       * the translation matrix 3d, so a 4x4 matrix ( you can use Matrix.translate to get once)
       * @see Matrix in matrix.ts
       */
      translationMatrix: number[];
      /**
       * 3d vector that translate (moves) the element in the space
       */
      translation: Point3D;
      /**
       * projection matrix 
       * @TODO add someway of projection matrix generation in Matrix
       */
      projectionMatrix: number[];
      /**
      * the scale to use for reduce/enlarge objects
      */
      scale: number | Point3D;
      /**
      * the scale matrix 3d, so a 4x4 matrix ( you can use Matrix.scale to get once)
      * @see Matrix in matrix.ts
      */
      scaleMatrix: number[];
      camera: Camera;
      transformationMatrix: number[];
      /**
       * vectors that indicate where the actual frame and costume of image atlas (sprite sheet) you want to draw
       */
      animationVector: [number, number];
      bumpScale: number;
      bones: Partial<BonesOpt>
}>;

DrawableElementOptions

type DrawableElementOptions = {
      color: number[];
      indices: number[];
      staticColor: Color;
      static: boolean;
      perspective: boolean;
      imageData: DrawableImageOptions;
      primitive: Primitives;
      bonesData: SkeletalAnimationOptions;
}

DrawableImageOptions

type DrawableImageOptions = {
      // coordinates of the texture in the space
      textureCoords: number[];
      //image to use
      image: ImageBitmap; 
      //if you want to animate your image
      animate?: boolean;
      // image used for displacement mapping
      displacementMap?: ImageBitmap;
}

SkeletalAnimationOptions

type SkeletalAnimationOptions = {
      bones: number;
      weights: number[];
      indices: number[];
      root: number;
}

BonesOpt

type BonesOpt = {
      angle: number[];
      translate: Point3D[];
}

Point3D

type Point3D = {
      x: number,
      y: number,
      z: number,
}

Point2D

type Point2D = {
      x: number,
      y: number,
}

NEXT STEPS

LEGEND

  • done: "already implemented"
  • on-going: "actually working at..."
  • coming soon: "the next step"
  • ideally: "if possible, in the future will be supported"
checklist feature status
global game object on-going
✔️ webgpu texture done
✔️ webgpu dynamic bindings definition ( create an array of all the bindings) done
✔️ webgpu uniforms done
✔️ webgl texture done
✔️ webgl uniforms done
implement lights coming soon
✔️ implement skeletal animations on webgpu done
✔️ implement skeletal animations on webgl done
✔️ implement a fallback system with possibility of require specific api for the renderer done

DOCUMENTATION

this section contains all the material used to study rendering (by me), and that I'd thought could be helpful for the beginners

WebGL

-WebGL Fundamentals
-Mozilla docs

WebGPU

-WebGPU Step By Step
-Raw WebGPU
-code labs google tutorial
-Mozilla docs
-WebGPU Fundamentals

VARIOUS RENDERING TECHNIQUES

-WebGL skeletal animation
-Skeletal Animation: from math to code
-Skeletal Animation
-WebGPU API for C++
-WebGPU for Metal developers
-Render grass