1 /***************************************************************************
2 Chooser.cpp - description
3 -------------------
4 begin : Tue Jan 27 2004
5 copyright : (C) 2004 by upi
6 email : upi@feel
7 ***************************************************************************/
8
9
10 #include "Chooser.h"
11 #include "PlayerSelect.h"
12 #include "Backend.h"
13 #include "Event.h"
14 #include "State.h"
15
16 #include "SDL_image.h"
17 #include "gfx.h"
18 #include "common.h"
19 #include "sge_primitives.h"
20
21
22 CChooser g_oChooser;
23
24
CChooser()25 CChooser::CChooser()
26 {
27 m_iNumberOfFighters = -1;
28 m_poScreen = NULL;
29 for ( int i=0; i<MAXPLAYERS; ++i )
30 {
31 m_abRectangleVisible[i] = false;
32 m_aiPlayerPosition[i] = 0;
33 }
34 x1=y1=0;
35 x2=y2=1;
36 m_iRows = m_iCols = 1;
37 }
38
39
~CChooser()40 CChooser::~CChooser()
41 {
42 // Should free the portraits..
43 }
44
45
Init()46 void CChooser::Init()
47 {
48 if ( m_iNumberOfFighters >= 0 )
49 {
50 // Should only run once.
51 return;
52 }
53
54 m_aiColors[0] = C_LIGHTGREEN;
55 m_aiColors[1] = C_LIGHTMAGENTA;
56 m_aiColors[2] = C_YELLOW;
57 m_aiColors[3] = C_LIGHTBLUE;
58
59 // 1. Query the list of fighters from PlayerSelect.
60
61 m_iNumberOfFighters = g_oBackend.GetNumberOfFighters();
62 if ( m_iNumberOfFighters > 100 )
63 {
64 m_iNumberOfFighters = 100;
65 }
66 if ( m_iNumberOfFighters < 0 )
67 {
68 m_iNumberOfFighters = 0;
69 }
70
71 char pcFilename[FILENAME_MAX+1];
72 const char* s;
73 int i;
74
75 for ( i=0; i<m_iNumberOfFighters; ++i )
76 {
77 // Load the info of fighter #i
78 FighterEnum enFighter = g_oBackend.GetFighterID( i );
79 debug( "Fighter %d ID is %d\n", i, enFighter );
80 m_aenFighters[i] = enFighter;
81
82 // Load the portrait of fighter #i
83 g_oBackend.PerlEvalF( "GetFighterStats(%d);", enFighter );
84 s = g_oBackend.GetPerlString( "Portrait" );
85
86 strcpy( pcFilename, DATADIR );
87 strcat( pcFilename, "/characters/" );
88 strcat( pcFilename, s );
89
90 m_apoPortraits[i] = IMG_Load( pcFilename );
91 if ( m_apoPortraits[i] ) SDL_SetColorKey( m_apoPortraits[i], 0, 0 );
92 }
93 for ( i=m_iNumberOfFighters; i<100; ++i )
94 {
95 m_aenFighters[i] = UNKNOWN;
96 m_apoPortraits[i] = NULL;
97 }
98
99 Resize( 158, 74, 483, 479 );
100
101 for ( i=0; i<MAXPLAYERS; ++i )
102 {
103 m_aiPlayerPosition[i] = FighterToPosition( g_oPlayerSelect.GetPlayerInfo(i).m_enFighter );
104 }
105 }
106
107
108 #define LINEWIDTH 5
109
Draw()110 void CChooser::Draw()
111 {
112 Init();
113
114 int i;
115
116 for ( i = 0; i<m_iCols * m_iRows; ++i )
117 {
118
119 // Blit portrait # i
120
121 if ( i >= m_iNumberOfFighters
122 || NULL == m_apoPortraits[i] )
123 {
124 DrawRectangle( i, C_BLACK );
125 continue;
126 }
127
128 // Calculate the bounding rectangle of the character portrait
129
130 SDL_Rect oDst = GetRect(i);
131 SDL_Rect oSrc;
132 oSrc.x = (m_apoPortraits[i]->w - oDst.w) / 2;
133 oSrc.y = (m_apoPortraits[i]->h - oDst.h) / 2;
134 oSrc.w = oDst.w;
135 oSrc.h = oDst.h;
136
137 Uint32 iBgColor = m_aenFighters[i] < 100 ? C_YELLOW: C_LIGHTBLUE;
138 sge_FilledRectAlpha( m_poScreen, oDst.x, oDst.y, oDst.x+oDst.w, oDst.y+oDst.h, iBgColor, 64 );
139 SDL_BlitSurface( m_apoPortraits[i], &oSrc, m_poScreen, &oDst );
140 DrawRectangle( i, C_BLACK );
141 }
142 }
143
144
145
Start(SDL_Surface * a_poScreen)146 void CChooser::Start( SDL_Surface* a_poScreen )
147 {
148 Init();
149 m_poScreen = a_poScreen;
150 }
151
152
153
Stop()154 void CChooser::Stop()
155 {
156 m_poScreen = NULL;
157 }
158
159
160
Resize(int a_x1,int a_y1,int a_x2,int a_y2)161 void CChooser::Resize( int a_x1, int a_y1, int a_x2, int a_y2 )
162 {
163 Init();
164 x1 = a_x1;
165 y1 = a_y1;
166 x2 = a_x2 + LINEWIDTH;
167 y2 = a_y2 + LINEWIDTH;
168 m_iRows = 1;
169 m_iCols = 1;
170
171 while ( m_iRows * m_iCols < m_iNumberOfFighters )
172 {
173 double dColDensity = double(x2-x1) / double(m_iCols);
174 double dRowDensity = double(y2-y1) / double(m_iRows);
175
176 if ( dRowDensity > dColDensity *1.1 )
177 {
178 m_iRows ++;
179 }
180 else
181 {
182 m_iCols ++;
183 }
184 }
185 }
186
187
MarkFighter(FighterEnum a_enFighter,Uint32 a_iColor)188 void CChooser::MarkFighter( FighterEnum a_enFighter, Uint32 a_iColor )
189 {
190 SDL_Rect oRect = GetFighterRect( a_enFighter );
191 if ( oRect.w <= 0 )
192 {
193 return;
194 }
195
196 int x1 = oRect.x;
197 int y1 = oRect.y;
198 int w = oRect.w;
199 int h = oRect.h;
200
201 sge_Line(m_poScreen, x1+5, y1+5, x1 + w-10, y1 + h-10, a_iColor);
202 sge_Line(m_poScreen, x1 + w-10, y1+5, x1+5, y1 + h-10, a_iColor);
203 x1++;
204 sge_Line(m_poScreen, x1+5, y1+5, x1 + w-10, y1 + h-10, a_iColor);
205 sge_Line(m_poScreen, x1 + w-10, y1+5, x1+5, y1 + h-10, a_iColor);
206 y1++;
207 sge_Line(m_poScreen, x1+5, y1+5, x1 + w-10, y1 + h-10, a_iColor);
208 sge_Line(m_poScreen, x1 + w-10, y1+5, x1+5, y1 + h-10, a_iColor);
209 x1--;
210 sge_Line(m_poScreen, x1+5, y1+5, x1 + w-10, y1 + h-10, a_iColor);
211 sge_Line(m_poScreen, x1 + w-10, y1+5, x1+5, y1 + h-10, a_iColor);
212 }
213
214
215
GetPortrait(FighterEnum a_enFighter)216 SDL_Surface* CChooser::GetPortrait( FighterEnum a_enFighter )
217 {
218 Init();
219
220 for ( int i=0; i<m_iNumberOfFighters; ++i )
221 {
222 if ( m_aenFighters[i] == a_enFighter )
223 {
224 return m_apoPortraits[i];
225 }
226 }
227 return NULL;
228 }
229
230
231
DrawPortrait(FighterEnum a_enFighter,SDL_Surface * a_poScreen,const SDL_Rect & a_roRect)232 void CChooser::DrawPortrait( FighterEnum a_enFighter, SDL_Surface* a_poScreen, const SDL_Rect& a_roRect )
233 {
234 SDL_Surface* poPortrait = GetPortrait( a_enFighter );
235
236 if ( NULL == poPortrait )
237 {
238 return ;
239 }
240
241 SDL_Rect oDst = a_roRect;
242 SDL_Rect oSrc;
243 oSrc.x = (poPortrait->w - oDst.w) / 2;
244 oSrc.y = (poPortrait->h - oDst.h) / 2;
245 oSrc.w = oDst.w;
246 oSrc.h = oDst.h;
247
248 SDL_BlitSurface( poPortrait, &oSrc, a_poScreen, &oDst );
249 }
250
251
252
GetCurrentFighter(int a_iPlayer)253 FighterEnum CChooser::GetCurrentFighter( int a_iPlayer )
254 {
255 return PositionToFighter( m_aiPlayerPosition[ a_iPlayer ] );
256 }
257
258
MoveRectangle(int a_iPlayer,int a_iDirection)259 void CChooser::MoveRectangle( int a_iPlayer, int a_iDirection )
260 {
261 int& riPlayerPosition = m_aiPlayerPosition[ a_iPlayer ];
262
263 int iNew = riPlayerPosition;
264
265 switch ( a_iDirection )
266 {
267 case Mk_UP: if ( iNew >= m_iCols ) iNew -= m_iCols; break;
268 case Mk_DOWN: if ( iNew / m_iCols < m_iRows-1 ) iNew += m_iCols; break;
269 case Mk_LEFT: if ( iNew % m_iCols > 0 ) --iNew; break;
270 case Mk_RIGHT: if ( iNew % m_iCols < m_iCols-1 ) ++iNew; break;
271 }
272
273 if ( iNew != riPlayerPosition )
274 {
275 ClearRectangle( a_iPlayer );
276 riPlayerPosition = iNew;
277 DrawRectangle( a_iPlayer );
278 }
279 }
280
281
SetRectangle(int a_iPlayer,FighterEnum a_enFighter)282 void CChooser::SetRectangle( int a_iPlayer, FighterEnum a_enFighter )
283 {
284 int& riPlayerPosition = m_aiPlayerPosition[ a_iPlayer ];
285 int iNew = FighterToPosition( a_enFighter );
286
287 if ( iNew != riPlayerPosition )
288 {
289 ClearRectangle( a_iPlayer );
290 riPlayerPosition = iNew;
291 DrawRectangle( a_iPlayer );
292 }
293 }
294
295
SetRectangleVisible(int a_iPlayer,bool a_bVisible)296 void CChooser::SetRectangleVisible( int a_iPlayer, bool a_bVisible )
297 {
298 m_abRectangleVisible[ a_iPlayer ] = a_bVisible;
299 if ( a_bVisible )
300 {
301 DrawRectangle( a_iPlayer );
302 }
303 else
304 {
305 ClearRectangle( a_iPlayer );
306 }
307 }
308
309
IsRectangleVisible(int a_iPlayer)310 bool CChooser::IsRectangleVisible( int a_iPlayer )
311 {
312 return m_abRectangleVisible[ a_iPlayer ];
313 }
314
315
DrawRectangles(int a_iStartingWith)316 void CChooser::DrawRectangles( int a_iStartingWith )
317 {
318 a_iStartingWith = a_iStartingWith % g_oState.m_iNumPlayers;
319 int i = a_iStartingWith;
320
321 while (1)
322 {
323 DrawRectangle(i);
324 i = (i+1) % g_oState.m_iNumPlayers;
325
326 if ( i==a_iStartingWith)
327 break;
328 }
329 }
330
331
332
FighterToPosition(FighterEnum a_enFighter)333 int CChooser::FighterToPosition( FighterEnum a_enFighter )
334 {
335 for ( int i=0; i<m_iNumberOfFighters; ++i )
336 {
337 if ( m_aenFighters[i] == a_enFighter )
338 {
339 return i;
340 }
341 }
342
343 return 0;
344 }
345
346
PositionToFighter(int a_iPosition)347 FighterEnum CChooser::PositionToFighter( int a_iPosition )
348 {
349 if ( a_iPosition < 0
350 || a_iPosition >= m_iNumberOfFighters )
351 {
352 return UNKNOWN;
353 }
354 return m_aenFighters[a_iPosition];
355 }
356
357
GetFighterRect(FighterEnum a_enFighter)358 SDL_Rect CChooser::GetFighterRect( FighterEnum a_enFighter )
359 {
360 return GetRect( FighterToPosition( a_enFighter ) );
361 }
362
363
GetRect(int a_iPosition)364 SDL_Rect CChooser::GetRect( int a_iPosition )
365 {
366 SDL_Rect oRect;
367 oRect.x = oRect.y = oRect.w = oRect.h = 0;
368
369 if ( a_iPosition < 0 || a_iPosition >= m_iRows*m_iCols )
370 return oRect;
371
372 int iRow = a_iPosition / m_iCols;
373 int iCol = a_iPosition % m_iCols;
374 oRect.x = (x2-x1-LINEWIDTH) * iCol / m_iCols + LINEWIDTH + x1;
375 oRect.y = (y2-y1-LINEWIDTH) * iRow / m_iRows + LINEWIDTH + y1;
376 oRect.w = (x2-x1-LINEWIDTH) * (iCol+1) / m_iCols + LINEWIDTH + x1 - oRect.x;
377 oRect.h = (y2-y1-LINEWIDTH) * (iRow+1) / m_iRows + LINEWIDTH + y1 - oRect.y;
378
379 return oRect;
380 }
381
382
DrawRectangle(int a_iPlayer)383 void CChooser::DrawRectangle( int a_iPlayer )
384 {
385 if ( ! m_abRectangleVisible[a_iPlayer] )
386 {
387 return;
388 }
389
390 DrawRectangle( m_aiPlayerPosition[a_iPlayer], m_aiColors[a_iPlayer] );
391 }
392
393
ClearRectangle(int a_iPlayer)394 void CChooser::ClearRectangle( int a_iPlayer )
395 {
396 DrawRectangle( m_aiPlayerPosition[a_iPlayer], C_BLACK );
397 }
398
399
DrawRectangle(int a_iPosition,Uint32 a_iColor)400 void CChooser::DrawRectangle( int a_iPosition, Uint32 a_iColor )
401 {
402 SDL_Rect oRect = GetRect( a_iPosition );
403 oRect.x -= LINEWIDTH - 1;
404 oRect.y -= LINEWIDTH - 1;
405
406 /* ===1====
407 | |
408 3 4
409 | |
410 ===2==== */
411
412 SDL_Rect r = oRect;
413 r.h = LINEWIDTH;
414 r.w += LINEWIDTH;
415 SDL_Rect r1 = r;
416 SDL_FillRect( m_poScreen, &r1, a_iColor );
417
418 r.y += oRect.h;
419 r1 = r;
420 SDL_FillRect( m_poScreen, &r1, a_iColor );
421
422 r.y = oRect.y;
423 r.w = LINEWIDTH;
424 r.h = oRect.h;
425 r1 = r;
426 SDL_FillRect( m_poScreen, &r1, a_iColor );
427
428 r.x += oRect.w;
429 r1 = r;
430 SDL_FillRect( m_poScreen, &r1, a_iColor );
431 }
432
433