1 /* 2000-08-13T14:36:17Z
3 * graphics manipulation crap
8 #define MIN_SCREEN_XPOS_RAW 0
9 #define MIN_SCREEN_YPOS_RAW 0
10 #define MAX_SCREEN_XPOS_RAW MAX(0, lev.width - SCR_FIELDX)
11 #define MAX_SCREEN_YPOS_RAW MAX(0, lev.height - SCR_FIELDY)
13 #define MIN_SCREEN_XPOS (MIN_SCREEN_XPOS_RAW + CAVE_BUFFER_XOFFSET)
14 #define MIN_SCREEN_YPOS (MIN_SCREEN_YPOS_RAW + CAVE_BUFFER_YOFFSET)
15 #define MAX_SCREEN_XPOS (MAX_SCREEN_XPOS_RAW + CAVE_BUFFER_XOFFSET)
16 #define MAX_SCREEN_YPOS (MAX_SCREEN_YPOS_RAW + CAVE_BUFFER_YOFFSET)
18 #define MIN_SCREEN_X (MIN_SCREEN_XPOS * TILEX)
19 #define MIN_SCREEN_Y (MIN_SCREEN_YPOS * TILEY)
20 #define MAX_SCREEN_X (MAX_SCREEN_XPOS * TILEX)
21 #define MAX_SCREEN_Y (MAX_SCREEN_YPOS * TILEY)
23 #define VALID_SCREEN_X(x) ((x) < MIN_SCREEN_X ? MIN_SCREEN_X : \
24 (x) > MAX_SCREEN_X ? MAX_SCREEN_X : (x))
25 #define VALID_SCREEN_Y(y) ((y) < MIN_SCREEN_Y ? MIN_SCREEN_Y : \
26 (y) > MAX_SCREEN_Y ? MAX_SCREEN_Y : (y))
28 #define PLAYER_SCREEN_X(p) ((( frame) * ply[p].oldx + \
29 (8 - frame) * ply[p].x) * TILEX / 8 \
30 - ((SCR_FIELDX - 1) * TILEX) / 2)
31 #define PLAYER_SCREEN_Y(p) ((( frame) * ply[p].oldy + \
32 (8 - frame) * ply[p].y) * TILEY / 8 \
33 - ((SCR_FIELDY - 1) * TILEY) / 2)
35 #define USE_EXTENDED_GRAPHICS_ENGINE 1
38 int frame; /* current screen frame */
39 int screen_x, screen_y; /* current scroll position */
41 /* tiles currently on screen */
42 static int screentiles[MAX_PLAYFIELD_WIDTH + 2][MAX_PLAYFIELD_HEIGHT + 2];
43 static int crumbled_state[MAX_PLAYFIELD_WIDTH + 2][MAX_PLAYFIELD_HEIGHT + 2];
45 /* graphic info for game objects/frames and players/actions/frames */
46 struct GraphicInfo_EM graphic_info_em_object[TILE_MAX][8];
47 struct GraphicInfo_EM graphic_info_em_player[MAX_PLAYERS][PLY_MAX][8];
49 int getFieldbufferOffsetX_EM(void)
51 return screen_x % TILEX;
54 int getFieldbufferOffsetY_EM(void)
56 return screen_y % TILEY;
59 void BlitScreenToBitmap_EM(Bitmap *target_bitmap)
61 /* blit all (up to four) parts of the scroll buffer to the target bitmap */
63 int x = screen_x % (MAX_BUF_XSIZE * TILEX);
64 int y = screen_y % (MAX_BUF_YSIZE * TILEY);
67 int full_xsize = lev.width * TILEX;
68 int full_ysize = lev.height * TILEY;
69 int sx = SX + (full_xsize < xsize ? (xsize - full_xsize) / 2 : 0);
70 int sy = SY + (full_ysize < ysize ? (ysize - full_ysize) / 2 : 0);
71 int sxsize = (full_xsize < xsize ? full_xsize : xsize);
72 int sysize = (full_ysize < ysize ? full_ysize : ysize);
74 if (x < 2 * TILEX && y < 2 * TILEY)
76 BlitBitmap(screenBitmap, target_bitmap, x, y,
77 sxsize, sysize, sx, sy);
79 else if (x < 2 * TILEX && y >= 2 * TILEY)
81 BlitBitmap(screenBitmap, target_bitmap, x, y,
82 sxsize, MAX_BUF_YSIZE * TILEY - y,
84 BlitBitmap(screenBitmap, target_bitmap, x, 0,
85 sxsize, y - 2 * TILEY,
86 sx, sy + MAX_BUF_YSIZE * TILEY - y);
88 else if (x >= 2 * TILEX && y < 2 * TILEY)
90 BlitBitmap(screenBitmap, target_bitmap, x, y,
91 MAX_BUF_XSIZE * TILEX - x, sysize,
93 BlitBitmap(screenBitmap, target_bitmap, 0, y,
94 x - 2 * TILEX, sysize,
95 sx + MAX_BUF_XSIZE * TILEX - x, sy);
99 BlitBitmap(screenBitmap, target_bitmap, x, y,
100 MAX_BUF_XSIZE * TILEX - x, MAX_BUF_YSIZE * TILEY - y,
102 BlitBitmap(screenBitmap, target_bitmap, 0, y,
103 x - 2 * TILEX, MAX_BUF_YSIZE * TILEY - y,
104 sx + MAX_BUF_XSIZE * TILEX - x, sy);
105 BlitBitmap(screenBitmap, target_bitmap, x, 0,
106 MAX_BUF_XSIZE * TILEX - x, y - 2 * TILEY,
107 sx, sy + MAX_BUF_YSIZE * TILEY - y);
108 BlitBitmap(screenBitmap, target_bitmap, 0, 0,
109 x - 2 * TILEX, y - 2 * TILEY,
110 sx + MAX_BUF_XSIZE * TILEX - x, sy + MAX_BUF_YSIZE * TILEY - y);
114 static void BackToFront_EM(void)
116 BlitBitmap(backbuffer, window, SX, SY, SXSIZE, SYSIZE, SX, SY);
119 static struct GraphicInfo_EM *getObjectGraphic(int x, int y)
121 int tile = lev.draw[x][y];
122 struct GraphicInfo_EM *g = &graphic_info_em_object[tile][frame];
124 if (!game.use_native_emc_graphics_engine)
125 getGraphicSourceObjectExt_EM(g, tile, 7 - frame, x - lev.left, y - lev.top);
130 static struct GraphicInfo_EM *getPlayerGraphic(int player_nr, int anim)
132 struct GraphicInfo_EM *g = &graphic_info_em_player[player_nr][anim][frame];
134 if (!game.use_native_emc_graphics_engine)
135 getGraphicSourcePlayerExt_EM(g, player_nr, anim, 7 - frame);
140 static void DrawLevelField_EM(int x, int y, int sx, int sy,
143 struct GraphicInfo_EM *g = getObjectGraphic(x, y);
144 int src_x = g->src_x + g->src_offset_x * TILESIZE_VAR / TILESIZE;
145 int src_y = g->src_y + g->src_offset_y * TILESIZE_VAR / TILESIZE;
146 int dst_x = sx * TILEX + g->dst_offset_x * TILESIZE_VAR / TILESIZE;
147 int dst_y = sy * TILEY + g->dst_offset_y * TILESIZE_VAR / TILESIZE;
148 int width = g->width * TILESIZE_VAR / TILESIZE;
149 int height = g->height * TILESIZE_VAR / TILESIZE;
150 int left = screen_x / TILEX;
151 int top = screen_y / TILEY;
153 /* do not draw fields that are outside the visible screen area */
154 if (x < left || x >= left + MAX_BUF_XSIZE ||
155 y < top || y >= top + MAX_BUF_YSIZE)
160 if (width > 0 && height > 0)
161 BlitBitmapMasked(g->bitmap, screenBitmap,
162 src_x, src_y, width, height, dst_x, dst_y);
166 if ((width != TILEX || height != TILEY) && !g->preserve_background)
167 ClearRectangle(screenBitmap, sx * TILEX, sy * TILEY, TILEX, TILEY);
169 if (width > 0 && height > 0)
170 BlitBitmap(g->bitmap, screenBitmap,
171 src_x, src_y, width, height, dst_x, dst_y);
175 static void DrawLevelFieldCrumbled_EM(int x, int y, int sx, int sy,
176 int crm, boolean draw_masked)
178 struct GraphicInfo_EM *g;
179 int crumbled_border_size;
180 int left = screen_x / TILEX;
181 int top = screen_y / TILEY;
184 /* do not draw fields that are outside the visible screen area */
185 if (x < left || x >= left + MAX_BUF_XSIZE ||
186 y < top || y >= top + MAX_BUF_YSIZE)
189 if (crm == 0) /* no crumbled edges for this tile */
192 g = getObjectGraphic(x, y);
194 crumbled_border_size =
195 g->crumbled_border_size * TILESIZE_VAR / g->crumbled_tile_size;
197 for (i = 0; i < 4; i++)
201 int width, height, cx, cy;
203 if (i == 1 || i == 2)
205 width = crumbled_border_size;
207 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
213 height = crumbled_border_size;
215 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
218 if (width > 0 && height > 0)
220 int src_x = g->crumbled_src_x + cx;
221 int src_y = g->crumbled_src_y + cy;
222 int dst_x = sx * TILEX + cx;
223 int dst_y = sy * TILEY + cy;
226 BlitBitmapMasked(g->crumbled_bitmap, screenBitmap,
227 src_x, src_y, width, height, dst_x, dst_y);
229 BlitBitmap(g->crumbled_bitmap, screenBitmap,
230 src_x, src_y, width, height, dst_x, dst_y);
236 static void DrawLevelPlayer_EM(int x1, int y1, int player_nr, int anim,
239 struct GraphicInfo_EM *g = getPlayerGraphic(player_nr, anim);
240 int src_x = g->src_x, src_y = g->src_y;
243 /* do not draw fields that are outside the visible screen area */
244 if (x1 < screen_x - TILEX || x1 >= screen_x + MAX_BUF_XSIZE * TILEX ||
245 y1 < screen_y - TILEY || y1 >= screen_y + MAX_BUF_YSIZE * TILEY)
248 x1 %= MAX_BUF_XSIZE * TILEX;
249 y1 %= MAX_BUF_YSIZE * TILEY;
253 /* draw the player to current location */
256 BlitBitmapMasked(g->bitmap, screenBitmap,
257 src_x, src_y, TILEX, TILEY, dst_x, dst_y);
259 /* draw the player to opposite wrap-around column */
260 dst_x = x1 - MAX_BUF_XSIZE * TILEX;
262 BlitBitmapMasked(g->bitmap, screenBitmap,
263 g->src_x, g->src_y, TILEX, TILEY, dst_x, dst_y);
265 /* draw the player to opposite wrap-around row */
267 dst_y = y1 - MAX_BUF_YSIZE * TILEY;
268 BlitBitmapMasked(g->bitmap, screenBitmap,
269 g->src_x, g->src_y, TILEX, TILEY, dst_x, dst_y);
273 /* draw the player to current location */
276 BlitBitmap(g->bitmap, screenBitmap,
277 g->src_x, g->src_y, TILEX, TILEY, dst_x, dst_y);
279 /* draw the player to opposite wrap-around column */
280 dst_x = x1 - MAX_BUF_XSIZE * TILEX;
282 BlitBitmap(g->bitmap, screenBitmap,
283 g->src_x, g->src_y, TILEX, TILEY, dst_x, dst_y);
285 /* draw the player to opposite wrap-around row */
287 dst_y = y1 - MAX_BUF_YSIZE * TILEY;
288 BlitBitmap(g->bitmap, screenBitmap,
289 g->src_x, g->src_y, TILEX, TILEY, dst_x, dst_y);
293 /* draw differences between game tiles and screen tiles
295 * implicitly handles scrolling and restoring background under the sprites
298 static void animscreen(void)
301 int left = screen_x / TILEX;
302 int top = screen_y / TILEY;
303 static int xy[4][2] =
311 if (!game.use_native_emc_graphics_engine)
312 for (y = lev.top; y < lev.bottom; y++)
313 for (x = lev.left; x < lev.right; x++)
314 SetGfxAnimation_EM(&graphic_info_em_object[lev.draw[x][y]][frame],
315 lev.draw[x][y], 7 - frame,
316 x - lev.left, y - lev.top);
318 for (y = top; y < top + MAX_BUF_YSIZE; y++)
320 for (x = left; x < left + MAX_BUF_XSIZE; x++)
322 int sx = x % MAX_BUF_XSIZE;
323 int sy = y % MAX_BUF_YSIZE;
324 int tile = lev.draw[x][y];
325 struct GraphicInfo_EM *g = &graphic_info_em_object[tile][frame];
326 int obj = g->unique_identifier;
328 boolean redraw_screen_tile = FALSE;
330 /* re-calculate crumbled state of this tile */
331 if (g->has_crumbled_graphics)
333 for (i = 0; i < 4; i++)
335 int xx = x + xy[i][0];
336 int yy = y + xy[i][1];
339 if (xx < 0 || xx >= CAVE_BUFFER_WIDTH ||
340 yy < 0 || yy >= CAVE_BUFFER_HEIGHT)
343 tile_next = lev.draw[xx][yy];
345 if (!graphic_info_em_object[tile_next][frame].has_crumbled_graphics)
350 redraw_screen_tile = (screentiles[sx][sy] != obj ||
351 crumbled_state[sx][sy] != crm);
353 /* only redraw screen tiles if they (or their crumbled state) changed */
354 if (redraw_screen_tile)
356 DrawLevelField_EM(x, y, sx, sy, FALSE);
357 DrawLevelFieldCrumbled_EM(x, y, sx, sy, crm, FALSE);
359 screentiles[sx][sy] = obj;
360 crumbled_state[sx][sy] = crm;
367 /* blit players to the screen
369 * handles transparency and movement
372 static void blitplayer(struct PLAYER *ply)
379 /* x1/y1 are left/top and x2/y2 are right/down part of the player movement */
380 x1 = (frame * ply->oldx + (8 - frame) * ply->x) * TILEX / 8;
381 y1 = (frame * ply->oldy + (8 - frame) * ply->y) * TILEY / 8;
385 if ((int)(x2 - screen_x) < ((MAX_BUF_XSIZE - 1) * TILEX - 1) &&
386 (int)(y2 - screen_y) < ((MAX_BUF_YSIZE - 1) * TILEY - 1))
388 /* some casts to "int" are needed because of negative calculation values */
389 int dx = (int)ply->x - (int)ply->oldx;
390 int dy = (int)ply->y - (int)ply->oldy;
391 int old_x = (int)ply->oldx + (7 - (int)frame) * dx / 8;
392 int old_y = (int)ply->oldy + (7 - (int)frame) * dy / 8;
393 int new_x = old_x + SIGN(dx);
394 int new_y = old_y + SIGN(dy);
395 int old_sx = old_x % MAX_BUF_XSIZE;
396 int old_sy = old_y % MAX_BUF_YSIZE;
397 int new_sx = new_x % MAX_BUF_XSIZE;
398 int new_sy = new_y % MAX_BUF_YSIZE;
399 int new_crm = crumbled_state[new_sx][new_sy];
401 /* only diggable elements can be crumbled in the classic EM engine */
402 boolean player_is_digging = (new_crm != 0);
404 if (player_is_digging)
406 /* draw the field the player is moving to (under the player) */
407 DrawLevelField_EM(new_x, new_y, new_sx, new_sy, FALSE);
408 DrawLevelFieldCrumbled_EM(new_x, new_y, new_sx, new_sy, new_crm, FALSE);
410 /* draw the player (masked) over the element he is just digging away */
411 DrawLevelPlayer_EM(x1, y1, ply->num, ply->anim, TRUE);
413 /* draw the field the player is moving from (masked over the player) */
414 DrawLevelField_EM(old_x, old_y, old_sx, old_sy, TRUE);
418 /* draw the player under the element which is on the same field */
419 DrawLevelPlayer_EM(x1, y1, ply->num, ply->anim, FALSE);
421 /* draw the field the player is moving from (masked over the player) */
422 DrawLevelField_EM(old_x, old_y, old_sx, old_sy, TRUE);
424 /* draw the field the player is moving to (masked over the player) */
425 DrawLevelField_EM(new_x, new_y, new_sx, new_sy, TRUE);
428 /* redraw screen tiles in the next frame (player may have left the tiles) */
429 screentiles[old_sx][old_sy] = -1;
430 screentiles[new_sx][new_sy] = -1;
434 void game_initscreen(void)
441 player_nr = (game.centered_player_nr != -1 ? game.centered_player_nr : 0);
443 screen_x = VALID_SCREEN_X(PLAYER_SCREEN_X(player_nr));
444 screen_y = VALID_SCREEN_Y(PLAYER_SCREEN_Y(player_nr));
446 for (y = 0; y < MAX_BUF_YSIZE; y++)
448 for (x = 0; x < MAX_BUF_XSIZE; x++)
450 screentiles[x][y] = -1;
451 crumbled_state[x][y] = 0;
456 static int getMaxCenterDistancePlayerNr(int center_x, int center_y)
458 int max_dx = 0, max_dy = 0;
459 int player_nr = game_em.last_moving_player;
462 for (i = 0; i < MAX_PLAYERS; i++)
466 int sx = PLAYER_SCREEN_X(i);
467 int sy = PLAYER_SCREEN_Y(i);
469 if (game_em.last_player_direction[i] != MV_NONE &&
470 (ABS(sx - center_x) > max_dx ||
471 ABS(sy - center_y) > max_dy))
473 max_dx = MAX(max_dx, ABS(sx - center_x));
474 max_dy = MAX(max_dy, ABS(sy - center_y));
484 static void setMinimalPlayerBoundaries(int *sx1, int *sy1, int *sx2, int *sy2)
486 boolean num_checked_players = 0;
489 for (i = 0; i < MAX_PLAYERS; i++)
493 int sx = PLAYER_SCREEN_X(i);
494 int sy = PLAYER_SCREEN_Y(i);
496 if (num_checked_players == 0)
503 *sx1 = MIN(*sx1, sx);
504 *sy1 = MIN(*sy1, sy);
505 *sx2 = MAX(*sx2, sx);
506 *sy2 = MAX(*sy2, sy);
509 num_checked_players++;
514 boolean checkIfAllPlayersFitToScreen(void)
516 int sx1 = 0, sy1 = 0, sx2 = 0, sy2 = 0;
518 setMinimalPlayerBoundaries(&sx1, &sy1, &sx2, &sy2);
520 return (sx2 - sx1 <= SCR_FIELDX * TILEX &&
521 sy2 - sy1 <= SCR_FIELDY * TILEY);
524 static void setScreenCenteredToAllPlayers(int *sx, int *sy)
526 int sx1 = screen_x, sy1 = screen_y, sx2 = screen_x, sy2 = screen_y;
528 setMinimalPlayerBoundaries(&sx1, &sy1, &sx2, &sy2);
530 *sx = (sx1 + sx2) / 2;
531 *sy = (sy1 + sy2) / 2;
534 static void setMaxCenterDistanceForAllPlayers(int *max_dx, int *max_dy,
535 int center_x, int center_y)
537 int sx1 = center_x, sy1 = center_y, sx2 = center_x, sy2 = center_y;
539 setMinimalPlayerBoundaries(&sx1, &sy1, &sx2, &sy2);
541 *max_dx = MAX(ABS(sx1 - center_x), ABS(sx2 - center_x));
542 *max_dy = MAX(ABS(sy1 - center_y), ABS(sy2 - center_y));
545 static boolean checkIfAllPlayersAreVisible(int center_x, int center_y)
549 setMaxCenterDistanceForAllPlayers(&max_dx, &max_dy, center_x, center_y);
551 return (max_dx <= SCR_FIELDX * TILEX / 2 &&
552 max_dy <= SCR_FIELDY * TILEY / 2);
555 void RedrawPlayfield_EM(boolean force_redraw)
557 boolean draw_new_player_location = FALSE;
558 boolean draw_new_player_location_fast = FALSE;
559 boolean quick_relocation = setup.quick_switch;
560 int max_center_distance_player_nr =
561 getMaxCenterDistancePlayerNr(screen_x, screen_y);
562 int stepsize = TILEX / 8;
563 int offset_raw = game.scroll_delay_value;
564 int offset_x = MIN(offset_raw, (SCR_FIELDX - 2) / 2) * TILEX;
565 int offset_y = MIN(offset_raw, (SCR_FIELDY - 2) / 2) * TILEY;
566 int screen_x_old = screen_x;
567 int screen_y_old = screen_y;
571 if (game.set_centered_player)
573 boolean all_players_fit_to_screen = checkIfAllPlayersFitToScreen();
575 /* switching to "all players" only possible if all players fit to screen */
576 if (game.centered_player_nr_next == -1 && !all_players_fit_to_screen)
578 game.centered_player_nr_next = game.centered_player_nr;
579 game.set_centered_player = FALSE;
582 /* do not switch focus to non-existing (or non-active) player */
583 if (game.centered_player_nr_next >= 0 &&
584 !ply[game.centered_player_nr_next].alive)
586 game.centered_player_nr_next = game.centered_player_nr;
587 game.set_centered_player = FALSE;
591 /* also allow focus switching when screen is scrolled to half tile */
592 if (game.set_centered_player)
594 game.centered_player_nr = game.centered_player_nr_next;
596 draw_new_player_location = TRUE;
597 draw_new_player_location_fast = game.set_centered_player_fast;
600 game.set_centered_player = FALSE;
601 game.set_centered_player_fast = FALSE;
604 if (game.centered_player_nr == -1)
606 if (draw_new_player_location || offset_raw == 0)
608 setScreenCenteredToAllPlayers(&sx, &sy);
612 sx = PLAYER_SCREEN_X(max_center_distance_player_nr);
613 sy = PLAYER_SCREEN_Y(max_center_distance_player_nr);
618 sx = PLAYER_SCREEN_X(game.centered_player_nr);
619 sy = PLAYER_SCREEN_Y(game.centered_player_nr);
622 if (draw_new_player_location && quick_relocation)
624 screen_x = VALID_SCREEN_X(sx);
625 screen_y = VALID_SCREEN_Y(sy);
626 screen_x_old = screen_x;
627 screen_y_old = screen_y;
630 if (draw_new_player_location && !quick_relocation)
632 unsigned int frame_delay_value_old = GetVideoFrameDelay();
633 int wait_delay_value = frame_delay_value_old;
634 int screen_xx = VALID_SCREEN_X(sx);
635 int screen_yy = VALID_SCREEN_Y(sy);
637 if (draw_new_player_location_fast)
638 wait_delay_value /= 4;
640 SetVideoFrameDelay(wait_delay_value);
642 while (screen_x != screen_xx || screen_y != screen_yy)
644 int dx = (screen_xx < screen_x ? +1 : screen_xx > screen_x ? -1 : 0);
645 int dy = (screen_yy < screen_y ? +1 : screen_yy > screen_y ? -1 : 0);
646 int dxx = 0, dyy = 0;
648 if (dx == 0 && dy == 0) /* no scrolling needed at all */
651 if (ABS(screen_xx - screen_x) >= TILEX)
653 screen_x -= dx * TILEX;
654 dxx = dx * TILEX / 2;
658 screen_x = screen_xx;
662 if (ABS(screen_yy - screen_y) >= TILEY)
664 screen_y -= dy * TILEY;
665 dyy = dy * TILEY / 2;
669 screen_y = screen_yy;
673 /* scroll in two steps of half tile size to make things smoother */
679 for (i = 0; i < MAX_PLAYERS; i++)
682 BlitScreenToBitmap_EM(backbuffer);
685 /* scroll second step to align at full tile size */
691 for (i = 0; i < MAX_PLAYERS; i++)
694 BlitScreenToBitmap_EM(backbuffer);
698 SetVideoFrameDelay(frame_delay_value_old);
700 screen_x_old = screen_x;
701 screen_y_old = screen_y;
706 for (y = 0; y < MAX_BUF_YSIZE; y++)
708 for (x = 0; x < MAX_BUF_XSIZE; x++)
710 screentiles[x][y] = -1;
711 crumbled_state[x][y] = 0;
716 /* calculate new screen scrolling position, with regard to scroll delay */
717 screen_x = VALID_SCREEN_X(sx + offset_x < screen_x ? sx + offset_x :
718 sx - offset_x > screen_x ? sx - offset_x :
720 screen_y = VALID_SCREEN_Y(sy + offset_y < screen_y ? sy + offset_y :
721 sy - offset_y > screen_y ? sy - offset_y :
724 /* prevent scrolling further than double player step size when scrolling */
725 if (ABS(screen_x - screen_x_old) > 2 * stepsize)
727 int dx = SIGN(screen_x - screen_x_old);
729 screen_x = screen_x_old + dx * 2 * stepsize;
731 if (ABS(screen_y - screen_y_old) > 2 * stepsize)
733 int dy = SIGN(screen_y - screen_y_old);
735 screen_y = screen_y_old + dy * 2 * stepsize;
738 /* prevent scrolling away from the other players when focus on all players */
739 if (game.centered_player_nr == -1)
741 /* check if all players are still visible with new scrolling position */
742 if (checkIfAllPlayersAreVisible(screen_x_old, screen_y_old) &&
743 !checkIfAllPlayersAreVisible(screen_x, screen_y))
745 /* reset horizontal scroll position to last value, if needed */
746 if (!checkIfAllPlayersAreVisible(screen_x, screen_y_old))
747 screen_x = screen_x_old;
749 /* reset vertical scroll position to last value, if needed */
750 if (!checkIfAllPlayersAreVisible(screen_x_old, screen_y))
751 screen_y = screen_y_old;
755 /* prevent scrolling (for screen correcting) if no player is moving */
756 if (!game_em.any_player_moving)
758 screen_x = screen_x_old;
759 screen_y = screen_y_old;
763 /* prevent scrolling against the players move direction */
764 int player_nr = (game.centered_player_nr == -1 ?
765 max_center_distance_player_nr : game.centered_player_nr);
766 int player_move_dir = game_em.last_player_direction[player_nr];
767 int dx = SIGN(screen_x - screen_x_old);
768 int dy = SIGN(screen_y - screen_y_old);
770 if ((dx < 0 && player_move_dir != MV_LEFT) ||
771 (dx > 0 && player_move_dir != MV_RIGHT))
772 screen_x = screen_x_old;
774 if ((dy < 0 && player_move_dir != MV_UP) ||
775 (dy > 0 && player_move_dir != MV_DOWN))
776 screen_y = screen_y_old;
779 // skip redrawing playfield in warp mode or when testing tapes with "autotest"
780 if (DrawingDeactivatedField())
785 for (i = 0; i < MAX_PLAYERS; i++)