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