mirror of
https://github.com/Aviortheking/games.git
synced 2025-06-08 12:59:54 +00:00
u
Signed-off-by: Avior <github@avior.me>
This commit is contained in:
parent
8952b61651
commit
79b74d16d5
68
docs/classModel.puml
Normal file
68
docs/classModel.puml
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
@startuml classes
|
||||||
|
!theme toy
|
||||||
|
|
||||||
|
class GameEngine {
|
||||||
|
- scenes: Record<string, Scene>
|
||||||
|
|
||||||
|
+ addScene(scene: Scene): void
|
||||||
|
+ setScene(id: string): void
|
||||||
|
+ removeScene(scene: string | Scene): void
|
||||||
|
+ start(): void
|
||||||
|
+ pause(): void
|
||||||
|
+ destroy(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
class Scene {
|
||||||
|
+ id: string
|
||||||
|
|
||||||
|
+ setCamera(id: String): void
|
||||||
|
+ addComponents(components: ...Component2D): void
|
||||||
|
+ removeComponents(components: ...(Component2D | string)): void
|
||||||
|
}
|
||||||
|
|
||||||
|
GameEngine "1" -- "0-*" Scene : "contains"
|
||||||
|
|
||||||
|
class Component {
|
||||||
|
+ id: string
|
||||||
|
+ position: Vector2D
|
||||||
|
+ renderer: Renderer
|
||||||
|
+ position: Vector2D
|
||||||
|
+ scale: Vector2D
|
||||||
|
+ collider: Collider
|
||||||
|
+ origin: Vector2D
|
||||||
|
+ childs: Array<Component2D>
|
||||||
|
+ debug: boolean
|
||||||
|
|
||||||
|
+ init(): void
|
||||||
|
+ update(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
Scene "1" -- "0-*" Component : "contains"
|
||||||
|
|
||||||
|
class Camera extends Component {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Pointer extends Component {}
|
||||||
|
|
||||||
|
class Asset {}
|
||||||
|
|
||||||
|
class Sound {}
|
||||||
|
|
||||||
|
class Tileset {}
|
||||||
|
|
||||||
|
Component -- Component
|
||||||
|
Tileset -- Asset
|
||||||
|
|
||||||
|
class Vector2D {
|
||||||
|
+ x: number
|
||||||
|
+ y: number
|
||||||
|
}
|
||||||
|
|
||||||
|
class Collider {}
|
||||||
|
|
||||||
|
Component "1" -- "0-1" Collider
|
||||||
|
|
||||||
|
Component "1" -- "0-*" Vector2D
|
||||||
|
|
||||||
|
@enduml
|
24
package-lock.json
generated
24
package-lock.json
generated
@ -9191,7 +9191,8 @@
|
|||||||
"@next/react-refresh-utils": {
|
"@next/react-refresh-utils": {
|
||||||
"version": "11.0.0",
|
"version": "11.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@next/react-refresh-utils/-/react-refresh-utils-11.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@next/react-refresh-utils/-/react-refresh-utils-11.0.0.tgz",
|
||||||
"integrity": "sha512-hi5eY+KBn4QGtUv7VL2OptdM33fI2hxhd7+omOFmAK+S0hDWhg1uqHqqGJk0W1IfqlWEzzL10WvTJDPRAtDugQ=="
|
"integrity": "sha512-hi5eY+KBn4QGtUv7VL2OptdM33fI2hxhd7+omOFmAK+S0hDWhg1uqHqqGJk0W1IfqlWEzzL10WvTJDPRAtDugQ==",
|
||||||
|
"requires": {}
|
||||||
},
|
},
|
||||||
"@nodelib/fs.scandir": {
|
"@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
@ -9601,7 +9602,8 @@
|
|||||||
"version": "5.3.1",
|
"version": "5.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
|
||||||
"integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
|
"integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"requires": {}
|
||||||
},
|
},
|
||||||
"ajv": {
|
"ajv": {
|
||||||
"version": "6.12.6",
|
"version": "6.12.6",
|
||||||
@ -9617,7 +9619,8 @@
|
|||||||
"ajv-keywords": {
|
"ajv-keywords": {
|
||||||
"version": "3.5.2",
|
"version": "3.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
|
||||||
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ=="
|
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
|
||||||
|
"requires": {}
|
||||||
},
|
},
|
||||||
"alphanum-sort": {
|
"alphanum-sort": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
@ -11218,7 +11221,8 @@
|
|||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz",
|
||||||
"integrity": "sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==",
|
"integrity": "sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"requires": {}
|
||||||
},
|
},
|
||||||
"eslint-scope": {
|
"eslint-scope": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
@ -11715,7 +11719,8 @@
|
|||||||
"icss-utils": {
|
"icss-utils": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
|
||||||
"integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA=="
|
"integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
|
||||||
|
"requires": {}
|
||||||
},
|
},
|
||||||
"ieee754": {
|
"ieee754": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
@ -12382,7 +12387,8 @@
|
|||||||
"next-plausible": {
|
"next-plausible": {
|
||||||
"version": "1.6.1",
|
"version": "1.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/next-plausible/-/next-plausible-1.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/next-plausible/-/next-plausible-1.6.1.tgz",
|
||||||
"integrity": "sha512-eMVqZbzU6bJsBIHlC63lNKl0KLvx8NA+/YlUUqj2gvCviQ7C2X4PY59gEB+mO46JvKSy/IhAD8l85/YGFhCkDg=="
|
"integrity": "sha512-eMVqZbzU6bJsBIHlC63lNKl0KLvx8NA+/YlUUqj2gvCviQ7C2X4PY59gEB+mO46JvKSy/IhAD8l85/YGFhCkDg==",
|
||||||
|
"requires": {}
|
||||||
},
|
},
|
||||||
"next-pre-css": {
|
"next-pre-css": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@ -13407,7 +13413,8 @@
|
|||||||
"postcss-modules-extract-imports": {
|
"postcss-modules-extract-imports": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
|
||||||
"integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw=="
|
"integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==",
|
||||||
|
"requires": {}
|
||||||
},
|
},
|
||||||
"postcss-modules-local-by-default": {
|
"postcss-modules-local-by-default": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
@ -14865,7 +14872,8 @@
|
|||||||
"stylis-rule-sheet": {
|
"stylis-rule-sheet": {
|
||||||
"version": "0.0.10",
|
"version": "0.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz",
|
||||||
"integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw=="
|
"integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==",
|
||||||
|
"requires": {}
|
||||||
},
|
},
|
||||||
"stylus": {
|
"stylus": {
|
||||||
"version": "0.54.8",
|
"version": "0.54.8",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Component2D from 'GameEngine/Component2D'
|
import Component2D from 'GameEngine/Component2D'
|
||||||
import Vector2D from '../Vector2D'
|
import Vector2D from '../Vector2D'
|
||||||
|
|
||||||
type BuiltinCollisionTypes = 'click'
|
type BuiltinCollisionTypes = 'click' | 'pointerDown' | 'pointerUp'
|
||||||
|
|
||||||
export default class BoxCollider2D {
|
export default class BoxCollider2D {
|
||||||
public constructor(
|
public constructor(
|
||||||
|
@ -1,14 +1,20 @@
|
|||||||
import Component2D from 'GameEngine/Component2D'
|
import Component2D from 'GameEngine/Component2D'
|
||||||
import RectRenderer from 'GameEngine/Renderer/RectRenderer'
|
import RectRenderer from 'GameEngine/Renderer/RectRenderer'
|
||||||
import Vector2D from '../Vector2D'
|
import Vector2D from '../Vector2D'
|
||||||
|
import PointDebugger from './PointDebugger'
|
||||||
|
|
||||||
export default class ComponentDebug extends Component2D {
|
export default class ComponentDebug extends Component2D {
|
||||||
public constructor(component: Component2D) {
|
public constructor(component: Component2D) {
|
||||||
super()
|
super()
|
||||||
this.position = component.position
|
this.position = new Vector2D(0, 0)
|
||||||
this.origin = component.origin
|
// this.origin = component.origin
|
||||||
this.scale = new Vector2D(.1, .1)
|
this.scale = component.scale
|
||||||
console.log('Position of the origin point', this.position)
|
console.log('Position of the origin point', this.position)
|
||||||
this.renderer = new RectRenderer(this, {material: 'red'})
|
// this.renderer = new RectRenderer(this, {material: 'red'})
|
||||||
|
this.childs = [
|
||||||
|
new PointDebugger(new Vector2D(0, 0), 'aqua'),
|
||||||
|
new PointDebugger(this.origin, 'green'),
|
||||||
|
new PointDebugger(component.position.sum(component.scale), 'aqua')
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,12 @@ import RectRenderer from 'GameEngine/Renderer/RectRenderer'
|
|||||||
import Vector2D from '../Vector2D'
|
import Vector2D from '../Vector2D'
|
||||||
|
|
||||||
export default class PointDebugger extends Component2D {
|
export default class PointDebugger extends Component2D {
|
||||||
public constructor(point: Vector2D) {
|
public constructor(point: Vector2D, color = 'red') {
|
||||||
super()
|
super()
|
||||||
this.scale = new Vector2D(.1, .1)
|
this.scale = new Vector2D(.1, .1)
|
||||||
this.position = point
|
this.position = point
|
||||||
console.log('Debugging point at location', point)
|
console.log('Debugging point at location', point)
|
||||||
// this.origin = component.origin
|
// this.origin = component.origin
|
||||||
this.renderer = new RectRenderer(this, {material: 'red'})
|
this.renderer = new RectRenderer(this, {material: color})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
/* eslint-disable no-underscore-dangle */
|
|
||||||
export default class Size2D {
|
|
||||||
private _width: number
|
|
||||||
private _height?: number
|
|
||||||
|
|
||||||
public constructor(
|
|
||||||
width: number,
|
|
||||||
height?: number
|
|
||||||
) {
|
|
||||||
this._width = width
|
|
||||||
this._height = height
|
|
||||||
}
|
|
||||||
|
|
||||||
public get width() {
|
|
||||||
return this._width
|
|
||||||
}
|
|
||||||
|
|
||||||
public set width(v: number) {
|
|
||||||
this._width = v
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public get height() {
|
|
||||||
return this._height ?? this._width
|
|
||||||
}
|
|
||||||
|
|
||||||
public set height(v: number) {
|
|
||||||
this._height = v
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,7 +4,6 @@ export default class Vector2D {
|
|||||||
public y: number
|
public y: number
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|
||||||
public multiply(v: Vector2D): Vector2D {
|
public multiply(v: Vector2D): Vector2D {
|
||||||
return new Vector2D(
|
return new Vector2D(
|
||||||
v.x * this.x,
|
v.x * this.x,
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* Asset management Class
|
||||||
|
*/
|
||||||
export default class Asset {
|
export default class Asset {
|
||||||
|
|
||||||
public static assets: Record<string, Asset> = {}
|
public static assets: Record<string, Asset> = {}
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
import Vector2D from './2D/Vector2D'
|
|
||||||
|
|
||||||
export default class Camera {
|
|
||||||
public topLeft = new Vector2D(0.5, 0.5)
|
|
||||||
}
|
|
@ -10,14 +10,45 @@ export interface ComponentState {
|
|||||||
isColliding?: string
|
isColliding?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2D Component
|
||||||
|
*/
|
||||||
export default abstract class Component2D {
|
export default abstract class Component2D {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate how the component is rendered
|
||||||
|
*
|
||||||
|
* @type {Renderer}
|
||||||
|
* @memberof Component2D
|
||||||
|
*/
|
||||||
public renderer?: Renderer
|
public renderer?: Renderer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component position relative to the parent position and to the component origin
|
||||||
|
*
|
||||||
|
* (see also: Component2D.origin)
|
||||||
|
*
|
||||||
|
* @type {Vector2D}
|
||||||
|
* @memberof Component2D
|
||||||
|
*/
|
||||||
public position: Vector2D = new Vector2D(0, 0)
|
public position: Vector2D = new Vector2D(0, 0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component scale relative to 1 case size
|
||||||
|
*
|
||||||
|
* (see also: GameEngine.caseSize)
|
||||||
|
*
|
||||||
|
* @type {Vector2D}
|
||||||
|
* @memberof Component2D
|
||||||
|
*/
|
||||||
public scale: Vector2D = new Vector2D(1, 1)
|
public scale: Vector2D = new Vector2D(1, 1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component collider for events
|
||||||
|
*
|
||||||
|
* @type {BoxCollider2D}
|
||||||
|
* @memberof Component2D
|
||||||
|
*/
|
||||||
public collider?: BoxCollider2D
|
public collider?: BoxCollider2D
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,11 +56,35 @@ export default abstract class Component2D {
|
|||||||
*/
|
*/
|
||||||
public origin: Vector2D = new Vector2D(0 , 0)
|
public origin: Vector2D = new Vector2D(0 , 0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component Child Components
|
||||||
|
*
|
||||||
|
* @type {Array<Component2D>}
|
||||||
|
* @memberof Component2D
|
||||||
|
*/
|
||||||
public childs: Array<Component2D> = []
|
public childs: Array<Component2D> = []
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component in debug mode
|
||||||
|
* It will display more informations depending on the Collider and other items
|
||||||
|
*
|
||||||
|
* note: Does not apply to childs components
|
||||||
|
*
|
||||||
|
* @type {boolean}
|
||||||
|
* @memberof Component2D
|
||||||
|
*/
|
||||||
public debug?: boolean
|
public debug?: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function run when the component is initialized
|
||||||
|
*/
|
||||||
public init?(): Promise<void> | void
|
public init?(): Promise<void> | void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function run on each game ticks
|
||||||
|
* @param state the component state
|
||||||
|
*/
|
||||||
public update?(state: ComponentState): Promise<void> | void
|
public update?(state: ComponentState): Promise<void> | void
|
||||||
|
|
||||||
|
public destroy?(): Promise<void> | void
|
||||||
}
|
}
|
||||||
|
8
src/GameEngine/Components/Camera.ts
Normal file
8
src/GameEngine/Components/Camera.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import Vector2D from '../2D/Vector2D'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Currently not working Camera implementation
|
||||||
|
*/
|
||||||
|
export default class Camera {
|
||||||
|
public topLeft = new Vector2D(0.5, 0.5)
|
||||||
|
}
|
25
src/GameEngine/Components/FPSCounter.ts
Normal file
25
src/GameEngine/Components/FPSCounter.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import ComponentDebug from 'GameEngine/2D/Debug/ComponentDebug'
|
||||||
|
import Vector2D from 'GameEngine/2D/Vector2D'
|
||||||
|
import Component2D from 'GameEngine/Component2D'
|
||||||
|
import Renderer from 'GameEngine/Renderer'
|
||||||
|
import TextRenderer from 'GameEngine/Renderer/TextRenderer'
|
||||||
|
|
||||||
|
export default class FPSCounter extends Component2D {
|
||||||
|
|
||||||
|
|
||||||
|
public position: Vector2D = new Vector2D(0,0)
|
||||||
|
public scale: Vector2D = new Vector2D(1, 1)
|
||||||
|
public origin: Vector2D = new Vector2D(0, 0)
|
||||||
|
public childs: Array<Component2D> = [new ComponentDebug(this)]
|
||||||
|
|
||||||
|
public renderer: TextRenderer = new TextRenderer(this, {text: 'pouet'})
|
||||||
|
|
||||||
|
private lastUpdate: number = new Date().getTime()
|
||||||
|
|
||||||
|
public update() {
|
||||||
|
const now = new Date().getTime()
|
||||||
|
this.renderer.text = (1000 / (now - this.lastUpdate)).toFixed(2)
|
||||||
|
this.lastUpdate = now
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
31
src/GameEngine/Event/PointerEvents.ts
Normal file
31
src/GameEngine/Event/PointerEvents.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import Event from '.'
|
||||||
|
|
||||||
|
export default class PointerEvents extends Event {
|
||||||
|
public override init(): void {
|
||||||
|
document.addEventListener('mousemove', this.basicEvent)
|
||||||
|
document.addEventListener('mousedown', this.mouseDown)
|
||||||
|
document.addEventListener('mouseup', this.mouseUp)
|
||||||
|
}
|
||||||
|
|
||||||
|
public update() {
|
||||||
|
// pouet
|
||||||
|
}
|
||||||
|
|
||||||
|
public override destroy() {
|
||||||
|
document.removeEventListener('mousemove', this.basicEvent)
|
||||||
|
document.removeEventListener('mousedown', this.mouseDown)
|
||||||
|
document.removeEventListener('mouseup', this.mouseUp)
|
||||||
|
}
|
||||||
|
|
||||||
|
private basicEvent = (ev: MouseEvent) => {
|
||||||
|
console.log('Mouse Event :D')
|
||||||
|
}
|
||||||
|
|
||||||
|
private mouseUp = (ev: MouseEvent) => {
|
||||||
|
this.basicEvent(ev)
|
||||||
|
}
|
||||||
|
|
||||||
|
private mouseDown = (ev: MouseEvent) => {
|
||||||
|
this.basicEvent(ev)
|
||||||
|
}
|
||||||
|
}
|
11
src/GameEngine/Event/index.ts
Normal file
11
src/GameEngine/Event/index.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import GameEngine from 'GameEngine'
|
||||||
|
|
||||||
|
export default abstract class Event {
|
||||||
|
public constructor(
|
||||||
|
protected ge: GameEngine
|
||||||
|
) {}
|
||||||
|
|
||||||
|
abstract init(): void
|
||||||
|
abstract update(): void
|
||||||
|
abstract destroy(): void
|
||||||
|
}
|
@ -9,7 +9,7 @@ interface Params {
|
|||||||
stroke?: string
|
stroke?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class RectRenderer extends Renderer implements Partial<Params> {
|
export default class RectRenderer extends Renderer implements Params {
|
||||||
|
|
||||||
public material?: string | Asset
|
public material?: string | Asset
|
||||||
public stroke?: string
|
public stroke?: string
|
||||||
|
41
src/GameEngine/Renderer/TextRenderer.ts
Normal file
41
src/GameEngine/Renderer/TextRenderer.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { objectLoop } from '@dzeio/object-util'
|
||||||
|
import GameEngine from 'GameEngine'
|
||||||
|
import Component2D from 'GameEngine/Component2D'
|
||||||
|
import Renderer from '.'
|
||||||
|
|
||||||
|
interface Params {
|
||||||
|
text?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class TextRenderer extends Renderer {
|
||||||
|
|
||||||
|
public text?: string
|
||||||
|
public size?: number
|
||||||
|
|
||||||
|
public constructor(component: Component2D, params?: Params) {
|
||||||
|
super(component)
|
||||||
|
objectLoop(params ?? {}, (v, k) => {this[k as 'text'] = v})
|
||||||
|
}
|
||||||
|
|
||||||
|
public async render(ge: GameEngine, ctx: CanvasRenderingContext2D) {
|
||||||
|
const position = this.getPosition()
|
||||||
|
const item: [number, number] = [
|
||||||
|
// source x
|
||||||
|
// 0 - 1.5 - -1.5
|
||||||
|
position.x * (ge.caseSize.x),
|
||||||
|
// source y
|
||||||
|
position.y * (ge.caseSize.y)
|
||||||
|
]
|
||||||
|
|
||||||
|
const size = this.component.scale.y * ge.caseSize.y
|
||||||
|
|
||||||
|
// console.log
|
||||||
|
if (this.text) {
|
||||||
|
ctx.fillStyle = 'black'
|
||||||
|
ctx.textBaseline = 'top'
|
||||||
|
|
||||||
|
ctx.font = `${size}px sans-serif`
|
||||||
|
ctx.fillText(this.text, ...item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,7 @@ export default abstract class Renderer {
|
|||||||
|
|
||||||
protected getPosition(): Vector2D {
|
protected getPosition(): Vector2D {
|
||||||
const ge = GameEngine.getGameEngine()
|
const ge = GameEngine.getGameEngine()
|
||||||
const realPosition = ge.currentScene.camera.topLeft.sum(this.component.position)
|
const realPosition = ge.currentScene!.camera.topLeft.sum(this.component.position)
|
||||||
return new Vector2D(
|
return new Vector2D(
|
||||||
realPosition.x - this.component.scale.x / 2 - this.component.origin.x,
|
realPosition.x - this.component.scale.x / 2 - this.component.origin.x,
|
||||||
realPosition.y - this.component.scale.y / 2 - this.component.origin.y
|
realPosition.y - this.component.scale.y / 2 - this.component.origin.y
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import GameEngine from 'GameEngine'
|
import GameEngine from 'GameEngine'
|
||||||
import AssetsManager from './Asset'
|
import AssetsManager from './Asset'
|
||||||
import Camera from './Camera'
|
import Camera from './Components/Camera'
|
||||||
import Component2D, { ComponentState } from './Component2D'
|
import Component2D, { ComponentState } from './Component2D'
|
||||||
|
|
||||||
export default class Scene {
|
export default class Scene {
|
||||||
@ -42,6 +42,12 @@ export default class Scene {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async destroy() {
|
||||||
|
for await (const component of this.components) {
|
||||||
|
await component.destroy?.()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async updateComponent(v: Component2D) {
|
private async updateComponent(v: Component2D) {
|
||||||
const debug = v.debug
|
const debug = v.debug
|
||||||
if (debug) {
|
if (debug) {
|
||||||
@ -64,6 +70,13 @@ export default class Scene {
|
|||||||
// state.mouseClicking = state.mouseHovering && this.ge.cursor.isDown
|
// state.mouseClicking = state.mouseHovering && this.ge.cursor.isDown
|
||||||
// state.mouseClicked = state.mouseClicking && !this.ge.cursor.wasDown
|
// state.mouseClicked = state.mouseClicking && !this.ge.cursor.wasDown
|
||||||
// }
|
// }
|
||||||
|
if (v.update) {
|
||||||
|
if (debug) {
|
||||||
|
console.log('Updating Component', v)
|
||||||
|
}
|
||||||
|
v.update(state as ComponentState)
|
||||||
|
}
|
||||||
|
|
||||||
if (v.renderer) {
|
if (v.renderer) {
|
||||||
if (debug) {
|
if (debug) {
|
||||||
console.log('Rendering Component', v)
|
console.log('Rendering Component', v)
|
||||||
@ -71,17 +84,12 @@ export default class Scene {
|
|||||||
// console.log('is rendering new element')
|
// console.log('is rendering new element')
|
||||||
await v.renderer.render(this.ge, this.ge.ctx)
|
await v.renderer.render(this.ge, this.ge.ctx)
|
||||||
}
|
}
|
||||||
if (v.update) {
|
|
||||||
if (debug) {
|
|
||||||
console.log('Updating Component', v)
|
|
||||||
}
|
|
||||||
v.update(state as ComponentState)
|
|
||||||
}
|
|
||||||
if (v.childs) {
|
if (v.childs) {
|
||||||
if (debug) {
|
if (debug) {
|
||||||
console.log('Processing childs', v)
|
console.log('Processing childs', v)
|
||||||
}
|
}
|
||||||
for (const child of v.childs) {
|
for await (const child of v.childs) {
|
||||||
await this.updateComponent(child)
|
await this.updateComponent(child)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,15 +21,22 @@ export default class GameEngine {
|
|||||||
isDown: false,
|
isDown: false,
|
||||||
wasDown: false
|
wasDown: false
|
||||||
}
|
}
|
||||||
public currentScene!: Scene
|
public currentScene?: Scene
|
||||||
private isRunning = false
|
private isRunning = false
|
||||||
|
private timer = 16.6
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
private id: string,
|
id: string,
|
||||||
public options?: {
|
public options?: {
|
||||||
caseCount?: number | [number, number]
|
caseCount?: number | [number, number]
|
||||||
background?: string
|
background?: string
|
||||||
debugColliders?: boolean
|
debugColliders?: boolean
|
||||||
|
/**
|
||||||
|
* Maximum framerate you want to achieve
|
||||||
|
*
|
||||||
|
* note: -1 mean infinite
|
||||||
|
*/
|
||||||
|
goalFramerate?: number
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
GameEngine.ge = this
|
GameEngine.ge = this
|
||||||
@ -53,6 +60,14 @@ export default class GameEngine {
|
|||||||
}
|
}
|
||||||
ctx.imageSmoothingEnabled = false
|
ctx.imageSmoothingEnabled = false
|
||||||
this.ctx = ctx
|
this.ctx = ctx
|
||||||
|
|
||||||
|
if (options?.goalFramerate) {
|
||||||
|
if (options.goalFramerate === -1) {
|
||||||
|
this.timer = 0
|
||||||
|
} else {
|
||||||
|
this.timer = 1000 / options.goalFramerate
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getGameEngine(): GameEngine {
|
public static getGameEngine(): GameEngine {
|
||||||
@ -70,8 +85,8 @@ export default class GameEngine {
|
|||||||
})
|
})
|
||||||
document.addEventListener('mousemove', (ev) => {
|
document.addEventListener('mousemove', (ev) => {
|
||||||
this.cursor.position = new Vector2D(
|
this.cursor.position = new Vector2D(
|
||||||
ev.clientX / this.caseSize.x - this.currentScene.camera.topLeft.x,
|
ev.clientX / this.caseSize.x - (this.currentScene?.camera?.topLeft?.x ?? 0),
|
||||||
ev.clientY / this.caseSize.y - this.currentScene.camera.topLeft.y
|
ev.clientY / this.caseSize.y - (this.currentScene?.camera?.topLeft?.y ?? 0)
|
||||||
)
|
)
|
||||||
if (this.cursor.isDown) {
|
if (this.cursor.isDown) {
|
||||||
this.cursor.wasDown = true
|
this.cursor.wasDown = true
|
||||||
@ -90,13 +105,15 @@ export default class GameEngine {
|
|||||||
this.isRunning = false
|
this.isRunning = false
|
||||||
}
|
}
|
||||||
|
|
||||||
public setScene(scene: Scene | string) {
|
public async setScene(scene: Scene | string) {
|
||||||
console.log('Setting scene', typeof scene === 'string' ? scene : scene.id)
|
console.log('Setting scene', typeof scene === 'string' ? scene : scene.id)
|
||||||
|
await this.currentScene?.destroy()
|
||||||
this.currentScene = typeof scene === 'string' ? Scene.scenes[scene] : scene
|
this.currentScene = typeof scene === 'string' ? Scene.scenes[scene] : scene
|
||||||
this.currentScene.setGameEngine(this)
|
this.currentScene.setGameEngine(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
private update() {
|
private update() {
|
||||||
|
const now = new Date().getTime()
|
||||||
if (!this.isRunning) {
|
if (!this.isRunning) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -106,9 +123,19 @@ export default class GameEngine {
|
|||||||
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height)
|
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height)
|
||||||
}
|
}
|
||||||
this.currentScene?.update()
|
this.currentScene?.update()
|
||||||
setTimeout(() => {
|
const diff = new Date().getTime() - now
|
||||||
|
if (diff > this.timer) {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
this.update()
|
this.update()
|
||||||
}, 0)
|
})
|
||||||
|
} else {
|
||||||
|
setTimeout(() => {
|
||||||
|
// this.update()
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
this.update()
|
||||||
|
})
|
||||||
|
}, this.timer - diff)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ export default class Item extends Component2D {
|
|||||||
console.log('item initialized')
|
console.log('item initialized')
|
||||||
}
|
}
|
||||||
|
|
||||||
public update(state: ComponentState) {
|
public async update(state: ComponentState) {
|
||||||
if (!globalState.isPlaying) {
|
if (!globalState.isPlaying) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ export default class Item extends Component2D {
|
|||||||
const value: '' | 'X' | 'O' = globalState.gameState[this.x][this.y] as '' | 'X' | 'O'
|
const value: '' | 'X' | 'O' = globalState.gameState[this.x][this.y] as '' | 'X' | 'O'
|
||||||
if (state.isColliding === 'click' && value === '') {
|
if (state.isColliding === 'click' && value === '') {
|
||||||
// console.log('hovering')
|
// console.log('hovering')
|
||||||
this.onClick()
|
await this.onClick()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value === 'X') {
|
if (value === 'X') {
|
||||||
@ -75,7 +75,7 @@ export default class Item extends Component2D {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onClick() {
|
private async onClick() {
|
||||||
const clickSound = new SoundManager('/assets/tictactoe/bip.wav')
|
const clickSound = new SoundManager('/assets/tictactoe/bip.wav')
|
||||||
clickSound.play()
|
clickSound.play()
|
||||||
globalState.gameState[this.x][this.y] = globalState.playerTurn
|
globalState.gameState[this.x][this.y] = globalState.playerTurn
|
||||||
@ -88,7 +88,7 @@ export default class Item extends Component2D {
|
|||||||
['', '', '']
|
['', '', '']
|
||||||
]
|
]
|
||||||
console.log(globalState)
|
console.log(globalState)
|
||||||
GameEngine.getGameEngine().setScene('Menu')
|
await GameEngine.getGameEngine().setScene('Menu')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
globalState.playerTurn = globalState.playerTurn === 'X' ? 'O' : 'X'
|
globalState.playerTurn = globalState.playerTurn === 'X' ? 'O' : 'X'
|
||||||
|
@ -13,11 +13,16 @@ export default class Start extends Component2D {
|
|||||||
public collider: BoxCollider2D = new BoxCollider2D(this, 'click')
|
public collider: BoxCollider2D = new BoxCollider2D(this, 'click')
|
||||||
public childs: Array<Component2D> = [new ColliderDebugger(this, this.collider)]
|
public childs: Array<Component2D> = [new ColliderDebugger(this, this.collider)]
|
||||||
|
|
||||||
public update(state: ComponentState) {
|
private hasCollided = false
|
||||||
|
|
||||||
|
public async update(state: ComponentState) {
|
||||||
if (state.isColliding === 'click') {
|
if (state.isColliding === 'click') {
|
||||||
|
this.hasCollided = true
|
||||||
|
} else if (this.hasCollided) {
|
||||||
console.log('Start Game !')
|
console.log('Start Game !')
|
||||||
GameEngine.getGameEngine().setScene('TicTacToe')
|
await GameEngine.getGameEngine().setScene('TicTacToe')
|
||||||
globalState.isPlaying = true
|
globalState.isPlaying = true
|
||||||
|
this.hasCollided = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@ import Scene from 'GameEngine/Scene'
|
|||||||
import Item from 'games/tictactoe/Item'
|
import Item from 'games/tictactoe/Item'
|
||||||
import Line from 'games/tictactoe/Line'
|
import Line from 'games/tictactoe/Line'
|
||||||
import Start from 'games/tictactoe/Menu/Start'
|
import Start from 'games/tictactoe/Menu/Start'
|
||||||
|
import FPSCounter from 'GameEngine/Components/FPSCounter'
|
||||||
|
import ComponentDebug from 'GameEngine/2D/Debug/ComponentDebug'
|
||||||
|
|
||||||
export default class Snake extends React.PureComponent {
|
export default class Snake extends React.PureComponent {
|
||||||
|
|
||||||
@ -13,23 +15,26 @@ export default class Snake extends React.PureComponent {
|
|||||||
const ge = new GameEngine('#test', {
|
const ge = new GameEngine('#test', {
|
||||||
caseCount: 3,
|
caseCount: 3,
|
||||||
background: 'blue',
|
background: 'blue',
|
||||||
debugColliders: true
|
debugColliders: true,
|
||||||
|
goalFramerate: 30
|
||||||
})
|
})
|
||||||
const menuScene = new Scene('Menu')
|
const menuScene = new Scene('Menu')
|
||||||
menuScene.addComponent(
|
menuScene.addComponent(
|
||||||
new Start()
|
new Start(),
|
||||||
|
new FPSCounter()
|
||||||
)
|
)
|
||||||
const scene = new Scene('TicTacToe')
|
const scene = new Scene('TicTacToe')
|
||||||
scene.addComponent(
|
scene.addComponent(
|
||||||
...Array.from(new Array(2)).map((_, index) => new Line(0, index)),
|
...Array.from(new Array(2)).map((_, index) => new Line(0, index)),
|
||||||
...Array.from(new Array(2)).map((_, index) => new Line(1, index)),
|
...Array.from(new Array(2)).map((_, index) => new Line(1, index)),
|
||||||
...Array.from(new Array(9)).map((_, index) => new Item(index)),
|
...Array.from(new Array(9)).map((_, index) => new Item(index)),
|
||||||
Item.explosion
|
Item.explosion,
|
||||||
|
new FPSCounter()
|
||||||
// new TilingDebugger()
|
// new TilingDebugger()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
await ge.setScene(menuScene)
|
||||||
ge.start()
|
ge.start()
|
||||||
ge.setScene(menuScene)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public render = () => (
|
public render = () => (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user