232 lines
4.8 KiB
C
232 lines
4.8 KiB
C
// "Dropout" module for IdleWild.
|
|
//
|
|
// By Tony Krueger
|
|
|
|
#ifdef PM
|
|
#define INCL_WIN
|
|
#define INCL_GPI
|
|
#include <os2.h>
|
|
/*int _acrtused = 0;*/
|
|
#endif
|
|
#ifdef WIN
|
|
#include <windows.h>
|
|
#include <port1632.h>
|
|
#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;
|
|
}
|