📄 ripple.cpp
字号:
// Ripple.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "resource.h"
#include "bitmap.h"
#include <cmath>
inline void SAFE_RELEASE(LPDIRECTDRAW7 lpdd)
{
if(lpdd)
{
lpdd->Release();
lpdd = NULL;
}
}
inline void SAFE_RELEASE(LPDIRECTDRAWSURFACE7 lpdds)
{
if(lpdds)
{
lpdds->Release();
lpdds = NULL;
}
}
inline BOOL KEYDOWN(int vk)
{
return GetAsyncKeyState(vk) & 0x80000000;
}
//color function
#define _RGB16BIT565(r,g,b) ((b%32) + ((g%64) << 5) + ((r%32) << 11))
inline int GetRValue565(UINT color){ return (color >> 11) & 0x1f; }
inline int GetGValue565(UINT color){ return (color >> 5) & 0xef;}
inline int GetBValue565(UINT color){ return color & 0x1f; }
inline int RGB16BIT565(int r, int g, int b){ return ((r%32) <<11) + ((g%64) << 5) + b%32; }
// Global Variables:
HINSTANCE hInst; // current instance
HWND main_window_handle;
const TCHAR szTitle[] = "DXTest-Ripple"; // The title bar text
const TCHAR szWindowClass[] = "DXTest-Class"; // The title bar text
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 600;
const int COLORBPP = 16;
//ripple object
const double DXPI = 3.1415926;
const int WAVE_LENGTH = 12;
const int PRECISION = 1000;
int disp_index; //wave center displacement index;
int disp[12]; //pixel displacement
int dist[600][800]; //distance to center
Bitmap* pBmpBack;
//ripple function
inline void Build_Disp_Matrix()
{
for(int i = 0; i < 12; ++i)
disp[i] = static_cast<int>(sin((double)i*30*DXPI/360)*PRECISION);
}
void Create_Ripple(int center_x, int center_y, int force, int damp, int wave_length = 12);
void Render_Ripple(LPDIRECTDRAWSURFACE7 lpdds);
//dx objects
LPDIRECTDRAW7 lpdd;
LPDIRECTDRAWSURFACE7 lpddsprimary;
LPDIRECTDRAWSURFACE7 lpddsback;
// Foward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//game function
int Game_Init(LPVOID params = NULL, int num_Params = 0);
int Game_Main(LPVOID params = NULL, int num_params = 0);
int Game_Shutdown(LPVOID params = NULL, int num_params = 0);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
MSG msg;
// Initialize global strings
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
//initial game
Game_Init();
// Main message loop:
while (TRUE)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(WM_QUIT == msg.message) break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}else{
Game_Main();
}
}
Game_Shutdown();
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_RIPPLE);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = (LPCSTR)IDC_RIPPLE;
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;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
0, 0, 0, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
main_window_handle = hWnd;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
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)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int Game_Init(LPVOID params, int num_params)
{
HRESULT hr;
hr = DirectDrawCreateEx(NULL, (void**)&lpdd, IID_IDirectDraw7, NULL);
if(FAILED(hr))
{
return FALSE;
}
hr = lpdd->SetCooperativeLevel(main_window_handle, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
if(FAILED(hr))
{
return FALSE;
}
hr = lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, COLORBPP, 0, 0);
if(FAILED(hr))
{
return FALSE;
}
DDSURFACEDESC2 ddsd = {sizeof(ddsd)};
ddsd.dwFlags = DDSD_BACKBUFFERCOUNT | DDSD_CAPS;
ddsd.dwBackBufferCount = 1;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
hr = lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL);
if(FAILED(hr))
{
return FALSE;
}
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
hr = lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback);
if(FAILED(hr))
{
return FALSE;
}
//init ripple object
disp_index = 11;
Build_Disp_Matrix();
Create_Ripple( 500, 410, 30, 0);
pBmpBack = new Bitmap( lpdd, 800, 600);
pBmpBack->LoadBitmap("back.bmp", 0, 0);
pBmpBack->SetColorKey();
return TRUE;
}
int Game_Main(LPVOID params, int num_params)
{
int start_count = GetTickCount();
if(KEYDOWN(VK_ESCAPE))
SendMessage(main_window_handle, WM_DESTROY, 0, 0);
Render_Ripple(lpddsprimary);
// pBmpBack->Draw(lpddsprimary, 0, 0);
// while((GetTickCount() - start_count) < 50) Sleep(0);
return 0;
}
int Game_Shutdown(LPVOID params, int num_params)
{
delete pBmpBack;
SAFE_RELEASE(lpddsback);
SAFE_RELEASE(lpddsprimary);
SAFE_RELEASE(lpdd);
return TRUE;
}
void Create_Ripple(int center_x, int center_y, int force, int damp, int wave_length)
{
for(int i = 0 ; i < wave_length; ++i)
{
disp[i] = force * disp[i] / PRECISION;
}
int dist_x, dist_y;
for(i = 0; i < SCREEN_HEIGHT; ++i)
{
for(int j = 0; j< SCREEN_WIDTH; ++j)
{
dist_y = i - center_y;
dist_x = j - center_x;
dist[i][j] = static_cast<int>(sqrt(dist_x*dist_x +
dist_y*dist_y) + 0.5) % wave_length;
}
}
}
void Render_Ripple(LPDIRECTDRAWSURFACE7 lpdds)
{
DDSURFACEDESC2 ddsd = { sizeof(ddsd) };
if(disp_index < 0) disp_index = 12;
--disp_index;
lpdds->Lock(NULL,&ddsd, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL);
short* lpSrcBuffer = static_cast<short*>(
pBmpBack->GetBitmapBuffer());
int pitch = (ddsd.lPitch) >> 1;
short* lpBuffer = static_cast<short*>(ddsd.lpSurface);
int left,right,bottom,top;
int k = 0,l = 0;
int index_x,index_y;
int x_off,y_off;
int pos1,pos2;
for(int i = 1; i < SCREEN_HEIGHT - 2; ++i)
for( int j = 1; j < SCREEN_WIDTH - 2; ++j)
{
left = right = bottom = top = disp_index;
left += dist[i][j -1];
if(left > 12) left -= 12;
right += dist[i][j+1];
if(right >12) right -= 12;
bottom+=dist[i+1][j];
if(bottom > 12) bottom -= 12;
top += dist[i-1][j];
if(top >12 ) top -= 12;
x_off = disp[left] - disp[right];
y_off = disp[top] - disp[bottom];
index_x = j + x_off;
index_y = i + y_off;
pos1 = i*pitch +j;
pos2 = index_y * 800 + index_x;
if(pos2 < 0 || pos2 > 479999) break;
lpBuffer[pos1] = lpSrcBuffer[pos2];
}
pBmpBack->ReleaseBuffer();
lpdds->Unlock(NULL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -