mirror of
https://github.com/Aviortheking/games.git
synced 2025-04-23 19:32:09 +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": {
|
||||
"version": "11.0.0",
|
||||
"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": {
|
||||
"version": "2.1.5",
|
||||
@ -9601,7 +9602,8 @@
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
|
||||
"integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"ajv": {
|
||||
"version": "6.12.6",
|
||||
@ -9617,7 +9619,8 @@
|
||||
"ajv-keywords": {
|
||||
"version": "3.5.2",
|
||||
"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": {
|
||||
"version": "1.0.2",
|
||||
@ -11218,7 +11221,8 @@
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz",
|
||||
"integrity": "sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"eslint-scope": {
|
||||
"version": "5.1.1",
|
||||
@ -11715,7 +11719,8 @@
|
||||
"icss-utils": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
|
||||
"integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA=="
|
||||
"integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
|
||||
"requires": {}
|
||||
},
|
||||
"ieee754": {
|
||||
"version": "1.2.1",
|
||||
@ -12382,7 +12387,8 @@
|
||||
"next-plausible": {
|
||||
"version": "1.6.1",
|
||||
"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": {
|
||||
"version": "1.0.0",
|
||||
@ -13407,7 +13413,8 @@
|
||||
"postcss-modules-extract-imports": {
|
||||
"version": "3.0.0",
|
||||
"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": {
|
||||
"version": "4.0.0",
|
||||
@ -14865,7 +14872,8 @@
|
||||
"stylis-rule-sheet": {
|
||||
"version": "0.0.10",
|
||||
"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": {
|
||||
"version": "0.54.8",
|
||||
|
@ -1,7 +1,7 @@
|
||||
import Component2D from 'GameEngine/Component2D'
|
||||
import Vector2D from '../Vector2D'
|
||||
|
||||
type BuiltinCollisionTypes = 'click'
|
||||
type BuiltinCollisionTypes = 'click' | 'pointerDown' | 'pointerUp'
|
||||
|
||||
export default class BoxCollider2D {
|
||||
public constructor(
|
||||
|
@ -1,14 +1,20 @@
|
||||
import Component2D from 'GameEngine/Component2D'
|
||||
import RectRenderer from 'GameEngine/Renderer/RectRenderer'
|
||||
import Vector2D from '../Vector2D'
|
||||
import PointDebugger from './PointDebugger'
|
||||
|
||||
export default class ComponentDebug extends Component2D {
|
||||
public constructor(component: Component2D) {
|
||||
super()
|
||||
this.position = component.position
|
||||
this.origin = component.origin
|
||||
this.scale = new Vector2D(.1, .1)
|
||||
this.position = new Vector2D(0, 0)
|
||||
// this.origin = component.origin
|
||||
this.scale = component.scale
|
||||
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'
|
||||
|
||||
export default class PointDebugger extends Component2D {
|
||||
public constructor(point: Vector2D) {
|
||||
public constructor(point: Vector2D, color = 'red') {
|
||||
super()
|
||||
this.scale = new Vector2D(.1, .1)
|
||||
this.position = point
|
||||
console.log('Debugging point at location', point)
|
||||
// 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 multiply(v: Vector2D): Vector2D {
|
||||
return new Vector2D(
|
||||
v.x * this.x,
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Asset management Class
|
||||
*/
|
||||
export default class 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
|
||||
}
|
||||
|
||||
/**
|
||||
* 2D Component
|
||||
*/
|
||||
export default abstract class Component2D {
|
||||
|
||||
/**
|
||||
* Indicate how the component is rendered
|
||||
*
|
||||
* @type {Renderer}
|
||||
* @memberof Component2D
|
||||
*/
|
||||
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)
|
||||
|
||||
/**
|
||||
* Component scale relative to 1 case size
|
||||
*
|
||||
* (see also: GameEngine.caseSize)
|
||||
*
|
||||
* @type {Vector2D}
|
||||
* @memberof Component2D
|
||||
*/
|
||||
public scale: Vector2D = new Vector2D(1, 1)
|
||||
|
||||
/**
|
||||
* Component collider for events
|
||||
*
|
||||
* @type {BoxCollider2D}
|
||||
* @memberof Component2D
|
||||
*/
|
||||
public collider?: BoxCollider2D
|
||||
|
||||
/**
|
||||
@ -25,11 +56,35 @@ export default abstract class Component2D {
|
||||
*/
|
||||
public origin: Vector2D = new Vector2D(0 , 0)
|
||||
|
||||
/**
|
||||
* Component Child Components
|
||||
*
|
||||
* @type {Array<Component2D>}
|
||||
* @memberof 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
|
||||
|
||||
/**
|
||||
* Function run when the component is initialized
|
||||
*/
|
||||
public init?(): Promise<void> | void
|
||||
|
||||
/**
|
||||
* Function run on each game ticks
|
||||
* @param state the component state
|
||||
*/
|
||||
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
|
||||
}
|
||||
|
||||
export default class RectRenderer extends Renderer implements Partial<Params> {
|
||||
export default class RectRenderer extends Renderer implements Params {
|
||||
|
||||
public material?: string | Asset
|
||||
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 {
|
||||
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(
|
||||
realPosition.x - this.component.scale.x / 2 - this.component.origin.x,
|
||||
realPosition.y - this.component.scale.y / 2 - this.component.origin.y
|
||||
|
@ -1,6 +1,6 @@
|
||||
import GameEngine from 'GameEngine'
|
||||
import AssetsManager from './Asset'
|
||||
import Camera from './Camera'
|
||||
import Camera from './Components/Camera'
|
||||
import Component2D, { ComponentState } from './Component2D'
|
||||
|
||||
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) {
|
||||
const debug = v.debug
|
||||
if (debug) {
|
||||
@ -64,6 +70,13 @@ export default class Scene {
|
||||
// state.mouseClicking = state.mouseHovering && this.ge.cursor.isDown
|
||||
// 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 (debug) {
|
||||
console.log('Rendering Component', v)
|
||||
@ -71,17 +84,12 @@ export default class Scene {
|
||||
// console.log('is rendering new element')
|
||||
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 (debug) {
|
||||
console.log('Processing childs', v)
|
||||
}
|
||||
for (const child of v.childs) {
|
||||
for await (const child of v.childs) {
|
||||
await this.updateComponent(child)
|
||||
}
|
||||
}
|
||||
|
@ -21,15 +21,22 @@ export default class GameEngine {
|
||||
isDown: false,
|
||||
wasDown: false
|
||||
}
|
||||
public currentScene!: Scene
|
||||
public currentScene?: Scene
|
||||
private isRunning = false
|
||||
private timer = 16.6
|
||||
|
||||
public constructor(
|
||||
private id: string,
|
||||
id: string,
|
||||
public options?: {
|
||||
caseCount?: number | [number, number]
|
||||
background?: string
|
||||
debugColliders?: boolean
|
||||
/**
|
||||
* Maximum framerate you want to achieve
|
||||
*
|
||||
* note: -1 mean infinite
|
||||
*/
|
||||
goalFramerate?: number
|
||||
}
|
||||
) {
|
||||
GameEngine.ge = this
|
||||
@ -53,6 +60,14 @@ export default class GameEngine {
|
||||
}
|
||||
ctx.imageSmoothingEnabled = false
|
||||
this.ctx = ctx
|
||||
|
||||
if (options?.goalFramerate) {
|
||||
if (options.goalFramerate === -1) {
|
||||
this.timer = 0
|
||||
} else {
|
||||
this.timer = 1000 / options.goalFramerate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static getGameEngine(): GameEngine {
|
||||
@ -70,8 +85,8 @@ export default class GameEngine {
|
||||
})
|
||||
document.addEventListener('mousemove', (ev) => {
|
||||
this.cursor.position = new Vector2D(
|
||||
ev.clientX / this.caseSize.x - this.currentScene.camera.topLeft.x,
|
||||
ev.clientY / this.caseSize.y - this.currentScene.camera.topLeft.y
|
||||
ev.clientX / this.caseSize.x - (this.currentScene?.camera?.topLeft?.x ?? 0),
|
||||
ev.clientY / this.caseSize.y - (this.currentScene?.camera?.topLeft?.y ?? 0)
|
||||
)
|
||||
if (this.cursor.isDown) {
|
||||
this.cursor.wasDown = true
|
||||
@ -90,13 +105,15 @@ export default class GameEngine {
|
||||
this.isRunning = false
|
||||
}
|
||||
|
||||
public setScene(scene: Scene | string) {
|
||||
public async setScene(scene: Scene | string) {
|
||||
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.setGameEngine(this)
|
||||
}
|
||||
|
||||
private update() {
|
||||
const now = new Date().getTime()
|
||||
if (!this.isRunning) {
|
||||
return
|
||||
}
|
||||
@ -106,9 +123,19 @@ export default class GameEngine {
|
||||
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height)
|
||||
}
|
||||
this.currentScene?.update()
|
||||
setTimeout(() => {
|
||||
this.update()
|
||||
}, 0)
|
||||
const diff = new Date().getTime() - now
|
||||
if (diff > this.timer) {
|
||||
requestAnimationFrame(() => {
|
||||
this.update()
|
||||
})
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
// this.update()
|
||||
requestAnimationFrame(() => {
|
||||
this.update()
|
||||
})
|
||||
}, this.timer - diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ export default class Item extends Component2D {
|
||||
console.log('item initialized')
|
||||
}
|
||||
|
||||
public update(state: ComponentState) {
|
||||
public async update(state: ComponentState) {
|
||||
if (!globalState.isPlaying) {
|
||||
return
|
||||
}
|
||||
@ -62,7 +62,7 @@ export default class Item extends Component2D {
|
||||
const value: '' | 'X' | 'O' = globalState.gameState[this.x][this.y] as '' | 'X' | 'O'
|
||||
if (state.isColliding === 'click' && value === '') {
|
||||
// console.log('hovering')
|
||||
this.onClick()
|
||||
await this.onClick()
|
||||
}
|
||||
|
||||
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')
|
||||
clickSound.play()
|
||||
globalState.gameState[this.x][this.y] = globalState.playerTurn
|
||||
@ -88,7 +88,7 @@ export default class Item extends Component2D {
|
||||
['', '', '']
|
||||
]
|
||||
console.log(globalState)
|
||||
GameEngine.getGameEngine().setScene('Menu')
|
||||
await GameEngine.getGameEngine().setScene('Menu')
|
||||
return
|
||||
}
|
||||
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 childs: Array<Component2D> = [new ColliderDebugger(this, this.collider)]
|
||||
|
||||
public update(state: ComponentState) {
|
||||
private hasCollided = false
|
||||
|
||||
public async update(state: ComponentState) {
|
||||
if (state.isColliding === 'click') {
|
||||
this.hasCollided = true
|
||||
} else if (this.hasCollided) {
|
||||
console.log('Start Game !')
|
||||
GameEngine.getGameEngine().setScene('TicTacToe')
|
||||
await GameEngine.getGameEngine().setScene('TicTacToe')
|
||||
globalState.isPlaying = true
|
||||
this.hasCollided = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ import Scene from 'GameEngine/Scene'
|
||||
import Item from 'games/tictactoe/Item'
|
||||
import Line from 'games/tictactoe/Line'
|
||||
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 {
|
||||
|
||||
@ -13,23 +15,26 @@ export default class Snake extends React.PureComponent {
|
||||
const ge = new GameEngine('#test', {
|
||||
caseCount: 3,
|
||||
background: 'blue',
|
||||
debugColliders: true
|
||||
debugColliders: true,
|
||||
goalFramerate: 30
|
||||
})
|
||||
const menuScene = new Scene('Menu')
|
||||
menuScene.addComponent(
|
||||
new Start()
|
||||
new Start(),
|
||||
new FPSCounter()
|
||||
)
|
||||
const scene = new Scene('TicTacToe')
|
||||
scene.addComponent(
|
||||
...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(9)).map((_, index) => new Item(index)),
|
||||
Item.explosion
|
||||
Item.explosion,
|
||||
new FPSCounter()
|
||||
// new TilingDebugger()
|
||||
)
|
||||
|
||||
await ge.setScene(menuScene)
|
||||
ge.start()
|
||||
ge.setScene(menuScene)
|
||||
}
|
||||
|
||||
public render = () => (
|
||||
|
Loading…
x
Reference in New Issue
Block a user