11import { Engine , World , Bodies , Query , Vector , Composite , Body } from "matter-js" ;
22import { raycast } from "../../core/raycast" ;
33
4+ const frictionAir = .3 ;
5+
6+ export type BodyType = "wall" | "player" | "bullet" | "obstacle" ;
47
58export type GameSettings = {
9+ ai : {
10+ sensorSidesArrayAngle : number [ ] ,
11+ sensorMaxRange : number ,
12+ } ,
613 game : {
714 playerSize : number ,
815 } ,
@@ -19,8 +26,10 @@ export type GameSettings = {
1926export type GameInputPlayer = {
2027 walk : boolean ,
2128 rotate : number ,
22- fire : boolean ,
23- switchWeapon : number ,
29+ /** use item/fire weapon */
30+ use : boolean ,
31+ /** select item/weapon */
32+ switch : number ,
2433} ;
2534
2635export type GameInput = {
@@ -31,16 +40,16 @@ export type GameInput = {
3140export type GameStatePlayer = {
3241 health : number ,
3342 ammo : number [ ] ,
34- weapon : {
43+ item : {
3544 /**
36- * index of selected weapon
45+ * index of selected item/ weapon
3746 */
3847 selected : number ,
3948 /**
40- * after shooting this number is how to long it takes to shoot/swithch weapon again
49+ * after shooting this number is how to long it takes to shoot/use/ swithch item/ weapon again
4150 * 0 means shooting is possible
4251 */
43- relodingTime : number ,
52+ cooldown : number ,
4453 } ,
4554 position : {
4655 x : number ,
@@ -56,6 +65,7 @@ export type GameState = {
5665
5766const mergeSettings = ( s : GameSettings , t : Partial < GameSettings > ) : GameSettings =>
5867 ( {
68+ ai : { ...s . ai , ...t ?. ai } ,
5969 game : { ...s . game , ...t ?. game } ,
6070 map : { ...s . map , ...t ?. map } ,
6171 simulation : { ...s . simulation , ...t ?. simulation } ,
@@ -71,11 +81,16 @@ export class Game {
7181 public mapping : {
7282 /** index of body in this array is same with index in game state */
7383 players : Matter . Body [ ] ,
84+ walls : Matter . Body [ ] ,
7485 } ;
7586
7687 public static readonly SETTINGS_DEFAULT : Readonly < GameSettings > = {
88+ ai : {
89+ sensorSidesArrayAngle : [ Math . PI * 1 / 4 , Math . PI * 1 / 8 , Math . PI * 1 / 32 ] ,
90+ sensorMaxRange : 200 ,
91+ } ,
7792 map : {
78- size : 200 ,
93+ size : 300 ,
7994 borders : 10 ,
8095 } ,
8196 game : {
@@ -101,7 +116,7 @@ export class Game {
101116
102117 const mergeInput = ( ) => ( {
103118 players : this . gameState . players . map ( ( _ , i ) => ( {
104- fire : false , rotate : 0 , switchWeapon : - 1 , walk : false ,
119+ use : false , rotate : 0 , switch : - 1 , walk : false ,
105120 ...( userInput ?. players ?. [ i ] ) ,
106121 } ) ) ,
107122 } ) ;
@@ -136,57 +151,75 @@ export class Game {
136151
137152 public sensor ( playerIndex : number ) {
138153 const {
139- settings : { map : { size } } ,
154+ settings : {
155+ map : { size } ,
156+ ai : {
157+ sensorMaxRange, sensorSidesArrayAngle,
158+ } } ,
140159 gameState : { players } ,
141160 } = this ;
142161 const player = players [ playerIndex ] ;
143162 const playerEngineBody = this . mapping . players [ playerIndex ] ;
144163
145- const rayLengt = size * Math . pow ( 2 , 1 / 2 ) ;
164+ const sensorAngles = [ 0 ]
165+ . concat ( sensorSidesArrayAngle )
166+ . concat ( sensorSidesArrayAngle . map ( x => - x ) )
167+ . map ( x => player . position . angle + x )
168+ ;
146169
170+ const rayRange = Math . min ( size * Math . pow ( 2 , 1 / 2 ) , sensorMaxRange ) ;
147171 const playerVector = Vector . create ( player . position . x , player . position . y ) ;
148-
149172 const bodies = Composite . allBodies ( this . world as any ) . filter ( ( { id } ) => id !== playerEngineBody . id ) ;
150- return { point : raycast ( bodies , playerVector , Vector . rotate ( Vector . create ( 1 , 0 ) , player . position . angle ) , rayLengt ) ?. point } ;
173+
174+ return sensorAngles . map ( x => {
175+ const ray = raycast ( bodies , playerVector , Vector . rotate ( Vector . create ( 1 , 0 ) , x ) , rayRange ) ;
176+ if ( ! ray ?. point )
177+ return Vector . add ( playerVector , Vector . mult ( Vector . normalise ( Vector . rotate ( Vector . create ( 1 , 0 ) , x ) ) , rayRange ) ) ;
178+ else
179+ return ray . point ;
180+ } ) ;
151181 }
152182
153183 constructor ( userSettings : Partial < GameSettings > = { } ) {
154- // create engine
155184 const settings = this . settings = mergeSettings ( Game . SETTINGS_DEFAULT , userSettings ) ;
156- const engine = this . engine = Engine . create ( ) ;
157-
185+ // create engine
186+ this . engine = Engine . create ( ) ;
158187 const world = this . world ;
159188
160189 world . gravity . y = 0 ;
161190
162191
163192 const { map : { size, borders } , game : { playerSize } } = settings ;
164193 const center = size / 2 ;
165-
166- World . add ( world , Bodies . rectangle ( 0 , center , borders * 2 , size , { isStatic : true } ) ) ;
167- World . add ( world , Bodies . rectangle ( size , center , borders * 2 , size , { isStatic : true , angle : Math . PI } ) ) ;
168- World . add ( world , Bodies . rectangle ( center , 0 , size , borders * 2 , { isStatic : true , angle : Math . PI } ) ) ;
169- World . add ( world , Bodies . rectangle ( center , size , size , borders * 2 , { isStatic : true } ) ) ;
170-
171194 const playerPadding = 5 ;
172195 const playerFromBorder = borders + playerSize + playerPadding ;
173196
174197
175- const frictionAir = .3 ;
176- const p1 = Bodies . circle ( size - playerFromBorder , playerFromBorder , playerSize , { frictionAir, angle : Math . PI * 3 / 4 } ) ;
177- World . add ( world , p1 ) ;
178- const p2 = Bodies . circle ( playerFromBorder , size - playerFromBorder , playerSize , { frictionAir, angle : Math . PI * ( - 1 / 4 ) } ) ;
179- World . add ( world , p2 ) ;
198+
199+ const walls = [
200+ Bodies . rectangle ( 0 , center , borders * 2 , size , { isStatic : true } ) ,
201+ Bodies . rectangle ( size , center , borders * 2 , size , { isStatic : true , angle : Math . PI } ) ,
202+ Bodies . rectangle ( center , 0 , size , borders * 2 , { isStatic : true , angle : Math . PI } ) ,
203+ Bodies . rectangle ( center , size , size , borders * 2 , { isStatic : true } ) ,
204+ ] ;
205+ World . add ( world , walls ) ;
206+
207+ const players = [
208+ Bodies . circle ( size - playerFromBorder , playerFromBorder , playerSize , { frictionAir, angle : Math . PI * 3 / 4 } ) ,
209+ Bodies . circle ( playerFromBorder , size - playerFromBorder , playerSize , { frictionAir, angle : Math . PI * ( - 1 / 4 ) } ) ,
210+ ] ;
211+ World . add ( world , players ) ;
180212
181213 this . mapping = {
182- players : [ p1 , p2 ] ,
214+ players,
215+ walls,
183216 } ;
184217
185218 this . gameState = {
186- players : [ p1 , p2 ] . map ( ( { position : { x, y } , angle } ) =>
219+ players : players . map ( ( { position : { x, y } , angle } ) =>
187220 ( {
188221 ammo : [ ] , health : 1 ,
189- weapon : { relodingTime : 0 , selected : 0 } ,
222+ item : { cooldown : 0 , selected : 0 } ,
190223 position : { x, y, angle } ,
191224 } as GameStatePlayer ) ) ,
192225 } ;
0 commit comments