// "Dropout" module for IdleWild. // // By Tony Krueger #ifdef PM #define INCL_WIN #define INCL_GPI #include /*int _acrtused = 0;*/ #endif #ifdef WIN #include #include #endif #include "std.h" #include "scrsave.h" #define cMovesMax 20 /* Max number of moves in one ANIMATE call */ #define cxBlockMax 32 /* Enough for 8514 */ #define cyBlockMax 24 #define FUsedXY(x, y) rgf[x + y * cxBlock] // Globals INT dxScreen, dyScreen; HDC hMemoryDC = NULL; HBITMAP hbmpScreen = NULL; HBITMAP hbmpBlock = NULL; HBITMAP hbmpOld = NULL; INT fBlock; INT x, y, dx, dy, dyVel; INT dxBlock, dyBlock; INT cxBlock, cyBlock; INT fAbove; INT cBlockRemain; UCHAR rgf[cxBlockMax * cyBlockMax]; INT rand(); BOOL EXPENTRY ScrSaveProc(INT ssm, LPVOID l1, LONG_PTR l2, LONG_PTR l3) { CHAR FAR * lpsz; CHAR FAR * lpch; switch (ssm) { default: return fFalse; case SSM_OPEN: lpsz = (PSZ) l1; lpch = "Dropout"; while ((*lpsz++ = *lpch++) != '\0') ; lpsz = (PSZ) l2; lpch = "Screen Blocks\nDrop Out\n\nby Tony Krueger"; while ((*lpsz++ = *lpch++) != '\0') ; #ifdef PM dxScreen = WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN); dyScreen = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN); #endif #ifdef WIN dxScreen = GetSystemMetrics(SM_CXSCREEN); dyScreen = GetSystemMetrics(SM_CYSCREEN); #endif break; case SSM_BLANK: { CVS cvs; ScrRestoreScreen(); cvs = (CVS) l1; dxBlock = 32; dyBlock = dxBlock * GetDeviceCaps(cvs, ASPECTX) / GetDeviceCaps(cvs, ASPECTY); if (dyBlock <= 0) // Assure at least one dyBlock = 1; cxBlock = (dxScreen + dxBlock - 1) / dxBlock; cyBlock = (dyScreen + dyBlock - 1) / dyBlock; // Assure number of blocks small enough while (cxBlock * cyBlock > cxBlockMax * cyBlockMax) { dxBlock *= 2; dyBlock *= 2; cxBlock = (dxScreen + dxBlock - 1) / dxBlock; cyBlock = (dyScreen + dyBlock - 1) / dyBlock; } cBlockRemain = cxBlock * cyBlock; for (x = 0; x < cxBlock; x++) for (y = 0; y < cyBlock; y++) FUsedXY(x, y) = fFalse; hMemoryDC = CreateCompatibleDC(cvs); hbmpScreen = CreateCompatibleBitmap(cvs, dxScreen, dyScreen); hbmpBlock = CreateCompatibleBitmap(cvs, dxBlock, dyBlock); if (hMemoryDC == NULL || hbmpScreen == NULL || hbmpBlock == NULL) { if (hMemoryDC != NULL) DeleteDC(hMemoryDC); hMemoryDC = NULL; if (hbmpScreen != NULL) DeleteObject(hbmpScreen); hbmpScreen = NULL; if (hbmpBlock != NULL) DeleteObject(hbmpBlock); hbmpBlock = NULL; ScrChooseRandomServer(); } else { hbmpOld = SelectObject(hMemoryDC, hbmpScreen); BitBlt(hMemoryDC, 0, 0, dxScreen, dyScreen, cvs, 0, 0, SRCCOPY); } fBlock = fFalse; } break; case SSM_UNBLANK: if (hMemoryDC != NULL) { SelectObject(hMemoryDC, hbmpOld); DeleteDC(hMemoryDC); } if (hbmpScreen != NULL) DeleteObject(hbmpScreen); if (hbmpBlock != NULL) DeleteObject(hbmpBlock); break; case SSM_ANIMATE: { CVS cvs; cvs = (CVS) l1; if (fBlock) { INT cMoves = 0; while (cMoves < cMovesMax && x <= dxScreen && x >= -dxBlock) { SelectObject(hMemoryDC, hbmpBlock); BitBlt(cvs, x, y, dxBlock, dyBlock, hMemoryDC, 0, 0, SRCCOPY); SelectObject(hMemoryDC, hbmpScreen); dyVel += 1; dy = dyVel / 16; if (dy > 0) BitBlt(cvs, x, y, dxBlock, dy, hMemoryDC, x, y, SRCCOPY); else if (dy < 0) BitBlt(cvs, x, y + dyBlock + dy, dxBlock, -dy, hMemoryDC, x, y + dyBlock + dy, SRCCOPY); if (dx > 0) BitBlt(cvs, x, y, dx, dyBlock, hMemoryDC, x, y, SRCCOPY); else if (dx < 0) BitBlt(cvs, x + dxBlock + dx, y, -dx, dyBlock, hMemoryDC, x + dxBlock + dx, y, SRCCOPY); y += dy; x += dx; if (y >= dyScreen - dyBlock && fAbove) { dyVel = -dyVel * 3 / 4 ; fAbove = fFalse; } else fAbove = fTrue; cMoves++; } fBlock = (x <= dxScreen && x >= -dxBlock); } else { INT cMoves = 0; do { // Choose random block x = WRand(cxBlock); y = WRand(cyBlock); } while (cMoves++ < cMovesMax && FUsedXY(x, y) == fTrue); if (cBlockRemain <= 0 || hMemoryDC == NULL) { ScrChooseRandomServer(); } else if (cMoves < cMovesMax) { FUsedXY(x, y) = fTrue; cBlockRemain--; x *= dxBlock; y *= dyBlock; // Copy original block into block bitmap SelectObject(hMemoryDC, hbmpBlock); BitBlt(hMemoryDC, 0, 0, dxBlock, dyBlock, cvs, x, y, SRCCOPY); // Black out block on screen PatBlt(cvs, x, y, dxBlock, dyBlock, BLACKNESS); // And on screen bitmap SelectObject(hMemoryDC, hbmpScreen); PatBlt(hMemoryDC, x, y, dxBlock, dyBlock, BLACKNESS); do { dx = WRand(5) - 2; dyVel = -(WRand(5) * 16); } while (dx == 0); fAbove = fTrue; fBlock = fTrue; } } } break; } return fTrue; }