1
- import { drawSquare } from "./utils" ;
2
- import { Color } from "./config" ;
3
- import MAP_DATA from "./map-data" ;
4
- import AStar from "./pathfinding/a-star" ;
5
- import { World } from "./world/world" ;
6
- import Tile from "./world/tile" ;
7
- import { Pathfinding } from "./pathfinding/pathfinding" ;
8
- import * as constants from "./constants" ;
9
- import Vector from "./core/vector" ;
10
-
1
+ import { Color } from './config' ;
2
+ import * as constants from './constants' ;
3
+ import Vector from './core/vector' ;
4
+ import MAP_DATA from './map-data' ;
5
+ import AStar from './pathfinding/a-star' ;
6
+ import { Pathfinding } from './pathfinding/pathfinding' ;
7
+ import { drawSquare } from './utils' ;
8
+ import Tile from './world/tile' ;
9
+ import { World } from './world/world' ;
11
10
12
11
console . log ( JSON . stringify ( constants , null , ' ' ) ) ;
13
12
14
-
15
13
let world : World ;
16
14
let aStar : AStar < Tile > ;
17
15
let pathfinding : Pathfinding ;
@@ -20,33 +18,36 @@ let ctx: CanvasRenderingContext2D;
20
18
let prevPath : IPrintablePath = null ;
21
19
const timeCost = [ ] as number [ ] ;
22
20
23
-
24
21
init ( ) ;
25
- const failure = [ world . get ( 25 , 0 ) , world . get ( 56 , 25 ) ] ;
26
- const successful = [ world . get ( 25 , 2 ) , world . get ( 33 , 30 ) ] ;
22
+ const failure = [ world . get ( 25 , 0 ) , world . get ( 56 , 25 ) ] ;
23
+ const successful = [ world . get ( 25 , 2 ) , world . get ( 33 , 30 ) ] ;
27
24
28
-
29
- if ( constants . PERF_ITERATIONS )
30
- performanceTest ( constants . PERF_ITERATIONS ) ;
25
+ if ( constants . PERF_ITERATIONS ) performanceTest ( constants . PERF_ITERATIONS ) ;
31
26
32
27
frame ( ) ;
33
28
34
29
if ( constants . RANDOM_PATH_INTERVAL )
35
- setInterval ( randomPath , constants . RANDOM_PATH_INTERVAL )
36
-
30
+ setInterval ( randomPath , constants . RANDOM_PATH_INTERVAL ) ;
37
31
38
32
function init ( ) {
39
- measure ( ( ) => {
40
- const data = constants . GRID_MULTIPLIER ?
41
- multiplyGrid ( MAP_DATA , constants . GRID_MULTIPLIER ) :
42
- MAP_DATA ;
43
-
44
- world = new World ( data , constants . TILE_SIZE , constants . DIAGONAL_MOVEMENT_COST ) ;
45
- aStar = new AStar < Tile > ( constants . CLOSER_MODIFIER ) ;
46
- pathfinding = new Pathfinding ( world , aStar , constants . CLUSTER_SIZE ) ;
47
- } , {
48
- message : 'INIT' ,
49
- } ) ;
33
+ measure (
34
+ ( ) => {
35
+ const data = constants . GRID_MULTIPLIER
36
+ ? multiplyGrid ( MAP_DATA , constants . GRID_MULTIPLIER )
37
+ : MAP_DATA ;
38
+
39
+ world = new World (
40
+ data ,
41
+ constants . TILE_SIZE ,
42
+ constants . DIAGONAL_MOVEMENT_COST
43
+ ) ;
44
+ aStar = new AStar < Tile > ( constants . CLOSER_MODIFIER ) ;
45
+ pathfinding = new Pathfinding ( world , aStar , constants . CLUSTER_SIZE ) ;
46
+ } ,
47
+ {
48
+ message : 'INIT' ,
49
+ }
50
+ ) ;
50
51
51
52
canvas = document . querySelector ( 'canvas' ) ;
52
53
ctx = canvas . getContext ( '2d' ) ;
@@ -55,22 +56,20 @@ function init() {
55
56
ctx . translate ( constants . TILE_SIZE , constants . TILE_SIZE ) ;
56
57
}
57
58
58
-
59
59
function frame ( ) {
60
60
ctx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
61
- world . forEach ( tile => tile . print ( ctx , constants . DRAW_GRID ) ) ;
62
61
63
- if ( constants . DRAW_CLUSTERS )
64
- drawClusters ( ) ;
65
-
62
+ if ( constants . DRAW_CLUSTERS ) drawClusters ( ) ;
63
+
64
+ world . forEach ( ( tile ) => tile . print ( ctx , constants . DRAW_GRID ) ) ;
65
+
66
66
requestAnimationFrame ( frame ) ;
67
67
}
68
68
69
-
70
69
function drawClusters ( ) {
71
70
pathfinding . forEach ( ( cluster , pathfinding ) => {
72
71
const depth = 0 ;
73
- const size = ( constants . CLUSTER_SIZE ** ( depth + 1 ) ) * constants . TILE_SIZE ;
72
+ const size = constants . CLUSTER_SIZE ** ( depth + 1 ) * constants . TILE_SIZE ;
74
73
const coords = cluster . location . multiply ( size ) ;
75
74
76
75
drawSquare ( ctx , coords . x , coords . y , size , {
@@ -80,56 +79,58 @@ function drawClusters() {
80
79
} ) ;
81
80
}
82
81
83
-
84
82
function randomPath ( ) {
85
- if ( prevPath )
86
- prevPath . remove ( ) ;
87
-
88
- const start = new Vector ( random ( world . size . x ) , random ( world . size . y ) ) ;
89
- const end = new Vector ( random ( world . size . x ) , random ( world . size . y ) ) ;
90
- console . log ( `drawPath(world.get(${ start . x } , ${ start . y } ), world.get(${ end . x } , ${ end . y } ))` ) ;
91
-
92
- prevPath = drawPath (
93
- world . get ( start . x , start . y ) ,
94
- world . get ( end . x , end . y ) ,
83
+ if ( prevPath ) prevPath . remove ( ) ;
84
+
85
+ let start , end ;
86
+
87
+ do {
88
+ start = new Vector ( random ( world . size . x ) , random ( world . size . y ) ) ;
89
+ } while ( world . get ( start . x , start . y ) . isObstacle ) ;
90
+
91
+ do {
92
+ end = new Vector ( random ( world . size . x ) , random ( world . size . y ) ) ;
93
+ } while ( world . get ( end . x , end . y ) . isObstacle ) ;
94
+
95
+ console . log (
96
+ `drawPath(world.get(${ start . x } , ${ start . y } ), world.get(${ end . x } , ${ end . y } ))`
95
97
) ;
96
- }
97
98
99
+ prevPath = drawPath ( world . get ( start . x , start . y ) , world . get ( end . x , end . y ) ) ;
100
+ }
98
101
99
102
function drawPath ( from : Tile , to : Tile ) : IPrintablePath {
100
- const {
101
- duration ,
102
- result ,
103
- } = measure ( ( ) => pathfinding . resolve ( from , to ) || { tiles : [ ] as Tile [ ] } , {
104
- log : false ,
105
- } ) ;
103
+ const { duration , result } = measure (
104
+ ( ) => pathfinding . resolve ( from , to ) || { tiles : [ ] as Tile [ ] } ,
105
+ {
106
+ log : false ,
107
+ }
108
+ ) ;
106
109
107
- for ( const tile of result . tiles )
108
- tile . color = constants . PATH_COLOR ;
110
+ for ( const tile of result . tiles ) tile . color = constants . PATH_COLOR ;
109
111
110
112
from . color = constants . START_COLOR ;
111
113
to . color = constants . END_COLOR ;
112
-
114
+
113
115
( result as any ) . remove = ( ) => {
114
116
from . color = null ;
115
117
to . color = null ;
116
118
117
- for ( const tile of result . tiles )
118
- tile . color = null ;
119
- }
119
+ for ( const tile of result . tiles ) tile . color = null ;
120
+ } ;
120
121
121
122
if ( constants . LOG_AVERAGE ) {
122
123
timeCost . push ( duration ) ;
123
- const average = timeCost . reduce ( ( prev , current ) => prev + current ) / timeCost . length ;
124
+ const average =
125
+ timeCost . reduce ( ( prev , current ) => prev + current ) / timeCost . length ;
124
126
console . log ( 'AVERAGE A*' , average , result . tiles . length ) ;
125
127
}
126
-
128
+
127
129
return result as IPrintablePath ;
128
130
}
129
131
130
-
131
132
function performanceTest ( repetitions : number ) {
132
- const cases : { [ key : string ] : ( ) => void } = {
133
+ const cases : { [ key : string ] : ( ) => void } = {
133
134
'successful non-hierarchical' : ( ) => {
134
135
for ( let i = 0 ; i < repetitions ; i ++ )
135
136
aStar . getPath ( successful [ 0 ] , successful [ 1 ] ) ;
@@ -148,31 +149,26 @@ function performanceTest(repetitions: number) {
148
149
} ,
149
150
} ;
150
151
151
- for ( const key of Object . keys ( cases ) )
152
- measure ( cases [ key ] , { message : key } ) ;
152
+ for ( const key of Object . keys ( cases ) ) measure ( cases [ key ] , { message : key } ) ;
153
153
}
154
154
155
-
156
155
function random ( max : number = 1 , min : number = 0 ) {
157
- return Math . floor ( Math . random ( ) * ( max - min ) ) + min
156
+ return Math . floor ( Math . random ( ) * ( max - min ) ) + min ;
158
157
}
159
158
160
-
161
- function measure ( operation : Function , {
162
- message = 'Operation' ,
163
- log = true ,
164
- } = { } ) {
159
+ function measure (
160
+ operation : Function ,
161
+ { message = 'Operation' , log = true } = { }
162
+ ) {
165
163
const before = performance . now ( ) ;
166
164
const result = operation ( ) ;
167
165
const after = performance . now ( ) ;
168
166
const duration = after - before ;
169
167
170
- if ( log )
171
- console . log ( `${ message } = ${ duration } ms` ) ;
172
-
173
- return { duration, result } ;
174
- }
168
+ if ( log ) console . log ( `${ message } = ${ duration } ms` ) ;
175
169
170
+ return { duration, result } ;
171
+ }
176
172
177
173
function multiplyGrid ( grid : number [ ] [ ] , multiplier : number ) {
178
174
if ( multiplier === 0 ) return [ ] ;
@@ -182,20 +178,19 @@ function multiplyGrid(grid: number[][], multiplier: number) {
182
178
183
179
grid . forEach ( ( row , y ) => {
184
180
for ( let i = 0 ; i < multiplier ; i ++ )
185
- result [ y * multiplier + i ] = [ ] as number [ ] ;
186
-
181
+ result [ y * multiplier + i ] = [ ] as number [ ] ;
182
+
187
183
row . forEach ( ( value , x ) => {
188
184
for ( let i = 0 ; i < multiplier ; i ++ )
189
185
for ( let j = 0 ; j < multiplier ; j ++ )
190
- result [ y * multiplier + i ] [ x * multiplier + j ] = value ;
186
+ result [ y * multiplier + i ] [ x * multiplier + j ] = value ;
191
187
} ) ;
192
188
} ) ;
193
189
194
190
return result ;
195
191
}
196
192
197
-
198
193
interface IPrintablePath {
199
194
tiles : Tile [ ] ;
200
195
remove ( ) : void ;
201
- }
196
+ }
0 commit comments