1+ import  {  getColor  }  from  '@irdashies/utils/colors' ; 
2+ import  {  TrackDrawing ,  TrackDriver  }  from  './TrackCanvas' ; 
3+ 
4+ export  const  setupCanvasContext  =  ( 
5+   ctx : CanvasRenderingContext2D , 
6+   scale : number , 
7+   offsetX : number , 
8+   offsetY : number 
9+ )  =>  { 
10+   ctx . save ( ) ; 
11+   ctx . translate ( offsetX ,  offsetY ) ; 
12+   ctx . scale ( scale ,  scale ) ; 
13+   
14+   // Apply shadow 
15+   ctx . shadowColor  =  'black' ; 
16+   ctx . shadowBlur  =  2 ; 
17+   ctx . shadowOffsetX  =  1 ; 
18+   ctx . shadowOffsetY  =  1 ; 
19+ } ; 
20+ 
21+ export  const  drawTrack  =  ( 
22+   ctx : CanvasRenderingContext2D , 
23+   path2DObjects : {  inside : Path2D  |  null  } 
24+ )  =>  { 
25+   if  ( ! path2DObjects . inside )  return ; 
26+ 
27+   // Draw black outline first 
28+   ctx . strokeStyle  =  'black' ; 
29+   ctx . lineWidth  =  40 ; 
30+   ctx . stroke ( path2DObjects . inside ) ; 
31+ 
32+   // Draw white track on top 
33+   ctx . strokeStyle  =  'white' ; 
34+   ctx . lineWidth  =  20 ; 
35+   ctx . stroke ( path2DObjects . inside ) ; 
36+ } ; 
37+ 
38+ export  const  drawStartFinishLine  =  ( 
39+   ctx : CanvasRenderingContext2D , 
40+   startFinishLine : {  point : {  x : number ;  y : number  } ;  perpendicular : {  x : number ;  y : number  }  }  |  null 
41+ )  =>  { 
42+   if  ( ! startFinishLine )  return ; 
43+ 
44+   const  lineLength  =  60 ;  // Length of the start/finish line 
45+   const  {  point : sfPoint ,  perpendicular }  =  startFinishLine ; 
46+ 
47+   // Calculate the start and end points of the line 
48+   const  startX  =  sfPoint . x  -  ( perpendicular . x  *  lineLength )  /  2 ; 
49+   const  startY  =  sfPoint . y  -  ( perpendicular . y  *  lineLength )  /  2 ; 
50+   const  endX  =  sfPoint . x  +  ( perpendicular . x  *  lineLength )  /  2 ; 
51+   const  endY  =  sfPoint . y  +  ( perpendicular . y  *  lineLength )  /  2 ; 
52+ 
53+   ctx . lineWidth  =  20 ; 
54+   ctx . strokeStyle  =  getColor ( 'red' ) ; 
55+   ctx . lineCap  =  'square' ; 
56+ 
57+   // Draw the perpendicular line 
58+   ctx . beginPath ( ) ; 
59+   ctx . moveTo ( startX ,  startY ) ; 
60+   ctx . lineTo ( endX ,  endY ) ; 
61+   ctx . stroke ( ) ; 
62+ } ; 
63+ 
64+ export  const  drawTurnNames  =  ( 
65+   ctx : CanvasRenderingContext2D , 
66+   turns : TrackDrawing [ 'turns' ] , 
67+   enableTurnNames : boolean  |  undefined 
68+ )  =>  { 
69+   if  ( ! enableTurnNames  ||  ! turns )  return ; 
70+ 
71+   turns . forEach ( ( turn )  =>  { 
72+     if  ( ! turn . content  ||  ! turn . x  ||  ! turn . y )  return ; 
73+     ctx . textAlign  =  'center' ; 
74+     ctx . textBaseline  =  'middle' ; 
75+     ctx . fillStyle  =  'white' ; 
76+     ctx . font  =  '2rem sans-serif' ; 
77+     ctx . fillText ( turn . content ,  turn . x ,  turn . y ) ; 
78+   } ) ; 
79+ } ; 
80+ 
81+ export  const  drawDrivers  =  ( 
82+   ctx : CanvasRenderingContext2D , 
83+   calculatePositions : Record < number ,  TrackDriver  &  {  position : {  x : number ;  y : number  }  } > , 
84+   driverColors : Record < number ,  {  fill : string ;  text : string  } > 
85+ )  =>  { 
86+   Object . values ( calculatePositions ) 
87+     . sort ( ( a ,  b )  =>  Number ( a . isPlayer )  -  Number ( b . isPlayer ) )  // draws player last to be on top 
88+     . forEach ( ( {  driver,  position } )  =>  { 
89+       const  color  =  driverColors [ driver . CarIdx ] ; 
90+       if  ( ! color )  return ; 
91+ 
92+       ctx . fillStyle  =  color . fill ; 
93+       ctx . beginPath ( ) ; 
94+       ctx . arc ( position . x ,  position . y ,  40 ,  0 ,  2  *  Math . PI ) ; 
95+       ctx . fill ( ) ; 
96+       ctx . textAlign  =  'center' ; 
97+       ctx . textBaseline  =  'middle' ; 
98+       ctx . fillStyle  =  color . text ; 
99+       ctx . font  =  '2rem sans-serif' ; 
100+       ctx . fillText ( driver . CarNumber ,  position . x ,  position . y ) ; 
101+     } ) ; 
102+ } ;  
0 commit comments