1- import { IEntityTransformOptions , ITransformOptions } from "./interface" ;
1+ import { InputManager } from "./input" ;
2+ import { IEntityTransformOptions , IGameOptions , ITransformOptions } from "./interface" ;
23import { MatrixStack , Vec2 } from "./math" ;
34import Rapid from "./render" ;
45
@@ -7,7 +8,6 @@ export const isPlainObject = (obj: any) => {
78 return Object . getPrototypeOf ( obj ) === Object . prototype ;
89}
910
10-
1111export class Entity {
1212 position : Vec2 ;
1313 scale : Vec2 ;
@@ -17,12 +17,14 @@ export class Entity {
1717 readonly children : Entity [ ] = [ ] ;
1818 transform = new MatrixStack ( ) ;
1919 rapid : Rapid ;
20+ game : Game
2021
2122 tags : string [ ] ;
2223
23- constructor ( rapid : Rapid , options : IEntityTransformOptions = { } ) {
24+ constructor ( game : Game , options : IEntityTransformOptions = { } ) {
2425 this . transform . pushIdentity ( )
25- this . rapid = rapid ;
26+ this . game = game
27+ this . rapid = game . render ;
2628
2729 this . tags = options . tags ?? [ ]
2830 // Position
@@ -49,9 +51,25 @@ export class Entity {
4951 return this . parent ? this . parent . transform : this . rapid . matrixStack ;
5052 }
5153
52- update ( deltaTime : number ) : void {
54+ public update ( deltaTime : number ) : void {
55+ this . onUpdate ( deltaTime ) ;
56+
57+ for ( const child of this . children ) {
58+ child . update ( deltaTime ) ;
59+ }
60+ }
61+ onUpdate ( deltaTime : number ) { }
62+
63+ public render ( ) : void {
64+ this . updateTransform ( ) ;
65+
66+ this . onRender ( ) ;
5367
68+ for ( const child of this . children ) {
69+ child . render ( ) ;
70+ }
5471 }
72+ onRender ( ) { }
5573
5674 updateTransform ( deep : boolean = false ) {
5775 if ( deep && this . parent ) {
@@ -64,24 +82,8 @@ export class Entity {
6482 transform . translate ( this . position ) ;
6583 transform . rotate ( this . rotation ) ;
6684 transform . scale ( this . scale ) ;
67- }
6885
69- render ( ) : void {
70- this . updateTransform ( ) ;
71- }
72-
73- postRender ( ) : void {
74- for ( const child of this . children ) {
75- child . render ( ) ;
76- child . postRender ( ) ;
77- }
78- }
79-
80- postUpdate ( deltaTime : number ) : void {
81- for ( const child of this . children ) {
82- child . update ( deltaTime ) ;
83- child . postUpdate ( deltaTime ) ;
84- }
86+ this . rapid . matrixStack . setTransform ( transform . getTransform ( ) )
8587 }
8688
8789 addChild ( child : Entity ) : void {
@@ -100,14 +102,6 @@ export class Entity {
100102 }
101103 }
102104
103- root ( dt : number ) {
104- this . update ( dt )
105- this . postUpdate ( dt )
106-
107- this . render ( )
108- this . postRender ( )
109- }
110-
111105 findDescendant ( predicate : ( entity : Entity ) => boolean , onlyFirst = true ) : Entity [ ] | Entity | null {
112106 const results : Entity [ ] = [ ] ;
113107 for ( const child of this . children ) {
@@ -136,25 +130,95 @@ export class Entity {
136130 } ;
137131 return this . findDescendant ( predicate , onlyFirst ) ;
138132 }
133+
134+ dispose ( ) {
135+ this . postDispose ( ) ;
136+ if ( this . parent ) {
137+ this . parent . removeChild ( this ) ;
138+ }
139+ }
140+
141+ postDispose ( ) {
142+ this . children . forEach ( child => {
143+ child . dispose ( ) ;
144+ } )
145+ }
139146}
140147
141148export class Camera extends Entity {
142149 override updateTransform ( ) {
143150 const transform = this . transform ;
144- const parentTransform = this . getParentTransform ( ) ;
145- transform . setTransform ( parentTransform . getTransform ( ) ) ;
146-
151+ transform . identity ( )
152+
147153 const centerdPosition = new Vec2 (
148- - this . rapid . logicWidth ,
154+ - this . rapid . logicWidth ,
149155 - this . rapid . logicHeight
150156 ) . divide ( 2 )
151157
152158 transform . translate ( centerdPosition ) ;
153159 transform . translate ( this . position ) ;
154-
160+
155161 transform . rotate ( this . rotation ) ;
156162 transform . scale ( this . scale ) ;
157163
158164 transform . setTransform ( transform . getInverse ( ) )
159165 }
166+ }
167+
168+ export class Scene extends Entity {
169+ create ( ) {
170+
171+ }
172+ }
173+
174+ export class Game {
175+ render : Rapid ;
176+ mainScene : Scene | null = null ;
177+ input : InputManager ;
178+ private isRunning : boolean = false ;
179+ private lastTime : number = 0 ;
180+
181+ constructor ( options : IGameOptions ) {
182+ this . render = new Rapid ( options ) ;
183+ this . input = new InputManager ( this . render ) ;
184+ }
185+
186+ switchScene ( newScene : Scene ) : void {
187+ if ( this . mainScene ) {
188+ this . mainScene . dispose ( ) ;
189+ }
190+ this . mainScene = newScene ;
191+ newScene . create ( ) ;
192+ }
193+
194+ start ( ) : void {
195+ if ( ! this . isRunning ) {
196+ this . isRunning = true ;
197+ this . lastTime = performance . now ( ) ;
198+ this . gameLoop ( ) ;
199+ }
200+ }
201+
202+ stop ( ) : void {
203+ this . isRunning = false ;
204+ }
205+
206+ private gameLoop ( ) : void {
207+ if ( ! this . isRunning ) return ;
208+
209+ const currentTime = performance . now ( ) ;
210+ const deltaTime = ( currentTime - this . lastTime ) / 1000 ; // Convert to seconds
211+ this . lastTime = currentTime ;
212+
213+ this . render . startRender ( ) ;
214+
215+ if ( this . mainScene ) {
216+ this . mainScene . update ( deltaTime )
217+ this . mainScene . render ( )
218+ }
219+
220+ this . render . endRender ( ) ;
221+
222+ requestAnimationFrame ( this . gameLoop . bind ( this ) ) ;
223+ }
160224}
0 commit comments