游戏开发论坛

 找回密码
 立即注册
搜索
查看: 1888|回复: 4

为什么我的水波特效代码不仅慢而且有效果也不对?和别

[复制链接]

2

主题

3

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2005-7-19 13:47:00 | 显示全部楼层 |阅读模式
// 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;
}

42

主题

418

帖子

418

积分

中级会员

Rank: 3Rank: 3

积分
418
发表于 2005-7-19 17:35:00 | 显示全部楼层

Re:为什么我的水波特效代码不仅慢而且有效果也不对?和

这么多代码,俺看不下去了@_@

2

主题

3

帖子

0

积分

新手上路

Rank: 1

积分
0
 楼主| 发表于 2005-7-19 18:37:00 | 显示全部楼层

Re:为什么我的水波特效代码不仅慢而且有效果也不对?和

我是说是不是有DirectX上设置的问题啊?

17

主题

258

帖子

264

积分

中级会员

Rank: 3Rank: 3

积分
264
发表于 2005-7-19 23:22:00 | 显示全部楼层

Re:为什么我的水波特效代码不仅慢而且有效果也不对?和

ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN
这一句改为:
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY
要把所有的OFFSCREEN表面都建立在内存里,而不是显存,这样计算速度会快好多倍.

64

主题

855

帖子

856

积分

高级会员

Rank: 4

积分
856
QQ
发表于 2005-7-20 10:16:00 | 显示全部楼层

Re:为什么我的水波特效代码不仅慢而且有效果也不对?和

同意楼上的
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-12-26 11:52

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表