rnd-20041127-1-src
[rocksndiamonds.git] / src / game_em / graphics.c
1 /* 2000-08-13T14:36:17Z
2  *
3  * graphics manipulation crap
4  */
5
6 #include "global.h"
7 #include "display.h"
8 #include "level.h"
9
10
11 unsigned int frame;             /* current screen frame */
12 unsigned int screen_x;          /* current scroll position */
13 unsigned int screen_y;
14
15 /* tiles currently on screen */
16 static unsigned int screentiles[MAX_BUF_YSIZE][MAX_BUF_XSIZE];
17
18
19 /* copy the entire screen to the window at the scroll position
20  *
21  * perhaps use mit-shm to speed this up
22  */
23
24 void blitscreen(void)
25 {
26   unsigned int x = screen_x % (MAX_BUF_XSIZE * TILEX);
27   unsigned int y = screen_y % (MAX_BUF_YSIZE * TILEY);
28
29   if (x < 2 * TILEX && y < 2 * TILEY)
30   {
31     BlitBitmap(screenBitmap, window, x, y,
32                SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
33   }
34   else if (x < 2 * TILEX && y >= 2 * TILEY)
35   {
36     BlitBitmap(screenBitmap, window, x, y,
37                SCR_FIELDX * TILEX, MAX_BUF_YSIZE * TILEY - y,
38                SX, SY);
39     BlitBitmap(screenBitmap, window, x, 0,
40                SCR_FIELDX * TILEX, y - 2 * TILEY,
41                SX, SY + MAX_BUF_YSIZE * TILEY - y);
42   }
43   else if (x >= 2 * TILEX && y < 2 * TILEY)
44   {
45     BlitBitmap(screenBitmap, window, x, y,
46                MAX_BUF_XSIZE * TILEX - x, SCR_FIELDY * TILEY,
47                SX, SY);
48     BlitBitmap(screenBitmap, window, 0, y,
49                x - 2 * TILEX, SCR_FIELDY * TILEY,
50                SX + MAX_BUF_XSIZE * TILEX - x, SY);
51   }
52   else
53   {
54     BlitBitmap(screenBitmap, window, x, y,
55                MAX_BUF_XSIZE * TILEX - x, MAX_BUF_YSIZE * TILEY - y,
56                SX, SY);
57     BlitBitmap(screenBitmap, window, 0, y,
58                x - 2 * TILEX, MAX_BUF_YSIZE * TILEY - y,
59                SX + MAX_BUF_XSIZE * TILEX - x, SY);
60     BlitBitmap(screenBitmap, window, x, 0,
61                MAX_BUF_XSIZE * TILEX - x, y - 2 * TILEY,
62                SX, SY + MAX_BUF_YSIZE * TILEY - y);
63     BlitBitmap(screenBitmap, window, 0, 0,
64                x - 2 * TILEX, y - 2 * TILEY,
65                SX + MAX_BUF_XSIZE * TILEX - x, SY + MAX_BUF_YSIZE * TILEY - y);
66   }
67 }
68
69
70 /* draw differences between game tiles and screen tiles
71  *
72  * implicitly handles scrolling and restoring background under the sprites
73  *
74  * perhaps use mit-shm to speed this up
75  */
76
77 static void animscreen(void)
78 {
79   unsigned int x, y, dx, dy;
80   unsigned int obj;
81   unsigned int left = screen_x / TILEX;
82   unsigned int top = screen_y / TILEY;
83
84   for (y = top; y < top + MAX_BUF_YSIZE; y++)
85   {
86     dy = y % MAX_BUF_YSIZE;
87
88     for (x = left; x < left + MAX_BUF_XSIZE; x++)
89     {
90       int tile = Draw[y][x];
91       struct GraphicInfo_EM *g = &graphic_info_em_object[tile][frame];
92
93       dx = x % MAX_BUF_XSIZE;
94
95 #if 1
96       /* create unique graphic identifier to decide if tile must be redrawn */
97       obj = g->unique_identifier;
98
99       if (1 || screentiles[dy][dx] != obj)
100       {
101         int dst_x = dx * TILEX;
102         int dst_y = dy * TILEY;
103
104         if (g->width != TILEX || g->height != TILEY)
105           ClearRectangle(screenBitmap, dst_x, dst_y, TILEX, TILEY);
106
107         if (g->width > 0 && g->height > 0)
108           BlitBitmap(g->bitmap, screenBitmap,
109                      g->src_x + g->src_offset_x, g->src_y + g->src_offset_y,
110                      g->width, g->height,
111                      dst_x + g->dst_offset_x, dst_y + g->dst_offset_y);
112
113         screentiles[dy][dx] = obj;
114       }
115 #else
116       obj = map_obj[frame][tile];
117
118       if (screentiles[dy][dx] != obj)
119       {
120         BlitBitmap(objBitmap, screenBitmap,
121                    (obj / 512) * TILEX, (obj % 512) * TILEY / 16,
122                    TILEX, TILEY, dx * TILEX, dy * TILEY);
123
124         screentiles[dy][dx] = obj;
125       }
126 #endif
127     }
128   }
129 }
130
131
132 /* blit players to the screen
133  *
134  * handles transparency and movement
135  */
136
137 static void blitplayer(struct PLAYER *ply)
138 {
139   int dx, dy;
140   int old_x, old_y, new_x, new_y;
141   int src_x, src_y, dst_x, dst_y;
142   unsigned int x1, y1, x2, y2;
143 #if 1
144   unsigned short spr;
145 #else
146   unsigned short obj, spr;
147 #endif
148
149   if (!ply->alive)
150     return;
151
152   /* some casts to "int" are needed because of negative calculation values */
153   dx = (int)ply->x - (int)ply->oldx;
154   dy = (int)ply->y - (int)ply->oldy;
155   old_x = (int)ply->oldx + (7 - (int)frame) * dx / 8;
156   old_y = (int)ply->oldy + (7 - (int)frame) * dy / 8;
157   new_x = old_x + SIGN(dx);
158   new_y = old_y + SIGN(dy);
159
160   /* x1/y1 are left/top and x2/y2 are right/down part of the player movement */
161   x1 = (frame * ply->oldx + (8 - frame) * ply->x) * TILEX / 8;
162   y1 = (frame * ply->oldy + (8 - frame) * ply->y) * TILEY / 8;
163   x2 = x1 + TILEX - 1;
164   y2 = y1 + TILEY - 1;
165
166   if ((unsigned int)(x2 - screen_x) < ((MAX_BUF_XSIZE - 1) * TILEX - 1) &&
167       (unsigned int)(y2 - screen_y) < ((MAX_BUF_YSIZE - 1) * TILEY - 1))
168   {
169     struct GraphicInfo_EM *g;
170     int tile;
171
172     spr = map_spr[ply->num][frame][ply->anim];
173     x1 %= MAX_BUF_XSIZE * TILEX;
174     y1 %= MAX_BUF_YSIZE * TILEY;
175     x2 %= MAX_BUF_XSIZE * TILEX;
176     y2 %= MAX_BUF_YSIZE * TILEY;
177
178 #if 1
179
180 #if 1
181     g = &graphic_info_em_player[ply->num][ply->anim][frame];
182
183     /* draw the player to current location */
184     BlitBitmap(g->bitmap, screenBitmap,
185                g->src_x, g->src_y, TILEX, TILEY,
186                x1, y1);
187
188     /* draw the player to opposite wrap-around column */
189     BlitBitmap(g->bitmap, screenBitmap,
190                g->src_x, g->src_y, TILEX, TILEY,
191                x1 - MAX_BUF_XSIZE * TILEX, y1);
192
193     /* draw the player to opposite wrap-around row */
194     BlitBitmap(g->bitmap, screenBitmap,
195                g->src_x, g->src_y, TILEX, TILEY,
196                x1, y1 - MAX_BUF_YSIZE * TILEY);
197 #else
198     /* draw the player to current location */
199     BlitBitmap(sprBitmap, screenBitmap,
200                (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
201                x1, y1);
202
203     /* draw the player to opposite wrap-around column */
204     BlitBitmap(sprBitmap, screenBitmap,
205                (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
206                x1 - MAX_BUF_XSIZE * TILEX, y1);
207
208     /* draw the player to opposite wrap-around row */
209     BlitBitmap(sprBitmap, screenBitmap,
210                (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
211                x1, y1 - MAX_BUF_YSIZE * TILEY);
212 #endif
213
214     /* draw the field the player is moving from (masked over the player) */
215 #if 0
216     obj = screentiles[y1 / TILEY][x1 / TILEX];
217     src_x = (obj / 512) * TILEX;
218     src_y = (obj % 512) * TILEY / 16;
219     dst_x = (x1 / TILEX) * TILEX;
220     dst_y = (y1 / TILEY) * TILEY;
221 #endif
222
223 #if 1
224     tile = Draw[old_y][old_x];
225     g = &graphic_info_em_object[tile][frame];
226
227     if (g->width > 0 && g->height > 0)
228     {
229       src_x = g->src_x + g->src_offset_x;
230       src_y = g->src_y + g->src_offset_y;
231       dst_x = old_x % MAX_BUF_XSIZE * TILEX + g->dst_offset_x;
232       dst_y = old_y % MAX_BUF_YSIZE * TILEY + g->dst_offset_y;
233
234       SetClipOrigin(g->bitmap, g->bitmap->stored_clip_gc,
235                     dst_x - src_x, dst_y - src_y);
236       BlitBitmapMasked(g->bitmap, screenBitmap,
237                        src_x, src_y, g->width, g->height, dst_x, dst_y);
238     }
239 #else
240     SetClipOrigin(objBitmap, objBitmap->stored_clip_gc,
241                   dst_x - src_x, dst_y - src_y);
242     BlitBitmapMasked(objBitmap, screenBitmap,
243                      src_x, src_y, TILEX, TILEY, dst_x, dst_y);
244 #endif
245
246     /* draw the field the player is moving to (masked over the player) */
247 #if 0
248     obj = screentiles[y2 / TILEY][x2 / TILEX];
249     src_x = (obj / 512) * TILEX;
250     src_y = (obj % 512) * TILEY / 16;
251     dst_x = (x2 / TILEX) * TILEX;
252     dst_y = (y2 / TILEY) * TILEY;
253 #endif
254
255 #if 1
256     tile = Draw[new_y][new_x];
257     g = &graphic_info_em_object[tile][frame];
258
259     if (g->width > 0 && g->height > 0)
260     {
261       src_x = g->src_x + g->src_offset_x;
262       src_y = g->src_y + g->src_offset_y;
263       dst_x = new_x % MAX_BUF_XSIZE * TILEX + g->dst_offset_x;
264       dst_y = new_y % MAX_BUF_YSIZE * TILEY + g->dst_offset_y;
265
266       SetClipOrigin(g->bitmap, g->bitmap->stored_clip_gc,
267                     dst_x - src_x, dst_y - src_y);
268       BlitBitmapMasked(g->bitmap, screenBitmap,
269                        src_x, src_y, g->width, g->height, dst_x, dst_y);
270     }
271 #else
272     SetClipOrigin(objBitmap, objBitmap->stored_clip_gc,
273                   dst_x - src_x, dst_y - src_y);
274     BlitBitmapMasked(objBitmap, screenBitmap,
275                      src_x, src_y, TILEX, TILEY, dst_x, dst_y);
276 #endif
277
278 #else
279
280     if (objmaskBitmap)
281     {
282       obj = screentiles[y1 / TILEY][x1 / TILEX];
283       XCopyArea(display, objmaskBitmap, spriteBitmap, spriteGC,
284                 (obj / 512) * TILEX, (obj % 512) * TILEY / 16, TILEX, TILEY,
285                 -(x1 % TILEX), -(y1 % TILEY));
286
287       obj = screentiles[y2 / TILEY][x2 / TILEX];
288       XCopyArea(display, objmaskBitmap, spriteBitmap, spriteGC,
289                 (obj / 512) * TILEX, (obj % 512) * TILEY / 16, TILEX, TILEY,
290                 (MAX_BUF_XSIZE * TILEX - x1) % TILEX,
291                 (MAX_BUF_YSIZE * TILEY - y1) % TILEY);
292     }
293     else if (sprmaskBitmap)
294     {
295       XCopyArea(display, sprmaskBitmap, spriteBitmap, spriteGC,
296                 (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY, 0, 0);
297     }
298     else
299     {
300       XFillRectangle(display, spriteBitmap, spriteGC, 0, 0, TILEX, TILEY);
301     }
302
303     SetClipMask(sprBitmap, sprBitmap->stored_clip_gc, spriteBitmap);
304
305     SetClipOrigin(sprBitmap, sprBitmap->stored_clip_gc, x, y);
306     BlitBitmapMasked(sprBitmap, screenBitmap,
307                      (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
308                      x1, y1);
309
310     SetClipOrigin(sprBitmap, sprBitmap->stored_clip_gc,
311                   x - MAX_BUF_XSIZE * TILEX, y);
312     BlitBitmapMasked(sprBitmap, screenBitmap,
313                      (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
314                      x1 - MAX_BUF_XSIZE * TILEX, y1);
315
316     SetClipOrigin(sprBitmap, sprBitmap->stored_clip_gc,
317                   x1, y1 - MAX_BUF_YSIZE * TILEY);
318     BlitBitmapMasked(sprBitmap, screenBitmap,
319                      (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
320                      x1, y1 - MAX_BUF_YSIZE * TILEY);
321
322     SetClipMask(sprBitmap, sprBitmap->stored_clip_gc, None);
323 #endif
324
325     /* mark screen tiles as dirty */
326     screentiles[y1 / TILEY][x1 / TILEX] = -1;
327     screentiles[y2 / TILEY][x2 / TILEX] = -1;
328   }
329 }
330
331 void game_initscreen(void)
332 {
333   unsigned int x,y;
334
335   frame = 6;
336   screen_x = 0;
337   screen_y = 0;
338
339   for (y = 0; y < MAX_BUF_YSIZE; y++)
340     for (x = 0; x < MAX_BUF_XSIZE; x++)
341       screentiles[y][x] = -1;
342
343   DrawGameDoorValues_EM(lev.required, ply1.dynamite, lev.score,
344                         DISPLAY_TIME(lev.time + 4));
345 }
346
347 void game_animscreen(void)
348 {
349   unsigned int x,y;
350
351   x = (frame * ply1.oldx + (8 - frame) * ply1.x) * TILEX / 8
352     + ((SCR_FIELDX - 1) * TILEX) / 2;
353   y = (frame * ply1.oldy + (8 - frame) * ply1.y) * TILEY / 8
354     + ((SCR_FIELDY - 1) * TILEY) / 2;
355
356   if (x > lev.width * TILEX)
357     x = lev.width * TILEX;
358   if (y > lev.height * TILEY)
359     y = lev.height * TILEY;
360
361   if (x < SCR_FIELDX * TILEX)
362     x = SCR_FIELDX * TILEY;
363   if (y < SCR_FIELDY * TILEY)
364     y = SCR_FIELDY * TILEY;
365
366   screen_x = x - (SCR_FIELDX - 1) * TILEX;
367   screen_y = y - (SCR_FIELDY - 1) * TILEY;
368
369   animscreen();
370   blitplayer(&ply1);
371   blitplayer(&ply2);
372   blitscreen();
373
374   FlushDisplay();
375 }