X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fgame_sp%2FDDScrollBuffer.c;h=271a6404a8626b0a52815798daa59f87a9250ea6;hp=1734aa8b7ebadc7d91d6d43285efa9892c622e89;hb=14d7691c65ca4a466ce9b9448153e8fbe8351a81;hpb=5ba7f2d9a3f07f342afdf215a3307d5487cb6d43 diff --git a/src/game_sp/DDScrollBuffer.c b/src/game_sp/DDScrollBuffer.c index 1734aa8b..271a6404 100644 --- a/src/game_sp/DDScrollBuffer.c +++ b/src/game_sp/DDScrollBuffer.c @@ -7,275 +7,297 @@ #include -// --- VERSION 1.0 CLASS -// --- BEGIN -// --- MultiUse = -1 'True // True -// --- Persistable = 0 'NotPersistable // NotPersistable -// --- DataBindingBehavior = 0 'vbNone // vbNone -// --- DataSourceBehavior = 0 'vbNone // vbNone -// --- MTSTransactionMode = 0 'NotAnMTSObject // NotAnMTSObject -// --- END - -static char *VB_Name = "DDScrollBuffer"; -static boolean VB_GlobalNameSpace = False; -static boolean VB_Creatable = True; -static boolean VB_PredeclaredId = False; -static boolean VB_Exposed = False; -// --- Option Explicit - -// needs reference to: DirectX7 for Visual Basic Type Library - -DirectDrawSurface7 Buffer; -DirectDrawSurface7 mPrimary; -long mWidth, mHeight; -long mhWnd; -long mScrollX, mScrollY; -long mDestXOff, mDestYOff; - -void DDScrollBuffer_Let_DestXOff(long NewVal) -{ - mDestXOff = NewVal; -} +int mScrollX, mScrollY; +int mScrollX_last, mScrollY_last; + +int ScreenBuffer[2 + MAX_PLAYFIELD_WIDTH + 2][2 + MAX_PLAYFIELD_HEIGHT + 2]; +boolean redraw[2 + MAX_PLAYFIELD_WIDTH + 2][2 + MAX_PLAYFIELD_HEIGHT + 2]; -long DDScrollBuffer_Get_DestXOff() + +void RestorePlayfield() { - long DestXOff; + int x1 = mScrollX / TILEX - 2; + int y1 = mScrollY / TILEY - 2; + int x2 = mScrollX / TILEX + (SCR_FIELDX - 1) + 2; + int y2 = mScrollY / TILEY + (SCR_FIELDY - 1) + 2; + int x, y; - DestXOff = mDestXOff; + DrawFrameIfNeeded(); - return DestXOff; + for (y = DisplayMinY; y <= DisplayMaxY; y++) + { + for (x = DisplayMinX; x <= DisplayMaxX; x++) + { + if (x >= x1 && x <= x2 && y >= y1 && y <= y2) + { + DrawFieldNoAnimated(x, y); + DrawFieldAnimated(x, y); + } + } + } } -void DDScrollBuffer_Let_DestYOff(long NewVal) +static void ScrollPlayfield(int dx, int dy) { - mDestYOff = NewVal; + int x1 = mScrollX_last / TILEX - 2; + int y1 = mScrollY_last / TILEY - 2; + int x2 = mScrollX_last / TILEX + (SCR_FIELDX - 1) + 2; + int y2 = mScrollY_last / TILEY + (SCR_FIELDY - 1) + 2; + int x, y; + + BlitBitmap(bitmap_db_field_sp, bitmap_db_field_sp, + TILEX_VAR * (dx == -1), + TILEY_VAR * (dy == -1), + (MAX_BUF_XSIZE * TILEX_VAR) - TILEX_VAR * (dx != 0), + (MAX_BUF_YSIZE * TILEY_VAR) - TILEY_VAR * (dy != 0), + TILEX_VAR * (dx == 1), + TILEY_VAR * (dy == 1)); + + /* when scrolling the whole playfield, do not redraw single tiles */ + for (x = 0; x < 2 + MAX_PLAYFIELD_WIDTH + 2; x++) + for (y = 0; y < 2 + MAX_PLAYFIELD_HEIGHT + 2; y++) + redraw[x][y] = FALSE; + redraw_tiles = 0; + + DrawFrameIfNeeded(); + + for (y = DisplayMinY; y <= DisplayMaxY; y++) + { + for (x = DisplayMinX; x <= DisplayMaxX; x++) + { + if (x >= x1 && x <= x2 && y >= y1 && y <= y2) + { + int sx = x - x1; + int sy = y - y1; + int tsi = GetSI(x, y); + int id = ((PlayField16[tsi]) | + (PlayField8[tsi] << 16) | + (DisPlayField[tsi] << 24)); + + if ((dx == -1 && x == x2) || + (dx == +1 && x == x1) || + (dy == -1 && y == y2) || + (dy == +1 && y == y1)) + { + DrawFieldNoAnimated(x, y); + DrawFieldAnimated(x, y); + } + + ScreenBuffer[sx][sy] = id; + } + } + } } -long DDScrollBuffer_Get_DestYOff() +static void ScrollPlayfieldIfNeededExt(boolean reset) { - long DestYOff; + if (reset) + { + mScrollX_last = -1; + mScrollY_last = -1; - DestYOff = mDestYOff; + return; + } - return DestYOff; -} + if (mScrollX_last == -1 || mScrollY_last == -1) + { + mScrollX_last = (mScrollX / TILESIZE) * TILESIZE; + mScrollY_last = (mScrollY / TILESIZE) * TILESIZE; -DirectDrawSurface7 DDScrollBuffer_Get_Surface() -{ - DirectDrawSurface7 Surface; + return; + } + + /* check if scrolling the playfield requires redrawing the viewport bitmap */ + if ((mScrollX != mScrollX_last || + mScrollY != mScrollY_last) && + (ABS(mScrollX - mScrollX_last) >= TILEX || + ABS(mScrollY - mScrollY_last) >= TILEY)) + { + int dx = (ABS(mScrollX - mScrollX_last) < TILEX ? 0 : + mScrollX < mScrollX_last ? 1 : mScrollX > mScrollX_last ? -1 : 0); + int dy = (ABS(mScrollY - mScrollY_last) < TILEY ? 0 : + mScrollY < mScrollY_last ? 1 : mScrollY > mScrollY_last ? -1 : 0); - Surface = Buffer; + mScrollX_last -= dx * TILEX; + mScrollY_last -= dy * TILEY; - return Surface; + ScrollPlayfield(dx, dy); + } } -long DDScrollBuffer_Get_Width() +static void ScrollPlayfieldIfNeeded() { - long Width; - - Width = mWidth; - - return Width; + ScrollPlayfieldIfNeededExt(FALSE); } -int DDScrollBuffer_Get_Height() +void InitScrollPlayfield() { - int Height; - - Height = mHeight; - - return Height; + ScrollPlayfieldIfNeededExt(TRUE); } -long DDScrollBuffer_CreateAtSize(long Width, long Height, long hWndViewPort) +#define DEBUG_REDRAW 0 + +void UpdatePlayfield(boolean force_redraw) { - long CreateAtSize; + int x, y; - DDSURFACEDESC2 SD; +#if DEBUG_REDRAW + int num_redrawn = 0; +#endif - CreateAtSize = 0; - mhWnd = hWndViewPort; - // Create ScrollBuffer: + for (y = DisplayMinY; y <= DisplayMaxY; y++) { - SD.lFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; - SD.ddsCaps.lCaps = DDSCAPS_VIDEOMEMORY; - // SD.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN - SD.LWidth = Width; - SD.LHeight = Height; + for (x = DisplayMinX; x <= DisplayMaxX; x++) + { + int element = LowByte(PlayField16[GetSI(x, y)]); + int graphic = GfxGraphic[x][y]; + int sync_frame = GfxFrame[x][y]; + boolean redraw = force_redraw; + + if (graphic < 0) + { + GfxGraphicLast[x][y] = GfxGraphic[x][y]; + + continue; + } + + if (element != GfxElementLast[x][y] && + graphic == GfxGraphicLast[x][y]) + { + /* element changed, but not graphic => disable updating graphic */ + + GfxElementLast[x][y] = element; + GfxGraphicLast[x][y] = GfxGraphic[x][y] = -1; + + continue; + } + + if (graphic != GfxGraphicLast[x][y]) // new graphic + { + redraw = TRUE; + + GfxElementLast[x][y] = element; + GfxGraphicLast[x][y] = GfxGraphic[x][y]; + sync_frame = GfxFrame[x][y] = 0; + } + else if (isNextAnimationFrame_SP(graphic, sync_frame)) // new frame + { + redraw = TRUE; + } + + if (redraw) + { + int sx = x * StretchWidth; + int sy = y * StretchWidth; + + DDSpriteBuffer_BltImg(sx, sy, graphic, sync_frame); + +#if DEBUG_REDRAW + num_redrawn++; +#endif + } + } } - // --- On Error Resume Next - Buffer = DDraw.CreateSurface(SD); - if (Err.Number != 0) - return CreateAtSize; - - // --- On Error GoTo 0 - - mWidth = Width; - mHeight = Height; - mScrollX = 0; - mScrollY = 0; - CreateAtSize = -1; - - return CreateAtSize; +#if DEBUG_REDRAW + printf("::: FRAME %d: %d redrawn\n", FrameCounter, num_redrawn); +#endif } -void DDScrollBuffer_Cls(int BackColor) +/* copy the entire screen to the window at the scroll position */ + +void BlitScreenToBitmap_SP(Bitmap *target_bitmap) { - RECT EmptyRect; + int px = 2 * TILEX + (mScrollX - mScrollX_last) % TILEX; + int py = 2 * TILEY + (mScrollY - mScrollY_last) % TILEY; + int sx, sy, sxsize, sysize; + int xsize = SXSIZE; + int ysize = SYSIZE; + int full_xsize = (FieldWidth - (menBorder ? 0 : 1)) * TILEX_VAR; + int full_ysize = (FieldHeight - (menBorder ? 0 : 1)) * TILEY_VAR; + + sxsize = (full_xsize < xsize ? full_xsize : xsize); + sysize = (full_ysize < ysize ? full_ysize : ysize); + sx = SX + (full_xsize < xsize ? (xsize - full_xsize) / 2 : 0); + sy = SY + (full_ysize < ysize ? (ysize - full_ysize) / 2 : 0); + + /* scroll correction for even number of visible tiles (half tile shifted) */ + px += game_sp.scroll_xoffset; + py += game_sp.scroll_yoffset; + + if (ExplosionShakeMurphy != 0) + { + px += TILEX / 2 - GetSimpleRandom(TILEX + 1); + py += TILEY / 2 - GetSimpleRandom(TILEX + 1); + } - if (NoDisplayFlag) - return; + px = px * TILESIZE_VAR / TILESIZE; + py = py * TILESIZE_VAR / TILESIZE; - Buffer.BltColorFill(EmptyRect, BackColor); + BlitBitmap(bitmap_db_field_sp, target_bitmap, px, py, sxsize, sysize, sx, sy); } -void DDScrollBuffer_Blt() +void BackToFront_SP(void) { - RECT DR, SR; - long tX, tY, L; - // RECT ERect; - // long Restore; - - if (NoDisplayFlag) - return; - - - // --- On Error GoTo BltEH - DirectX.GetWindowRect(mhWnd, DR); - // --- On Error GoTo 0 - - { - tX = (DR.right - DR.left) / Stretch; - tY = (DR.bottom - DR.top) / Stretch; - } + static int scroll_x_last = -1, scroll_y_last = -1; + static boolean scrolling_last = FALSE; + static boolean ExplosionShakeMurphy_last = -1; + boolean scrolling = (mScrollX != scroll_x_last || mScrollY != scroll_y_last); + int x, y; + + if (0 || + redraw_tiles > REDRAWTILES_THRESHOLD || scrolling || scrolling_last || + ExplosionShakeMurphy != 0 || ExplosionShakeMurphy_last != 0) { - SR.left = mScrollX + mDestXOff; - SR.top = mScrollY + mDestYOff; - SR.right = SR.left + tX; - SR.bottom = SR.top + tY; - // If mWidth < SR.right Then - // SR.right = mWidth - // DR.right = DR.left + Stretch * (SR.right - SR.left) - // End If - // If mHeight < SR.bottom Then - // SR.bottom = mHeight - // DR.bottom = DR.top + Stretch * (SR.bottom - SR.top) - // End If - // If (mScrollX + mDestXOff) < 0 Then - // SR.left = 0 - // DR.left = DR.left - Stretch * (mScrollX + mDestXOff) - // End If - // If (mScrollY + mDestYOff) < 0 Then - // SR.top = 0 - // DR.top = DR.top - Stretch * (mScrollY + mDestYOff) - // End If + BlitScreenToBitmap_SP(window); } - // DDraw.WaitForVerticalBlank DDWAITVB_BLOCKBEGIN, 0 - if (IS_NOTHING(&Buffer, sizeof(Buffer))) - return; - - if (IS_NOTHING(&PrimarySurface, sizeof(PrimarySurface))) - return; - - L = PrimarySurface_Blt(DR, Buffer, SR, DDBLT_WAIT); - if (L != DD_OK) + else { - switch (L) + int scroll_xoffset = mScrollX - mScrollX_last + game_sp.scroll_xoffset; + int scroll_yoffset = mScrollY - mScrollY_last + game_sp.scroll_yoffset; + int x1 = 0, x2 = SCR_FIELDX - (scroll_xoffset != 0 ? 0 : 1); + int y1 = 0, y2 = SCR_FIELDY - (scroll_yoffset != 0 ? 0 : 1); + int full_xsize = (FieldWidth - (menBorder ? 0 : 1)) * TILEX_VAR; + int full_ysize = (FieldHeight - (menBorder ? 0 : 1)) * TILEY_VAR; + int xsize = SXSIZE; + int ysize = SYSIZE; + int sxsize = (full_xsize < xsize ? full_xsize : xsize); + int sysize = (full_ysize < ysize ? full_ysize : ysize); + int sx = SX + (full_xsize < xsize ? (xsize - full_xsize) / 2 : 0); + int sy = SY + (full_ysize < ysize ? (ysize - full_ysize) / 2 : 0); + + InitGfxClipRegion(TRUE, sx, sy, sxsize, sysize); + + scroll_xoffset = scroll_xoffset * TILESIZE_VAR / TILESIZE; + scroll_yoffset = scroll_yoffset * TILESIZE_VAR / TILESIZE; + + for (x = x1; x <= x2; x++) { - case DDERR_GENERIC: - Debug.Assert(False); - break; - - case DDERR_INVALIDCLIPLIST: - Debug.Assert(False); - break; - - case DDERR_INVALIDOBJECT: - Debug.Assert(False); - break; - - case DDERR_INVALIDPARAMS: - Debug.Assert(False); - break; - - case DDERR_INVALIDRECT: - Debug.Assert(False); - break; - - case DDERR_NOALPHAHW: - Debug.Assert(False); - break; - - case DDERR_NOBLTHW: - Debug.Assert(False); - break; - - case DDERR_NOCLIPLIST: - Debug.Assert(False); - break; - - case DDERR_NODDROPSHW: - Debug.Assert(False); - break; - - case DDERR_NOMIRRORHW: - Debug.Assert(False); - break; - - case DDERR_NORASTEROPHW: - Debug.Assert(False); - break; - - case DDERR_NOROTATIONHW: - Debug.Assert(False); - break; - - case DDERR_NOSTRETCHHW: - Debug.Assert(False); - break; - - case DDERR_NOZBUFFERHW: - Debug.Assert(False); - break; - - case DDERR_SURFACEBUSY: - Debug.Assert(False); - break; - - case DDERR_SURFACELOST: - DDraw.RestoreAllSurfaces(); - if (! PrimarySurface.isLost()) - { - subDisplayLevel(); - // Blt(); - } - - // RestorePrimarySurface - // ClipToWindow 0 - break; - - case DDERR_UNSUPPORTED: - Debug.Assert(False); - break; - - case DDERR_WASSTILLDRAWING: - Debug.Assert(False); - break; - - default: - Debug.Assert(False); - break; + for (y = y1; y <= y2; y++) + { + int xx = 2 + x; + int yy = 2 + y; + + if (redraw[xx][yy]) + BlitBitmap(bitmap_db_field_sp, window, + xx * TILEX_VAR, yy * TILEY_VAR, TILEX_VAR, TILEY_VAR, + sx + x * TILEX_VAR - scroll_xoffset, + sy + y * TILEY_VAR - scroll_yoffset); + } } + + InitGfxClipRegion(FALSE, -1, -1, -1, -1); } -#if 0 - // Buffer.UpdateOverlay SR, PrimarySurface, DR, DDOVER_SHOW - if (EditFlag) - FMark.RefreshMarker(); -#endif + for (x = 0; x < 2 + MAX_PLAYFIELD_WIDTH + 2; x++) + for (y = 0; y < 2 + MAX_PLAYFIELD_HEIGHT + 2; y++) + redraw[x][y] = FALSE; + redraw_tiles = 0; - // BltEH: + scroll_x_last = mScrollX; + scroll_y_last = mScrollY; + scrolling_last = scrolling; + ExplosionShakeMurphy_last = ExplosionShakeMurphy; } void DDScrollBuffer_ScrollTo(int X, int Y) @@ -283,12 +305,10 @@ void DDScrollBuffer_ScrollTo(int X, int Y) if (NoDisplayFlag) return; - X = X / Stretch; - Y = Y / Stretch; - mScrollX = X; - mScrollY = Y; - ScrollX = mScrollX; - ScrollY = mScrollY; + ScrollX = mScrollX = X; + ScrollY = mScrollY = Y; + + ScrollPlayfieldIfNeeded(); } void DDScrollBuffer_ScrollTowards(int X, int Y, double Step) @@ -298,12 +318,11 @@ void DDScrollBuffer_ScrollTowards(int X, int Y, double Step) if (NoDisplayFlag) return; - X = X / Stretch; - Y = Y / Stretch; dx = X - mScrollX; dY = Y - mScrollY; + r = Sqr(dx * dx + dY * dY); - if (r == 0) // we are there already + if (r == 0) // we are there already return; if (Step < r) @@ -311,35 +330,32 @@ void DDScrollBuffer_ScrollTowards(int X, int Y, double Step) else r = 1; - mScrollX = mScrollX + dx * r; - mScrollY = mScrollY + dY * r; - ScrollX = mScrollX; - ScrollY = mScrollY; + ScrollX = mScrollX = mScrollX + dx * r; + ScrollY = mScrollY = mScrollY + dY * r; + + ScrollPlayfieldIfNeeded(); } -void DDScrollBuffer_SoftScrollTo(int X, int Y, long TimeMS, int FPS) +void DDScrollBuffer_SoftScrollTo(int X, int Y, int TimeMS, int FPS) { double dx, dY; - TickCountObject Tick; - long dT, StepCount; + int StepCount; double T, tStep; - long oldX, oldY, maxD; - boolean AlreadyRunning; + int oldX, oldY, maxD; + static boolean AlreadyRunning = False; if (NoDisplayFlag) return; if (AlreadyRunning) - { return; - } AlreadyRunning = True; - X = X / Stretch; - Y = Y / Stretch; + dx = X - mScrollX; dY = Y - mScrollY; - maxD = (Abs(dx) < Abs(dY) ? Abs(dY) : Abs(dY)); + maxD = (Abs(dx) < Abs(dY) ? Abs(dY) : Abs(dx)); + StepCount = FPS * (TimeMS / (double)1000); if (StepCount > maxD) StepCount = maxD; @@ -347,36 +363,20 @@ void DDScrollBuffer_SoftScrollTo(int X, int Y, long TimeMS, int FPS) if (StepCount == 0) StepCount = 1; - dT = 1000 / FPS; tStep = (double)1 / StepCount; oldX = mScrollX; oldY = mScrollY; - // R = Sqr(dX * dX + dY * dY) - // If R = 0 Then Exit Sub 'we are there already + for (T = (double)tStep; T <= (double)1; T += tStep) { - if (UserDragFlag) - goto SoftScrollEH; - - // If Claim Then Exit For - Tick.DelayMS(dT, False); - mScrollX = oldX + T * dx; - mScrollY = oldY + T * dY; - ScrollX = mScrollX; - ScrollY = mScrollY; - // Blt(); + ScrollX = mScrollX = oldX + T * dx; + ScrollY = mScrollY = oldY + T * dY; } - if (UserDragFlag) - goto SoftScrollEH; + ScrollX = mScrollX = X; + ScrollY = mScrollY = Y; - Tick.DelayMS(dT, False); - mScrollX = X; - mScrollY = Y; - ScrollX = mScrollX; - ScrollY = mScrollY; - // Blt(); - -SoftScrollEH: AlreadyRunning = False; + + ScrollPlayfieldIfNeeded(); }