|
|
// water.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "resource.h"
#define INITGUID
#include <stdio.h>
#include <ddraw.h>
#include <mmsystem.h>
#include <time.h>
#define MAX_LOADSTRING 100
#define SafeRelease(x) if (x) { x->Release(); x=NULL;}
#define STONE_SIZE 4
#define DATAWIDTH 640
#define DATAHEITH 480
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text
//------ Global Interface Pointers ------//
LPDIRECTDRAW7 lpDD=NULL;
LPDIRECTDRAWSURFACE7 lpDDSPrimary=NULL;
LPDIRECTDRAWSURFACE7 lpDDSBack=NULL;
LPDIRECTDRAWSURFACE7 lpmap=NULL;
static char water_data[DATAWIDTH*DATAHEITH];
static char water_data1[DATAWIDTH*DATAHEITH];
static tick;
char *buf1,*buf2;
// Foward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
//------ Function to Load a Bitmap into a DirectDraw Surface ------//
LPDIRECTDRAWSURFACE7 bitmap_surface(LPCTSTR file_name,RECT *dims=NULL)
{
HDC hdc;
HBITMAP bit;
LPDIRECTDRAWSURFACE7 surf=NULL;
// load the bitmap
bit=(HBITMAP) LoadImage(NULL,file_name,IMAGE_BITMAP,0,0,
LR_DEFAULTSIZE|LR_LOADFROMFILE);
if (!bit)
// failed to load, return failure to caller
return NULL;
// get bitmap dimensions
BITMAP bitmap;
GetObject( bit, sizeof(BITMAP), &bitmap );
int surf_width=bitmap.bmWidth;
int surf_height=bitmap.bmHeight;
// create surface
HRESULT ddrval;
DDSURFACEDESC2 ddsd;
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize = sizeof(DDSURFACEDESC2);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT ;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwWidth = surf_width;
ddsd.dwHeight = surf_height;
// attempt to create surface
ddrval=lpDD->CreateSurface(&ddsd,&surf,NULL);
// created ok?
if (ddrval!=DD_OK) {
// no, release the bitmap and return failure to caller
DeleteObject(bit);
return NULL;
} else {
// yes, get a DC for the surface
surf->GetDC(&hdc);
// generate a compatible DC
HDC bit_dc=CreateCompatibleDC(hdc);
// blit the interface to the surface
SelectObject(bit_dc,bit);
BitBlt(hdc,0,0,surf_width,surf_height,bit_dc,0,0,SRCCOPY);
// release the DCs
surf->ReleaseDC(hdc);
DeleteDC(bit_dc);
// save the dimensions if rectangle pointer provided
if (dims) {
dims->left=0;
dims->top=0;
dims->right=surf_width;
dims->bottom=surf_height;
}
}
// clear bitmap
DeleteObject(bit);
// return pointer to caller
return surf;
}
void Put_Stone(int x0,int y0)
{
int x,y;
char *p;
if(tick&1)p=water_data1;
else p=water_data;
for(x=x0-STONE_SIZE;x<x0+STONE_SIZE;x++)
for(y=y0-STONE_SIZE;y<y0+STONE_SIZE;y++)
if((x-x0)*(x-x0)+(y-y0)*(y-y0)<=STONE_SIZE*STONE_SIZE)
p[y*DATAWIDTH+x]=10;
}
//处理水纹
void RippleSpread()
{
int i;
if(tick&1)
{
buf1=water_data1;
buf2=water_data;
}
else
{
buf1=water_data;
buf2=water_data1;
}
tick++;
for(i=DATAWIDTH;i<DATAWIDTH*DATAHEITH-DATAWIDTH;i++)
{
buf2=((buf1[i-1]+buf1[i+1]+buf1[i+DATAWIDTH]+buf1[i-DATAWIDTH])>>1)-buf2;
buf2>>=1;
}
}
//具体的操作
void render_frame()
{
static kstep=2;
DDSURFACEDESC2 ddsd1;
DDSURFACEDESC2 ddsd2;
static rand_stone;
int depth1,depth2;
int xoff,yoff;
int k=DATAWIDTH+1;
int i,j,t;
int lstep1,lstep2;
int pos1,pos2;
if(lpDDSPrimary->IsLost())
lpDDSPrimary->Restore();
if(lpmap->IsLost())
{
lpmap->Restore();
lpmap=bitmap_surface("1.bmp");
}
ZeroMemory(&ddsd1,sizeof(DDSURFACEDESC2));
ddsd1.dwSize=sizeof(DDSURFACEDESC2);
ZeroMemory(&ddsd2,sizeof(DDSURFACEDESC2));
ddsd2.dwSize=sizeof(DDSURFACEDESC2);
lpDDSBack->Lock(NULL,&ddsd1,DDLOCK_WAIT,NULL);
lpmap->Lock(NULL,&ddsd2,DDLOCK_WAIT,NULL);
depth1=ddsd1.ddpfPixelFormat.dwRGBBitCount/8;
depth2=ddsd2.ddpfPixelFormat.dwRGBBitCount/8;
lstep1=ddsd1.lPitch;
lstep2=ddsd2.lPitch;
/*
if(depth1!=depth2)
{
lpmap->Unlock(NULL);
lpDDSBack->Unlock(NULL);
return;
}
if(lstep1!=lstep2)
{
lpmap->Unlock(NULL);
lpDDSBack->Unlock(NULL);
return;
}
*/
unsigned char *pmap=(unsigned char *)ddsd2.lpSurface;
unsigned char *pmem=(unsigned char *)ddsd1.lpSurface;
//开始处理数据
rand_stone++;
RippleSpread();
if(rand_stone==5)
{
rand_stone=0;
Put_Stone(rand()%600,rand()%400);
}
/*
for(i=0;i<DATAHEITH/5;i++)
{
memcpy(pmem,pmap+kstep,640*2-kstep);
memcpy(pmem+640*2-kstep,pmap,kstep);
pmem+=lstep1;
pmap+=lstep2;
}
kstep+=2;
if(kstep==640*2)kstep=2;
*/
for(i=1;i<DATAHEITH-1;i++)
{
for(j=1;j<DATAWIDTH-1;j++)
{
xoff=buf2[k-1]-buf2[k+1];
yoff=buf2[k-DATAWIDTH]-buf2[k+DATAWIDTH];
if((i+yoff)<0||(i+yoff)>DATAHEITH||(j+xoff)<0||(j+xoff)>DATAWIDTH){k++;continue;}
pos1=lstep2*(i+yoff)+2*(j+xoff);
pos2=lstep1*i+2*j;
//for(t=0;t<depth;t++)
pmem[pos2++]=pmap[pos1++];
pmem[pos2++]=pmap[pos1++];
k++;
}
k+=2;
}
//结束处理数据
lpmap->Unlock(NULL);
lpDDSBack->Unlock(NULL);
// lpDDSBack->BltFast(0,0,lpmap,NULL,DDBLTFAST_WAIT);
lpDDSPrimary->Flip(0,DDFLIP_WAIT);
}
void Cleanup()
{
// release DirectDraw interfaces
SafeRelease(lpDDSPrimary);
SafeRelease(lpDD);
// display error if one thrown
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
MSG msg;
BOOL notDone=TRUE;
LONGLONG cur_time;
DWORD time_count=16;
LONGLONG perf_cnt; // performance timer frequency
BOOL perf_flag=FALSE; // flag determining which timer to use
LONGLONG next_time=0; // time to render next frame
LONGLONG last_time=0; // time of previous frame
double time_scale; // scaling factor for time
HACCEL hAccelTable;
srand( (unsigned)time( NULL ) );
Put_Stone(rand()%600,rand()%400);
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_WATER, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_WATER);
/*
// Main message loop:
if (QueryPerformanceFrequency((LARGE_INTEGER *) &perf_cnt)) {
// yes, set time_count and timer choice flag
perf_flag=TRUE;
time_count=perf_cnt/30;
QueryPerformanceCounter((LARGE_INTEGER *) &next_time);
time_scale=1.0/perf_cnt;
} else {
// no performance counter, read in using timeGetTime
next_time=timeGetTime();
time_scale=0.001;
}
// save time of last frame
last_time=next_time;
// run till completed
*/
// Main message loop:
while (notDone) {
// is there a message to process?
if (PeekMessage( &msg, NULL, 0, 0, PM_REMOVE)) {
// yes, is it a quit message?
if (msg.message==WM_QUIT)
notDone=0;
// dispatch the message
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
// use the appropriate method to get time
// and calculate elapsed time since last frame
/*
if (perf_flag)
QueryPerformanceCounter((LARGE_INTEGER *) &cur_time);
else
cur_time=timeGetTime();
// is it time to render the frame?
if (cur_time>next_time) {
// save frame time
last_time=cur_time;
// yes, render the frame
render_frame();
next_time = cur_time + time_count;
}
*/
render_frame();
}
}
return msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage is only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_WATER);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);;
wcex.lpszMenuName = NULL;//(LPCSTR)IDC_WATER;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HANDLE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
HRESULT ddrval;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE|WS_POPUP,
0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
ddrval = DirectDrawCreateEx(NULL, (VOID **) &lpDD, IID_IDirectDraw7, NULL);
if (ddrval != DD_OK) {
return FALSE;
}
// Set our cooperative level
ddrval = lpDD->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
if (ddrval != DD_OK) {
return FALSE;
}
// Set the display mode
ddrval = lpDD->SetDisplayMode( 640, 480, 16, 0, 0);
if (ddrval !=DD_OK) {
return FALSE;
}
// Create the primary surface with 1 back buffer
DDSURFACEDESC2 ddsd;
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
DDSCAPS_FLIP |
DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1;
ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );
if (ddrval!=DD_OK) {
return FALSE;
}
// Fetch back buffer interface
DDSCAPS2 ddscaps;
ZeroMemory(&ddscaps,sizeof(ddscaps));
ddscaps.dwCaps=DDSCAPS_BACKBUFFER;
ddrval=lpDDSPrimary->GetAttachedSurface(&ddscaps,&lpDDSBack);
if (ddrval!=DD_OK) {
return FALSE;
}
// load the first image and display it
lpmap=bitmap_surface("1.bmp");
if (!lpmap)
return FALSE;
// return success to caller
return TRUE;
}
//
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
TCHAR szHello[MAX_LOADSTRING];
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_DESTROY:
Cleanup();
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
|
|