rnd-20040918-1-src
[rocksndiamonds.git] / src / game_em / graphics.c
1 /* 2000-08-13T14:36:17Z
2  *
3  * graphics manipulation crap
4  */
5
6 #include <X11/Xlib.h>
7 #include <X11/Xutil.h>
8
9 #include "global.h"
10 #include "display.h"
11 #include "level.h"
12
13
14 #if defined(TARGET_X11)
15
16 unsigned int frame;             /* current screen frame */
17 unsigned int screen_x;          /* current scroll position */
18 unsigned int screen_y;
19
20 /* tiles currently on screen */
21 static unsigned short screentiles[MAX_BUF_YSIZE][MAX_BUF_XSIZE];
22
23
24 /* copy the entire screen to the window at the scroll position
25  *
26  * perhaps use mit-shm to speed this up
27  */
28
29 void blitscreen(void)
30 {
31   unsigned int x = screen_x % (MAX_BUF_XSIZE * TILEX);
32   unsigned int y = screen_y % (MAX_BUF_YSIZE * TILEY);
33
34   if (x < 2 * TILEX && y < 2 * TILEY)
35   {
36     BlitBitmap(screenBitmap, window, x, y,
37                SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
38   }
39   else if (x < 2 * TILEX && y >= 2 * TILEY)
40   {
41     BlitBitmap(screenBitmap, window, x, y,
42                SCR_FIELDX * TILEX, MAX_BUF_YSIZE * TILEY - y,
43                SX, SY);
44     BlitBitmap(screenBitmap, window, x, 0,
45                SCR_FIELDX * TILEX, y - 2 * TILEY,
46                SX, SY + MAX_BUF_YSIZE * TILEY - y);
47   }
48   else if (x >= 2 * TILEX && y < 2 * TILEY)
49   {
50     BlitBitmap(screenBitmap, window, x, y,
51                MAX_BUF_XSIZE * TILEX - x, SCR_FIELDY * TILEY,
52                SX, SY);
53     BlitBitmap(screenBitmap, window, 0, y,
54                x - 2 * TILEX, SCR_FIELDY * TILEY,
55                SX + MAX_BUF_XSIZE * TILEX - x, SY);
56   }
57   else
58   {
59     BlitBitmap(screenBitmap, window, x, y,
60                MAX_BUF_XSIZE * TILEX - x, MAX_BUF_YSIZE * TILEY - y,
61                SX, SY);
62     BlitBitmap(screenBitmap, window, 0, y,
63                x - 2 * TILEX, MAX_BUF_YSIZE * TILEY - y,
64                SX + MAX_BUF_XSIZE * TILEX - x, SY);
65     BlitBitmap(screenBitmap, window, x, 0,
66                MAX_BUF_XSIZE * TILEX - x, y - 2 * TILEY,
67                SX, SY + MAX_BUF_YSIZE * TILEY - y);
68     BlitBitmap(screenBitmap, window, 0, 0,
69                x - 2 * TILEX, y - 2 * TILEY,
70                SX + MAX_BUF_XSIZE * TILEX - x, SY + MAX_BUF_YSIZE * TILEY - y);
71   }
72
73   XFlush(display);
74 }
75
76
77 /* draw differences between game tiles and screen tiles
78  *
79  * implicitly handles scrolling and restoring background under the sprites
80  *
81  * perhaps use mit-shm to speed this up
82  */
83
84 static void animscreen(void)
85 {
86   unsigned int x, y, dx, dy;
87   unsigned short obj;
88   unsigned int left = screen_x / TILEX;
89   unsigned int top = screen_y / TILEY;
90
91   for (y = top; y < top + MAX_BUF_YSIZE; y++)
92   {
93     dy = y % MAX_BUF_YSIZE;
94     for (x = left; x < left + MAX_BUF_XSIZE; x++)
95     {
96       dx = x % MAX_BUF_XSIZE;
97       obj = map_obj[frame][Draw[y][x]];
98
99       if (screentiles[dy][dx] != obj)
100       {
101         screentiles[dy][dx] = obj;
102         BlitBitmap(objBitmap, screenBitmap,
103                    (obj / 512) * TILEX, (obj % 512) * TILEY / 16,
104                    TILEX, TILEY, dx * TILEX, dy * TILEY);
105       }
106     }
107   }
108 }
109
110
111 /* blit players to the screen
112  *
113  * handles transparency and movement
114  */
115
116 static void blitplayer(struct PLAYER *ply)
117 {
118   unsigned int x, y, dx, dy;
119   unsigned short obj, spr;
120
121   if (ply->alive)
122   {
123     x = (frame * ply->oldx + (8 - frame) * ply->x) * TILEX / 8;
124     y = (frame * ply->oldy + (8 - frame) * ply->y) * TILEY / 8;
125     dx = x + TILEX - 1;
126     dy = y + TILEY - 1;
127
128     if ((unsigned int)(dx - screen_x) < ((MAX_BUF_XSIZE - 1) * TILEX - 1) &&
129         (unsigned int)(dy - screen_y) < ((MAX_BUF_YSIZE - 1) * TILEY - 1))
130     {
131       spr = map_spr[ply->num][frame][ply->anim];
132       x  %= MAX_BUF_XSIZE * TILEX;
133       y  %= MAX_BUF_YSIZE * TILEY;
134       dx %= MAX_BUF_XSIZE * TILEX;
135       dy %= MAX_BUF_YSIZE * TILEY;
136
137       if (objmaskBitmap)
138       {
139         obj = screentiles[y / TILEY][x / TILEX];
140         XCopyArea(display, objmaskBitmap, spriteBitmap, spriteGC,
141                   (obj / 512) * TILEX, (obj % 512) * TILEY / 16, TILEX, TILEY,
142                   -(x % TILEX), -(y % TILEY));
143
144         obj = screentiles[dy / TILEY][dx / TILEX];
145         XCopyArea(display, objmaskBitmap, spriteBitmap, spriteGC,
146                   (obj / 512) * TILEX, (obj % 512) * TILEY / 16, TILEX, TILEY,
147                   (MAX_BUF_XSIZE * TILEX - x) % TILEX,
148                   (MAX_BUF_YSIZE * TILEY - y) % TILEY);
149       }
150       else if (sprmaskBitmap)
151       {
152         XCopyArea(display, sprmaskBitmap, spriteBitmap, spriteGC,
153                   (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY, 0, 0);
154       }
155       else
156       {
157         XFillRectangle(display, spriteBitmap, spriteGC, 0, 0, TILEX, TILEY);
158       }
159
160       screentiles[y / TILEY][x / TILEX] = -1; /* mark screen as dirty */
161       screentiles[dy / TILEY][dx / TILEX] = -1;
162
163 #if 1
164
165
166 #if 1
167
168       SetClipMask(sprBitmap, sprBitmap->stored_clip_gc, spriteBitmap);
169
170       SetClipOrigin(sprBitmap, sprBitmap->stored_clip_gc, x, y);
171       BlitBitmapMasked(sprBitmap, screenBitmap,
172                        (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
173                        x, y);
174
175       SetClipOrigin(sprBitmap, sprBitmap->stored_clip_gc,
176                     x - MAX_BUF_XSIZE * TILEX, y);
177       BlitBitmapMasked(sprBitmap, screenBitmap,
178                        (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
179                        x - MAX_BUF_XSIZE * TILEX, y);
180
181       SetClipOrigin(sprBitmap, sprBitmap->stored_clip_gc,
182                     x, y - MAX_BUF_YSIZE * TILEY);
183       BlitBitmapMasked(sprBitmap, screenBitmap,
184                        (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
185                        x, y - MAX_BUF_YSIZE * TILEY);
186
187       SetClipMask(sprBitmap, sprBitmap->stored_clip_gc, None);
188
189 #else
190
191       XSetClipMask(display, sprBitmap->stored_clip_gc, spriteBitmap);
192
193       XSetClipOrigin(display, sprBitmap->stored_clip_gc, x, y);
194       XCopyArea(display, sprBitmap->drawable, screenBitmap->drawable,
195                 sprBitmap->stored_clip_gc,
196                 (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
197                 x, y);
198
199       XSetClipOrigin(display, sprBitmap->stored_clip_gc,
200                      x - MAX_BUF_XSIZE * TILEX, y);
201       XCopyArea(display, sprBitmap->drawable, screenBitmap->drawable,
202                 sprBitmap->stored_clip_gc,
203                 (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
204                 x - MAX_BUF_XSIZE * TILEX, y);
205
206       XSetClipOrigin(display, sprBitmap->stored_clip_gc,
207                      x, y - MAX_BUF_YSIZE * TILEY);
208       XCopyArea(display, sprBitmap->drawable, screenBitmap->drawable,
209                 sprBitmap->stored_clip_gc,
210                 (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
211                 x, y - MAX_BUF_YSIZE * TILEY);
212
213       XSetClipMask(display, sprBitmap->stored_clip_gc, None);
214
215 #endif
216
217 #else
218
219       XSetClipMask(display, screenGC, spriteBitmap);
220       XSetClipOrigin(display, screenGC, x, y);
221       XCopyArea(display, sprPixmap, screenPixmap, screenGC,
222                 (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
223                 x, y);
224       XSetClipOrigin(display, screenGC, x - MAX_BUF_XSIZE * TILEX, y);
225       XCopyArea(display, sprPixmap, screenPixmap, screenGC,
226                 (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
227                 x - MAX_BUF_XSIZE * TILEX, y);
228       XSetClipOrigin(display, screenGC, x, y - MAX_BUF_YSIZE * TILEY);
229       XCopyArea(display, sprPixmap, screenPixmap, screenGC,
230                 (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
231                 x, y - MAX_BUF_YSIZE * TILEY);
232       XSetClipMask(display, screenGC, None);
233
234 #endif
235     }
236   }
237 }
238
239 void game_initscreen(void)
240 {
241   unsigned int x,y;
242
243   frame = 6;
244   screen_x = 0;
245   screen_y = 0;
246
247   for (y = 0; y < MAX_BUF_YSIZE; y++)
248     for (x = 0; x < MAX_BUF_XSIZE; x++)
249       screentiles[y][x] = -1;
250
251   DrawGameDoorValues_EM(lev.required, ply1.dynamite, lev.score,
252                         (lev.time + 4) / 5);
253 }
254
255 void game_animscreen(void)
256 {
257   unsigned int x,y;
258
259   x = (frame * ply1.oldx + (8 - frame) * ply1.x) * TILEX / 8
260     + ((SCR_FIELDX - 1) * TILEX) / 2;
261   y = (frame * ply1.oldy + (8 - frame) * ply1.y) * TILEY / 8
262     + ((SCR_FIELDY - 1) * TILEY) / 2;
263
264   if (x > lev.width * TILEX)
265     x = lev.width * TILEX;
266   if (y > lev.height * TILEY)
267     y = lev.height * TILEY;
268
269   if (x < SCR_FIELDX * TILEX)
270     x = SCR_FIELDX * TILEY;
271   if (y < SCR_FIELDY * TILEY)
272     y = SCR_FIELDY * TILEY;
273
274   screen_x = x - (SCR_FIELDX - 1) * TILEX;
275   screen_y = y - (SCR_FIELDY - 1) * TILEY;
276
277   animscreen();
278   blitplayer(&ply1);
279   blitplayer(&ply2);
280   blitscreen();
281
282   XFlush(display);
283 }
284
285 #endif