Fishtank: C/C++ Version
/****************************************************************************\
* *
* Fishtank.c *
* *
* This program shows how to perform simple animation using Fastgraph for *
* Windows. Several types of tropical fish swim back and forth against a *
* coral reef background. The background image and fish sprites are stored *
* in PCX files. *
* *
\****************************************************************************/
#include <fgwin.h>
#include
#define MAX(x,y) ((x) > (y)) ? (x) : (y)
#define MIN(x,y) ((x) < (y)) ? (x) : (y)
#define NFISH 11
LRESULT CALLBACK WindowProc(HWND,UINT,WPARAM,LPARAM);
long WINAPI _export WindowProc(HWND,UINT,UINT,LONG);
void GetFish(void);
void GoFish(void);
void PutFish(int,int,int,int);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdParam, int iCmdShow)
{
static char szAppName[] = "FGfishtank";
HWND hWnd;
MSG msg;
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wndclass.lpfnWndProc = WindowProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground = NULL;
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
wndclass.hIconSm = LoadIcon(NULL,IDI_APPLICATION);
RegisterClassEx(&wndclass);
hWnd = CreateWindow(szAppName, // window class name
"Fastgraph Fish Tank", // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL); // creation parameters
ShowWindow(hWnd,iCmdShow);
UpdateWindow(hWnd);
// The message loop processes entries placed in the message queue.
// When no message is ready, call GoFish() to perform one frame of
// animation.
while (TRUE)
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
GoFish();
}
return msg.wParam;
}
/****************************************************************************\
* *
* WindowProc() *
* *
\****************************************************************************/
HDC hDC;
HPALETTE hPal;
int hVB1, hVB2;
UINT cxClient, cyClient;
LRESULT CALLBACK WindowProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
switch (iMsg)
{
case WM_CREATE:
// use the default logical palette
hDC = GetDC(hWnd);
fg_setdc(hDC);
hPal = fg_defpal();
fg_realize(hPal);
// create two 320x200 virtual buffers
fg_vbinit();
hVB1 = fg_vballoc(320,200);
hVB2 = fg_vballoc(320,200);
// display the coral background in virtual buffer #2 (which
// will always contain a clean copy of the background image)
fg_vbopen(hVB2);
fg_vbcolors();
fg_showpcx("CORAL.PCX",FG_AT_XY|FG_KEEPCOLORS);
// get the fish bitmaps
GetFish();
return 0;
case WM_PAINT:
BeginPaint(hWnd,&ps);
fg_vbscale(0,fg_getmaxx(),0,fg_getmaxy(),0,cxClient-1,0,cyClient-1);
EndPaint(hWnd,&ps);
return 0;
case WM_SETFOCUS:
fg_realize(hPal);
InvalidateRect(hWnd,NULL,TRUE);
return 0;
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
return 0;
case WM_DESTROY:
fg_vbclose();
fg_vbfree(hVB1);
fg_vbfree(hVB2);
fg_vbfin();
DeleteObject(hPal);
ReleaseDC(hWnd,hDC);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd,iMsg,wParam,lParam);
}
/****************************************************************************\
* *
* GetFish() *
* *
* Fill the fish bitmap arrays. *
* *
\****************************************************************************/
BYTE Fish1[56*25];
BYTE Fish2[54*38];
BYTE Fish3[68*26];
BYTE Fish4[56*30];
BYTE Fish5[62*22];
BYTE Fish6[68*36];
int FishX[] = { 0, 64,128,200, 0, 80}; /* location of fish x & y */
int FishY[] = {199,199,199,199,150,150};
int FishWidth[] = { 56, 54, 68, 56, 62, 68}; /* size of fish: width */
int FishHeight[] = { 25, 38, 26, 30, 22, 36}; /* size of fish: height */
BYTE *Fishes[] = {Fish1, /* for convenience, an array of pointers to fishes */
Fish2,
Fish3,
Fish4,
Fish5,
Fish6};
void GetFish()
{
register int FishNum;
// get the fish bitmaps from a PCX file
fg_vbopen(hVB1);
fg_vbcolors();
fg_showpcx("FISH.PCX",FG_AT_XY|FG_IGNOREPALETTE|FG_KEEPCOLORS);
for (FishNum = 0; FishNum < 6; FishNum++)
{
fg_move(FishX[FishNum],FishY[FishNum]);
fg_getimage(Fishes[FishNum],FishWidth[FishNum],FishHeight[FishNum]);
}
fg_erase();
}
/****************************************************************************\
* *
* GoFish() *
* *
* Make the fish swim around. *
* *
\****************************************************************************/
/* There are 11 fish total, and 6 different kinds of fish. These
* arrays keep track of what kind of fish each fish is, and how each
* fish moves:
*
* Fish[] -- which fish bitmap applies to this fish?
* xStart[] -- starting x coordinate
* yStart[] -- starting y coordinate
*
* xMin[] -- how far left (off screen) the fish can go
* xMax[] -- how far right (off screen) the fish can go
* xInc[] -- how fast the fish goes left and right
* Dir[] -- starting direction for each fish
*
* yMin[] -- how far up this fish can go
* yMax[] -- how far down this fish can go
* yInc[] -- how fast the fish moves up or down
* yTurn[] -- how long fish can go in the vertical direction
* before stopping or turning around
* yCount[] -- counter to compare to yTurn
*/
int Fish[] = { 1, 1, 2, 3, 3, 0, 0, 5, 4, 2, 3};
int xStart[] = {-100,-150,-450,-140,-200, 520, 620,-800, 800, 800,-300};
int yStart[] = { 40, 60, 150, 80, 70, 190, 180, 100, 30, 130, 92};
int xMin[] = {-300,-300,-800,-200,-200,-200,-300,-900,-900,-900,-400};
int xMax[] = { 600, 600,1100,1000,1000, 750, 800,1200,1400,1200, 900};
int xInc[] = { 2, 2, 8, 5, 5, -3, -3, 7, -8, -9, 6};
int Dir[] = { 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0};
int yMin[] = { 40, 60, 120, 70, 60, 160, 160, 80, 30, 110, 72};
int yMax[] = { 80, 100, 170, 110, 100, 199, 199, 120, 70, 150, 122};
int yTurn[] = { 50, 30, 10, 30, 20, 10, 10, 10, 30, 20, 10};
int yCount[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int yInc[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
void GoFish()
{
register int i;
// copy the background to the workspace
fg_copypage(hVB2,hVB1);
// put all the fish in their new positions
for (i = 0; i < NFISH; i++)
{
yCount[i]++;
if (yCount[i] > yTurn[i])
{
yCount[i] = 0;
yInc[i] = (rand() % 3) - 1;
}
yStart[i] += yInc[i];
yStart[i] = MIN(yMax[i],MAX(yStart[i],yMin[i]));
if (xStart[i] >= -72 && xStart[i] < 320)
PutFish(Fish[i],xStart[i],yStart[i],Dir[i]);
xStart[i] += xInc[i];
if (xStart[i] <= xMin[i] || xStart[i] >= xMax[i])
{
xInc[i] = -xInc[i];
Dir[i] = 1 - Dir[i];
}
}
// scale the workspace image to fill the client area
fg_vbscale(0,319,0,199,0,cxClient-1,0,cyClient-1);
}
/****************************************************************************\
* *
* PutFish() *
* *
* Draw one of the six fish anywhere you want. *
* *
\****************************************************************************/
void PutFish (int FishNum, int x, int y, int FishDir)
{
// move to position where the fish will appear
fg_move(x,y);
// draw a left- or right-facing fish, depending on FishDir
if (FishDir == 0)
fg_flpimage(Fishes[FishNum],FishWidth[FishNum],FishHeight[FishNum]);
else
fg_clpimage(Fishes[FishNum],FishWidth[FishNum],FishHeight[FishNum]);
}
|