1 /*
2  * GNUjump
3  * =======
4  *
5  * Copyright (C) 2005-2008, Juan Pedro Bolivar Puente
6  *
7  * GNUjump is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * GNUjump is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "gnujump.h"
22 #include "game.h"
23 #include "effects.h"
24 #include "tools.h"
25 
26 extern L_gblOptions gblOps;
27 extern SDL_Surface *screen;
28 
29 void
playHeroSound(data_t * gfx,int sound,replay_t * rep)30 playHeroSound (data_t * gfx, int sound, replay_t * rep)
31 {
32   if (sound == S_JUMP && gfx->gjump)
33     Mix_PlayChannel (-1, gfx->gjump, 0);
34   if (sound == S_FALL && gfx->gfall)
35     Mix_PlayChannel (-1, gfx->gfall, 0);
36   if (sound == S_DIE && gfx->gdie)
37     Mix_PlayChannel (-1, gfx->gdie, 0);
38   if (gblOps.recReplay)
39     rep->sounds |= sound;
40 }
41 
42 void
drawHero(data_t * gfx,hero_t * hero)43 drawHero (data_t * gfx, hero_t * hero)
44 {
45   SDL_Rect dest;
46 
47   /* In rotating surface, X and Y refer to the centre of the image */
48   dest.x =
49     hero->x + gfx->gameX - (getFrameRot (&hero->sprite[hero->id], 0)->w -
50 			    HEROSIZE) / 2 +
51     getFrameRot (&hero->sprite[hero->id], 0)->w / 2;
52   dest.y =
53     hero->y + gfx->gameY - (getFrameRot (&hero->sprite[hero->id], 0)->h -
54 			    HEROSIZE) + getFrameRot (&hero->sprite[hero->id],
55 						     0)->h / 2;
56 
57   printSpriteRot (&hero->sprite[hero->id], NULL, &dest, hero->dir,
58 		  hero->angle);
59 }
60 
61 void
drawScrolledBgPart(data_t * gfx,int x,int y,int w,int h,int th,int sc)62 drawScrolledBgPart (data_t * gfx, int x, int y, int w, int h, int th, int sc)
63 {
64   SDL_Rect src, dest;
65 
66   sc = th - sc;
67   src.x = x;
68   src.y = y + sc;
69   src.w = w;
70   src.h = th - sc;
71   dest.x = x;
72   dest.y = y;
73   dest.w = w;
74   dest.h = th - sc;
75   JPB_PrintSurface (gfx->gameBg, &src, &dest);
76 
77   dest.y += dest.h;
78   src.y = y;
79   dest.h = src.h = th;
80 
81   for (; dest.y < y + h - th; dest.y += dest.h)
82     {
83       //printf("TH:%d Y:%d SC: %d\n", th, dest.y, sc);
84       JPB_PrintSurface (gfx->gameBg, &src, &dest);
85     }
86 
87   src.h = dest.h = y + h - dest.y;
88   JPB_PrintSurface (gfx->gameBg, &src, &dest);
89 
90 }
91 
92 void
drawGame(data_t * gfx,game_t * game)93 drawGame (data_t * gfx, game_t * game)
94 {
95   int i, y, x, width;
96 
97   //printf("%d\n", gblOps.scrollBg);
98   if (gblOps.scrollBg && gfx->gameTileH)
99     {
100       drawScrolledBgPart (gfx, gfx->gameX + BLOCKSIZE, gfx->gameY,
101 			  BLOCKSIZE * (GRIDWIDTH - 2), BLOCKSIZE * GRIDHEIGHT,
102 			  gfx->gameTileH,
103 			  (int) (game->scrollTotal / 2) % gfx->gameTileH);
104       //printf("Total: %f\n", game->scrollTotal);
105       if (gfx->borderTileH)
106 	{
107 	  drawScrolledBgPart (gfx, gfx->gameX + BLOCKSIZE - gfx->borderTileW,
108 			      gfx->gameY, gfx->borderTileW,
109 			      BLOCKSIZE * GRIDHEIGHT, gfx->borderTileH,
110 			      (int) (game->scrollTotal * 2) %
111 			      gfx->borderTileH);
112 	  drawScrolledBgPart (gfx, gfx->gameX + (GRIDWIDTH - 1) * BLOCKSIZE,
113 			      gfx->gameY, gfx->borderTileW,
114 			      BLOCKSIZE * GRIDHEIGHT, gfx->borderTileH,
115 			      (int) (game->scrollTotal * 2) %
116 			      gfx->borderTileH);
117 	}
118       else
119 	{
120 	  drawBg (gfx->gameBg,
121 		  gfx->gameX, gfx->gameY,
122 		  BLOCKSIZE, BLOCKSIZE * GRIDHEIGHT);
123 
124 	  drawBg (gfx->gameBg,
125 		  gfx->gameX + BLOCKSIZE * (GRIDWIDTH - 1), gfx->gameY,
126 		  BLOCKSIZE, BLOCKSIZE * GRIDHEIGHT);
127 	}
128     }
129   else
130     {
131       drawBg (gfx->gameBg, gfx->gameX, gfx->gameY, BLOCKSIZE * GRIDWIDTH,
132 	      BLOCKSIZE * GRIDHEIGHT);
133     }
134 
135   for (y = game->floorTop % 5; y < GRIDHEIGHT; y += 5)
136     {
137       x = game->floor_l[(y + game->mapIndex) % GRIDHEIGHT];
138       width = game->floor_r[(y + game->mapIndex) % GRIDHEIGHT] - x + 1;
139       if ((y * BLOCKSIZE + game->scrollCount) < (GRIDHEIGHT - 1) * BLOCKSIZE)
140 	drawFloor (gfx, x, y * BLOCKSIZE + game->scrollCount, width);
141     }
142 
143   for (i = 0; i < game->numHeros; i++)
144     {
145       drawTrail (gfx, game->heros[i].trail, i);
146       drawBlur (gfx, game->heros[i].blur, i);
147     }
148 
149   for (i = 0; i < game->numHeros; i++)
150     if (game->heros[i].y < BLOCKSIZE * GRIDHEIGHT - HEROSIZE)
151       drawHero (gfx, &(game->heros[i]));
152 }
153 
154 int
drawBg(JPB_surface * surf,int x,int y,int w,int h)155 drawBg (JPB_surface * surf, int x, int y, int w, int h)
156 {
157   SDL_Rect rect;
158   rect.x = x;
159   rect.h = h;
160   rect.w = w;
161   rect.y = y;
162   JPB_PrintSurface (surf, &rect, &rect);
163   return TRUE;
164 }
165 
166 int
drawFloor(data_t * gfx,int x,int y,int bw)167 drawFloor (data_t * gfx, int x, int y, int bw)
168 {
169   SDL_Rect rect;
170   SDL_Rect src;
171   int j;
172 
173   rect.x = x * BLOCKSIZE + gfx->gameX;
174   rect.y = y + gfx->gameY;
175   src.x = src.y = 0;
176 
177   src.w = gfx->floorL->w;
178   src.h =
179     MIN (gfx->floorL->h, (gfx->gameY + (GRIDHEIGHT) * BLOCKSIZE) - rect.y);
180   JPB_PrintSurface (gfx->floorL, &src, &rect);
181 
182   for (j = 1; j < bw - 1; j++)
183     {
184       src.w = gfx->floorC->w;
185       src.h =
186 	MIN (gfx->floorC->h,
187 	     (gfx->gameY + (GRIDHEIGHT) * BLOCKSIZE) - rect.y);
188       rect.x = j * BLOCKSIZE + x * BLOCKSIZE + gfx->gameX;
189       JPB_PrintSurface (gfx->floorC, &src, &rect);
190     }
191   src.w = gfx->floorR->w;
192   src.h =
193     MIN (gfx->floorR->h, (gfx->gameY + (GRIDHEIGHT) * BLOCKSIZE) - rect.y);
194   rect.x =
195     j * BLOCKSIZE + x * BLOCKSIZE + gfx->gameX + BLOCKSIZE - gfx->floorR->w;
196   JPB_PrintSurface (gfx->floorR, &src, &rect);
197 
198   return TRUE;
199 }
200 
201 void
drawAnimatedSquare(data_t * gfx,Uint32 color,Uint8 alpha,int x,int y,int w,int h,int time)202 drawAnimatedSquare (data_t * gfx, Uint32 color, Uint8 alpha, int x, int y,
203 		    int w, int h, int time)
204 {
205   fader_t fader;
206   L_timer timer;
207   int xc = 0;
208   int ret = 0;
209 
210   if (gfx->gquestion)
211     Mix_PlayChannel (-1, gfx->gquestion, 0);
212 
213   x += w / 2;
214   initTimer (&timer, getFps ());
215   updateTimer (&timer);
216   setFader (&fader, 1, w / 2 + 1, time, 0);
217 
218   do
219     {
220       updateTimer (&timer);
221       ret = updateFader (&fader, timer.ms);
222       JPB_drawSquare (color, alpha, x + xc, y, fader.value - xc, h);
223       JPB_drawSquare (color, alpha, x - xc, y, xc - fader.value, h);
224       xc = fader.value;
225       FlipScreen ();
226     }
227   while (!ret);
228 
229 }
230 
231 void
drawScore(data_t * gfx,game_t * game,Uint32 currtime)232 drawScore (data_t * gfx, game_t * game, Uint32 currtime)
233 {
234   int i, j;
235   int x, y;
236   SDL_Rect rect;
237   char score[32];
238   char time[32];
239 
240   x = gfx->timeX;
241   y = gfx->timeY;
242   sprintf (time, "%d", currtime);
243   SFont_Write (gfx->timefont, x, y, time);
244 
245   for (i = 0; i < game->numHeros; i++)
246     {
247       sprintf (score, "%d", game->heros[i].floor);
248 
249       x = gfx->scoreX[i];
250       y = gfx->scoreY[i];
251 
252       SFont_Write (gfx->scorefont, x, y, score);
253 
254       rect.x = x = gfx->livesX[i];
255       rect.y = y = gfx->livesY[i];
256       rect.w = gfx->livePic->w;
257       rect.h = gfx->livePic->h;
258 
259       for (j = 0; j <= game->heros[i].lives; j++)
260 	{
261 	  JPB_PrintSurface (gfx->livePic, NULL, &rect);
262 	  if (gfx->liveAlign)
263 	    {
264 	      y += gfx->livePic->h;
265 	      rect.y = y;
266 	    }
267 	  else
268 	    {
269 	      x += gfx->livePic->w;
270 	      rect.x = x;
271 	    }
272 	}
273 
274       game->heros[i].prevLives = game->heros[i].lives;
275     }
276 }
277 
278 void
updateScore(data_t * gfx,game_t * game,Uint32 currtime)279 updateScore (data_t * gfx, game_t * game, Uint32 currtime)
280 {
281   int i, j;
282   int x, y;
283   SDL_Rect rect;
284   char score[32];
285   char prevscore[32];
286   char time[32];
287   char prevtime[32];
288   static int lastsec = -1;
289 
290   if ((currtime /= 1000) != lastsec)
291     {
292       sprintf (time, "%d", currtime);
293       sprintf (prevtime, "%d", lastsec);
294       lastsec = currtime;
295       x = gfx->timeX;
296       y = gfx->timeY;
297 
298       drawBg (gfx->gameBg, x - 1, y - 1,
299 	      SFont_TextWidth (gfx->timefont, prevtime) + 2,
300 	      SFont_TextHeight (gfx->timefont) + 2);
301 
302       SFont_Write (gfx->timefont, x, y, time);
303     }
304 
305   for (i = 0; i < game->numHeros; i++)
306     {
307       if (game->heros[i].floor != game->heros[i].prevFloor)
308 	{
309 	  sprintf (score, "%d", game->heros[i].floor);
310 	  sprintf (prevscore, "%d", game->heros[i].prevFloor);
311 
312 	  x = gfx->scoreX[i];
313 	  y = gfx->scoreY[i];
314 
315 	  drawBg (gfx->gameBg, x - 1, y - 1,
316 		  SFont_TextWidth (gfx->scorefont, prevscore) + 2,
317 		  SFont_TextHeight (gfx->scorefont) + 2);
318 
319 	  SFont_Write (gfx->scorefont, x, y, score);
320 	}
321       if (game->heros[i].prevLives != game->heros[i].lives)
322 	{
323 	  rect.x = x = gfx->livesX[i];
324 	  rect.y = y = gfx->livesY[i];
325 	  rect.w = gfx->livePic->w;
326 	  rect.h = gfx->livePic->h;
327 
328 	  if (gfx->liveAlign)
329 	    {
330 	      drawBg (gfx->gameBg, x, y,
331 		      gfx->livePic->w,
332 		      gfx->livePic->h * (game->heros[i].lives + 2));
333 	    }
334 	  else
335 	    {
336 	      drawBg (gfx->gameBg, x, y,
337 		      gfx->livePic->w * (game->heros[i].lives + 2),
338 		      gfx->livePic->h);
339 	    }
340 
341 	  for (j = 0; j <= game->heros[i].lives; j++)
342 	    {
343 	      JPB_PrintSurface (gfx->livePic, NULL, &rect);
344 	      if (gfx->liveAlign)
345 		{
346 		  y += gfx->livePic->h;
347 		  rect.y = y;
348 		}
349 	      else
350 		{
351 		  x += gfx->livePic->w;
352 		  rect.x = x;
353 		}
354 	    }
355 
356 	  game->heros[i].prevLives = game->heros[i].lives;
357 	}
358     }
359 }
360