1 /* 2000-08-13T14:36:17Z
3 * graphics manipulation crap
11 unsigned int frame; /* current screen frame */
12 unsigned int screen_x; /* current scroll position */
13 unsigned int screen_y;
15 /* tiles currently on screen */
16 static unsigned int screentiles[MAX_BUF_YSIZE][MAX_BUF_XSIZE];
17 static unsigned int crumbled_state[MAX_BUF_YSIZE][MAX_BUF_XSIZE];
20 /* copy the entire screen to the window at the scroll position
22 * perhaps use mit-shm to speed this up
27 unsigned int x = screen_x % (MAX_BUF_XSIZE * TILEX);
28 unsigned int y = screen_y % (MAX_BUF_YSIZE * TILEY);
30 if (x < 2 * TILEX && y < 2 * TILEY)
32 BlitBitmap(screenBitmap, window, x, y,
33 SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
35 else if (x < 2 * TILEX && y >= 2 * TILEY)
37 BlitBitmap(screenBitmap, window, x, y,
38 SCR_FIELDX * TILEX, MAX_BUF_YSIZE * TILEY - y,
40 BlitBitmap(screenBitmap, window, x, 0,
41 SCR_FIELDX * TILEX, y - 2 * TILEY,
42 SX, SY + MAX_BUF_YSIZE * TILEY - y);
44 else if (x >= 2 * TILEX && y < 2 * TILEY)
46 BlitBitmap(screenBitmap, window, x, y,
47 MAX_BUF_XSIZE * TILEX - x, SCR_FIELDY * TILEY,
49 BlitBitmap(screenBitmap, window, 0, y,
50 x - 2 * TILEX, SCR_FIELDY * TILEY,
51 SX + MAX_BUF_XSIZE * TILEX - x, SY);
55 BlitBitmap(screenBitmap, window, x, y,
56 MAX_BUF_XSIZE * TILEX - x, MAX_BUF_YSIZE * TILEY - y,
58 BlitBitmap(screenBitmap, window, 0, y,
59 x - 2 * TILEX, MAX_BUF_YSIZE * TILEY - y,
60 SX + MAX_BUF_XSIZE * TILEX - x, SY);
61 BlitBitmap(screenBitmap, window, x, 0,
62 MAX_BUF_XSIZE * TILEX - x, y - 2 * TILEY,
63 SX, SY + MAX_BUF_YSIZE * TILEY - y);
64 BlitBitmap(screenBitmap, window, 0, 0,
65 x - 2 * TILEX, y - 2 * TILEY,
66 SX + MAX_BUF_XSIZE * TILEX - x, SY + MAX_BUF_YSIZE * TILEY - y);
70 static void DrawLevelField_EM(int x, int y, int sx, int sy,
73 int tile = Draw[y][x];
74 struct GraphicInfo_EM *g = &graphic_info_em_object[tile][frame];
75 int src_x = g->src_x + g->src_offset_x;
76 int src_y = g->src_y + g->src_offset_y;
77 int dst_x = sx * TILEX + g->dst_offset_x;
78 int dst_y = sy * TILEY + g->dst_offset_y;
82 if (g->width > 0 && g->height > 0)
84 SetClipOrigin(g->bitmap, g->bitmap->stored_clip_gc,
85 dst_x - src_x, dst_y - src_y);
86 BlitBitmapMasked(g->bitmap, screenBitmap,
87 src_x, src_y, g->width, g->height, dst_x, dst_y);
92 if (g->width != TILEX || g->height != TILEY)
93 ClearRectangle(screenBitmap, sx * TILEX, sy * TILEY, TILEX, TILEY);
95 if (g->width > 0 && g->height > 0)
96 BlitBitmap(g->bitmap, screenBitmap,
97 src_x, src_y, g->width, g->height, dst_x, dst_y);
101 static void DrawLevelFieldCrumbled_EM(int x, int y, int sx, int sy,
102 int crm, boolean draw_masked)
104 int tile = Draw[y][x];
105 struct GraphicInfo_EM *g = &graphic_info_em_object[tile][frame];
108 if (crm == 0) /* no crumbled edges for this tile */
111 for (i = 0; i < 4; i++)
115 int width, height, cx, cy;
117 if (i == 1 || i == 2)
119 width = g->crumbled_border_size;
121 cx = (i == 2 ? TILEX - g->crumbled_border_size : 0);
127 height = g->crumbled_border_size;
129 cy = (i == 3 ? TILEY - g->crumbled_border_size : 0);
132 if (width > 0 && height > 0)
134 int src_x = g->crumbled_src_x + cx;
135 int src_y = g->crumbled_src_y + cy;
136 int dst_x = sx * TILEX + cx;
137 int dst_y = sy * TILEY + cy;
141 SetClipOrigin(g->crumbled_bitmap, g->crumbled_bitmap->stored_clip_gc,
142 dst_x - src_x, dst_y - src_y);
143 BlitBitmapMasked(g->crumbled_bitmap, screenBitmap,
144 src_x, src_y, width, height, dst_x, dst_y);
147 BlitBitmap(g->crumbled_bitmap, screenBitmap,
148 src_x, src_y, width, height, dst_x, dst_y);
154 static void DrawLevelPlayer_EM(int x1, int y1, int player_nr, int anim,
157 struct GraphicInfo_EM *g = &graphic_info_em_player[player_nr][anim][frame];
159 int src_x = g->src_x, src_y = g->src_y;
164 /* draw the player to current location */
167 SetClipOrigin(g->bitmap, g->bitmap->stored_clip_gc,
168 dst_x - src_x, dst_y - src_y);
169 BlitBitmapMasked(g->bitmap, screenBitmap,
170 src_x, src_y, TILEX, TILEY, dst_x, dst_y);
172 /* draw the player to opposite wrap-around column */
173 dst_x = x1 - MAX_BUF_XSIZE * TILEX;
175 SetClipOrigin(g->bitmap, g->bitmap->stored_clip_gc,
176 dst_x - src_x, dst_y - src_y);
177 BlitBitmapMasked(g->bitmap, screenBitmap,
178 g->src_x, g->src_y, TILEX, TILEY, dst_x, dst_y);
180 /* draw the player to opposite wrap-around row */
182 dst_y = y1 - MAX_BUF_YSIZE * TILEY;
183 SetClipOrigin(g->bitmap, g->bitmap->stored_clip_gc,
184 dst_x - src_x, dst_y - src_y);
185 BlitBitmapMasked(g->bitmap, screenBitmap,
186 g->src_x, g->src_y, TILEX, TILEY, dst_x, dst_y);
190 /* draw the player to current location */
193 BlitBitmap(g->bitmap, screenBitmap,
194 g->src_x, g->src_y, TILEX, TILEY, dst_x, dst_y);
196 /* draw the player to opposite wrap-around column */
197 dst_x = x1 - MAX_BUF_XSIZE * TILEX;
199 BlitBitmap(g->bitmap, screenBitmap,
200 g->src_x, g->src_y, TILEX, TILEY, dst_x, dst_y);
202 /* draw the player to opposite wrap-around row */
204 dst_y = y1 - MAX_BUF_YSIZE * TILEY;
205 BlitBitmap(g->bitmap, screenBitmap,
206 g->src_x, g->src_y, TILEX, TILEY, dst_x, dst_y);
210 /* draw differences between game tiles and screen tiles
212 * implicitly handles scrolling and restoring background under the sprites
214 * perhaps use mit-shm to speed this up
217 static void animscreen(void)
219 unsigned int x, y, i;
220 unsigned int left = screen_x / TILEX;
221 unsigned int top = screen_y / TILEY;
222 static int xy[4][2] =
230 for (y = top; y < top + MAX_BUF_YSIZE; y++)
232 for (x = left; x < left + MAX_BUF_XSIZE; x++)
234 int sx = x % MAX_BUF_XSIZE;
235 int sy = y % MAX_BUF_YSIZE;
236 int tile = Draw[y][x];
237 struct GraphicInfo_EM *g = &graphic_info_em_object[tile][frame];
238 unsigned int obj = g->unique_identifier;
239 unsigned int crm = 0;
241 /* re-calculate crumbled state of this tile */
242 if (g->has_crumbled_graphics)
244 for (i = 0; i < 4; i++)
246 int xx = x + xy[i][0];
247 int yy = y + xy[i][1];
250 if (xx < 0 || xx >= EM_MAX_CAVE_WIDTH ||
251 yy < 0 || yy >= EM_MAX_CAVE_HEIGHT)
254 tile_next = Draw[yy][xx];
256 if (!graphic_info_em_object[tile_next][frame].has_crumbled_graphics)
261 if (screentiles[sy][sx] != obj || crumbled_state[sy][sx] != crm)
263 DrawLevelField_EM(x, y, sx, sy, FALSE);
264 DrawLevelFieldCrumbled_EM(x, y, sx, sy, crm, FALSE);
266 screentiles[sy][sx] = obj;
267 crumbled_state[sy][sx] = crm;
274 /* blit players to the screen
276 * handles transparency and movement
279 static void blitplayer(struct PLAYER *ply)
281 unsigned int x1, y1, x2, y2;
286 /* x1/y1 are left/top and x2/y2 are right/down part of the player movement */
287 x1 = (frame * ply->oldx + (8 - frame) * ply->x) * TILEX / 8;
288 y1 = (frame * ply->oldy + (8 - frame) * ply->y) * TILEY / 8;
292 if ((unsigned int)(x2 - screen_x) < ((MAX_BUF_XSIZE - 1) * TILEX - 1) &&
293 (unsigned int)(y2 - screen_y) < ((MAX_BUF_YSIZE - 1) * TILEY - 1))
295 /* some casts to "int" are needed because of negative calculation values */
296 int dx = (int)ply->x - (int)ply->oldx;
297 int dy = (int)ply->y - (int)ply->oldy;
298 int old_x = (int)ply->oldx + (7 - (int)frame) * dx / 8;
299 int old_y = (int)ply->oldy + (7 - (int)frame) * dy / 8;
300 int new_x = old_x + SIGN(dx);
301 int new_y = old_y + SIGN(dy);
302 int old_sx = old_x % MAX_BUF_XSIZE;
303 int old_sy = old_y % MAX_BUF_XSIZE;
304 int new_sx = new_x % MAX_BUF_XSIZE;
305 int new_sy = new_y % MAX_BUF_XSIZE;
306 int old_crm = crumbled_state[old_sy][old_sx];
307 int new_crm = crumbled_state[new_sy][new_sx];
309 /* only diggable elements can be crumbled in the classic EM engine */
310 boolean player_is_digging = (crumbled_state[new_sy][new_sx] != 0);
312 x1 %= MAX_BUF_XSIZE * TILEX;
313 y1 %= MAX_BUF_YSIZE * TILEY;
314 x2 %= MAX_BUF_XSIZE * TILEX;
315 y2 %= MAX_BUF_YSIZE * TILEY;
317 if (player_is_digging)
319 /* draw the field the player is moving from (under the player) */
320 DrawLevelField_EM(old_x, old_y, old_sx, old_sy, FALSE);
321 DrawLevelFieldCrumbled_EM(old_x, old_y, old_sx, old_sy, old_crm, FALSE);
323 /* draw the field the player is moving to (under the player) */
324 DrawLevelField_EM(new_x, new_y, new_sx, new_sy, FALSE);
325 DrawLevelFieldCrumbled_EM(new_x, new_y, new_sx, new_sy, new_crm, FALSE);
327 /* draw the player (masked) over the element he is just digging away */
328 DrawLevelPlayer_EM(x1, y1, ply->num, ply->anim, TRUE);
332 /* draw the player under the element which is on the same field */
333 DrawLevelPlayer_EM(x1, y1, ply->num, ply->anim, FALSE);
335 /* draw the field the player is moving from (masked over the player) */
336 DrawLevelField_EM(old_x, old_y, old_sx, old_sy, TRUE);
338 /* draw the field the player is moving to (masked over the player) */
339 DrawLevelField_EM(new_x, new_y, new_sx, new_sy, TRUE);
342 /* mark screen tiles as dirty */
343 screentiles[old_sy][old_sx] = -1;
344 screentiles[new_sy][new_sx] = -1;
348 void game_initscreen(void)
356 for (y = 0; y < MAX_BUF_YSIZE; y++)
358 for (x = 0; x < MAX_BUF_XSIZE; x++)
360 screentiles[y][x] = -1;
361 crumbled_state[y][x] = 0;
365 DrawGameDoorValues_EM(lev.required, ply1.dynamite, lev.score,
366 DISPLAY_TIME(lev.time + 4));
369 void game_animscreen(void)
373 x = (frame * ply1.oldx + (8 - frame) * ply1.x) * TILEX / 8
374 + ((SCR_FIELDX - 1) * TILEX) / 2;
375 y = (frame * ply1.oldy + (8 - frame) * ply1.y) * TILEY / 8
376 + ((SCR_FIELDY - 1) * TILEY) / 2;
378 if (x > lev.width * TILEX)
379 x = lev.width * TILEX;
380 if (y > lev.height * TILEY)
381 y = lev.height * TILEY;
383 if (x < SCR_FIELDX * TILEX)
384 x = SCR_FIELDX * TILEY;
385 if (y < SCR_FIELDY * TILEY)
386 y = SCR_FIELDY * TILEY;
388 screen_x = x - (SCR_FIELDX - 1) * TILEX;
389 screen_y = y - (SCR_FIELDY - 1) * TILEY;