1 // ----------------------------------------------------------------------------
3 // ----------------------------------------------------------------------------
5 #include "DDScrollBuffer.h"
10 int mScrollX, mScrollY;
11 int mScrollX_last, mScrollY_last;
13 int ScreenBuffer[2 + MAX_PLAYFIELD_WIDTH + 2][2 + MAX_PLAYFIELD_HEIGHT + 2];
16 void RestorePlayfield()
18 int x1 = mScrollX / TILEX - 2;
19 int y1 = mScrollY / TILEY - 2;
20 int x2 = mScrollX / TILEX + (SCR_FIELDX - 1) + 2;
21 int y2 = mScrollY / TILEY + (SCR_FIELDY - 1) + 2;
26 for (y = DisplayMinY; y <= DisplayMaxY; y++)
28 for (x = DisplayMinX; x <= DisplayMaxX; x++)
30 if (x >= x1 && x <= x2 && y >= y1 && y <= y2)
32 DrawFieldNoAnimated(x, y);
33 DrawFieldAnimated(x, y);
39 static void ScrollPlayfield(int dx, int dy)
41 int x1 = mScrollX_last / TILEX - 2;
42 int y1 = mScrollY_last / TILEY - 2;
43 int x2 = mScrollX_last / TILEX + (SCR_FIELDX - 1) + 2;
44 int y2 = mScrollY_last / TILEY + (SCR_FIELDY - 1) + 2;
47 BlitBitmap(bitmap_db_field_sp, bitmap_db_field_sp,
48 TILEX_VAR * (dx == -1),
49 TILEY_VAR * (dy == -1),
50 (MAX_BUF_XSIZE * TILEX_VAR) - TILEX_VAR * (dx != 0),
51 (MAX_BUF_YSIZE * TILEY_VAR) - TILEY_VAR * (dy != 0),
52 TILEX_VAR * (dx == 1),
53 TILEY_VAR * (dy == 1));
57 for (y = DisplayMinY; y <= DisplayMaxY; y++)
59 for (x = DisplayMinX; x <= DisplayMaxX; x++)
61 if (x >= x1 && x <= x2 && y >= y1 && y <= y2)
65 int tsi = GetSI(x, y);
66 int id = ((PlayField16[tsi]) |
67 (PlayField8[tsi] << 16) |
68 (DisPlayField[tsi] << 24));
70 if ((dx == -1 && x == x2) ||
71 (dx == +1 && x == x1) ||
72 (dy == -1 && y == y2) ||
73 (dy == +1 && y == y1))
75 DrawFieldNoAnimated(x, y);
76 DrawFieldAnimated(x, y);
79 ScreenBuffer[sx][sy] = id;
85 static void ScrollPlayfieldIfNeededExt(boolean reset)
95 if (mScrollX_last == -1 || mScrollY_last == -1)
97 mScrollX_last = (mScrollX / TILESIZE) * TILESIZE;
98 mScrollY_last = (mScrollY / TILESIZE) * TILESIZE;
103 /* check if scrolling the playfield requires redrawing the viewport bitmap */
104 if ((mScrollX != mScrollX_last ||
105 mScrollY != mScrollY_last) &&
106 (ABS(mScrollX - mScrollX_last) >= TILEX ||
107 ABS(mScrollY - mScrollY_last) >= TILEY))
109 int dx = (ABS(mScrollX - mScrollX_last) < TILEX ? 0 :
110 mScrollX < mScrollX_last ? 1 : mScrollX > mScrollX_last ? -1 : 0);
111 int dy = (ABS(mScrollY - mScrollY_last) < TILEY ? 0 :
112 mScrollY < mScrollY_last ? 1 : mScrollY > mScrollY_last ? -1 : 0);
114 mScrollX_last -= dx * TILEX;
115 mScrollY_last -= dy * TILEY;
117 ScrollPlayfield(dx, dy);
121 static void ScrollPlayfieldIfNeeded()
123 ScrollPlayfieldIfNeededExt(FALSE);
126 void InitScrollPlayfield()
128 ScrollPlayfieldIfNeededExt(TRUE);
131 #define DEBUG_REDRAW 0
133 void UpdatePlayfield(boolean force_redraw)
141 for (y = DisplayMinY; y <= DisplayMaxY; y++)
143 for (x = DisplayMinX; x <= DisplayMaxX; x++)
145 int element = LowByte(PlayField16[GetSI(x, y)]);
146 int graphic = GfxGraphic[x][y];
147 int sync_frame = GfxFrame[x][y];
148 boolean redraw = force_redraw;
152 GfxGraphicLast[x][y] = GfxGraphic[x][y];
157 if (element != GfxElementLast[x][y] &&
158 graphic == GfxGraphicLast[x][y])
160 /* element changed, but not graphic => disable updating graphic */
162 GfxElementLast[x][y] = element;
163 GfxGraphicLast[x][y] = GfxGraphic[x][y] = -1;
168 if (graphic != GfxGraphicLast[x][y]) // new graphic
172 GfxElementLast[x][y] = element;
173 GfxGraphicLast[x][y] = GfxGraphic[x][y];
174 sync_frame = GfxFrame[x][y] = 0;
176 else if (isNextAnimationFrame_SP(graphic, sync_frame)) // new frame
183 int sx = x * StretchWidth;
184 int sy = y * StretchWidth;
186 DDSpriteBuffer_BltImg(sx, sy, graphic, sync_frame);
196 printf("::: FRAME %d: %d redrawn\n", FrameCounter, num_redrawn);
200 void BlitScreenToBitmap_SP(Bitmap *target_bitmap)
202 /* copy playfield buffer to target bitmap at scroll position */
204 int px = 2 * TILEX + (mScrollX - mScrollX_last) % TILEX;
205 int py = 2 * TILEY + (mScrollY - mScrollY_last) % TILEY;
206 int sx, sy, sxsize, sysize;
209 int full_xsize = (FieldWidth - (menBorder ? 0 : 1)) * TILEX_VAR;
210 int full_ysize = (FieldHeight - (menBorder ? 0 : 1)) * TILEY_VAR;
212 sxsize = (full_xsize < xsize ? full_xsize : xsize);
213 sysize = (full_ysize < ysize ? full_ysize : ysize);
214 sx = SX + (full_xsize < xsize ? (xsize - full_xsize) / 2 : 0);
215 sy = SY + (full_ysize < ysize ? (ysize - full_ysize) / 2 : 0);
217 /* scroll correction for even number of visible tiles (half tile shifted) */
218 px += game_sp.scroll_xoffset;
219 py += game_sp.scroll_yoffset;
221 if (ExplosionShakeMurphy != 0)
223 px += TILEX / 2 - GetSimpleRandom(TILEX + 1);
224 py += TILEY / 2 - GetSimpleRandom(TILEX + 1);
227 px = px * TILESIZE_VAR / TILESIZE;
228 py = py * TILESIZE_VAR / TILESIZE;
230 BlitBitmap(bitmap_db_field_sp, target_bitmap, px, py, sxsize, sysize, sx, sy);
233 void DDScrollBuffer_ScrollTo(int X, int Y)
238 ScrollX = mScrollX = X;
239 ScrollY = mScrollY = Y;
241 ScrollPlayfieldIfNeeded();
244 void DDScrollBuffer_ScrollTowards(int X, int Y, double Step)
254 r = Sqr(dx * dx + dY * dY);
255 if (r == 0) // we are there already
263 ScrollX = mScrollX = mScrollX + dx * r;
264 ScrollY = mScrollY = mScrollY + dY * r;
266 ScrollPlayfieldIfNeeded();
269 void DDScrollBuffer_SoftScrollTo(int X, int Y, int TimeMS, int FPS)
274 int oldX, oldY, maxD;
275 static boolean AlreadyRunning = False;
283 AlreadyRunning = True;
287 maxD = (Abs(dx) < Abs(dY) ? Abs(dY) : Abs(dx));
289 StepCount = FPS * (TimeMS / (double)1000);
290 if (StepCount > maxD)
296 tStep = (double)1 / StepCount;
300 for (T = (double)tStep; T <= (double)1; T += tStep)
302 ScrollX = mScrollX = oldX + T * dx;
303 ScrollY = mScrollY = oldY + T * dY;
306 ScrollX = mScrollX = X;
307 ScrollY = mScrollY = Y;
309 AlreadyRunning = False;
311 ScrollPlayfieldIfNeeded();