⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winmain.cpp

📁 [游戏开发参考书-用DirectX编写RPG游戏]这是一个系列的丛书如果你都看并且懂的话你就可以你工作啦!
💻 CPP
字号:
/**************************************************
WinMain.cpp
Chapter 6 Particle Demo

Programming Role-Playing Games with DirectX
by Jim Adams (01 Jan 2002)

Required libraries:
  WINMM.LIB, D3D8.LIB, and D3DX8.LIB
**************************************************/

// Include files
#include <windows.h>
#include <stdio.h>
#include "d3d8.h"
#include "d3dx8.h"

// Window handles, class and caption text
HWND          g_hWnd;
HINSTANCE     g_hInst;
static char   g_szClass[]   = "ParticleClass";
static char   g_szCaption[] = "Particle Demo by Jim Adams";

// The Direct3D and Device object
IDirect3D8       *g_pD3D       = NULL;
IDirect3DDevice8 *g_pD3DDevice = NULL;

// The particle vertex format and descriptor
typedef struct {
  FLOAT x, y, z;    // 3D coordinates
  D3DCOLOR Diffuse; // Color
  FLOAT u, v;       // Texture coordinates
} sVertex;
#define VERTEXFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)

// The Particle vertex buffer and texture
IDirect3DVertexBuffer8 *g_pParticleVB      = NULL;
IDirect3DTexture8      *g_pParticleTexture = NULL;

// Create a structure for tracking particles
typedef struct sParticle {
  float    XPos, YPos, ZPos;  // Coordinates
  float    XAdd, YAdd, ZAdd;  // Movement values
  float    Red, Green, Blue;  // Colors
  long     Timer, Counter;    // Current and update counter

  sParticle()
  {
    // Position particle at origin
    XPos = YPos = ZPos = 0.0f;

    // Get a random update counter
    Counter = rand() % 50 + 10;
    Timer = 0;

    // Get a random speed
    XAdd = (float)(rand() % 11) - 5.0f;
    YAdd = (float)(rand() % 11) - 5.0f;
    ZAdd = (float)(rand() % 11) - 5.0f;

    // Get a random color
    Red   = (float)(rand() % 101) / 100.0f;
    Green = (float)(rand() % 101) / 100.0f;
    Blue  = (float)(rand() % 101) / 100.0f;
  }
} sParticle;

sParticle *g_pParticles = NULL;

// Function prototypes
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow);
long FAR PASCAL WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

BOOL DoInit();
BOOL DoShutdown();
BOOL DoFrame();
BOOL SetupParticles();

int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
{
  WNDCLASSEX wcex;
  MSG        Msg;

  g_hInst = hInst;

  // Create the window class here and register it
  wcex.cbSize        = sizeof(wcex);
  wcex.style         = CS_CLASSDC;
  wcex.lpfnWndProc   = WindowProc;
  wcex.cbClsExtra    = 0;
  wcex.cbWndExtra    = 0;
  wcex.hInstance     = hInst;
  wcex.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
  wcex.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wcex.hbrBackground = NULL;
  wcex.lpszMenuName  = NULL;
  wcex.lpszClassName = g_szClass;
  wcex.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
  if(!RegisterClassEx(&wcex))
    return FALSE;

  // Create the Main Window
  g_hWnd = CreateWindow(g_szClass, g_szCaption,
        WS_CAPTION | WS_SYSMENU,
        0, 0, 400, 400,
        NULL, NULL,
        hInst, NULL );
  if(!g_hWnd)
    return FALSE;
  ShowWindow(g_hWnd, SW_NORMAL);
  UpdateWindow(g_hWnd);

  // Run init function and return on error
  if(DoInit() == FALSE)
    return FALSE;

  // Start message pump, waiting for signal to quit
  ZeroMemory(&Msg, sizeof(MSG));
  while(Msg.message != WM_QUIT) {
    if(PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) {
      TranslateMessage(&Msg);
      DispatchMessage(&Msg);
    }
    if(DoFrame() == FALSE)
      break;
  }

  // Run shutdown function
  DoShutdown();
  
  UnregisterClass(g_szClass, hInst);

  return Msg.wParam;
}

long FAR PASCAL WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  switch(uMsg) {
    case WM_DESTROY:
      PostQuitMessage(0);
      return 0;
  }

  return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

BOOL DoInit()
{
  D3DPRESENT_PARAMETERS d3dpp;
  D3DDISPLAYMODE        d3ddm;
  D3DXMATRIX            matView, matProj;

  // Do a windowed mode initialization of Direct3D
  if((g_pD3D = Direct3DCreate8(D3D_SDK_VERSION)) == NULL)
    return FALSE;
  if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))
    return FALSE;
  ZeroMemory(&d3dpp, sizeof(d3dpp));
  d3dpp.Windowed = TRUE;
  d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
  d3dpp.BackBufferFormat = d3ddm.Format;
  d3dpp.EnableAutoDepthStencil = TRUE;
  d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
  if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd,
                                  D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                  &d3dpp, &g_pD3DDevice)))
    return FALSE;

  // Set the render states
  g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
  g_pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);

  // Set ambient light to highest level (to see particles)
  g_pD3DDevice->SetRenderState(D3DRS_AMBIENT, 0xFFFFFFFF);

  // Create and set the projection transformation
  D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, 1.0f, 1.0f, 1000.0f);
  g_pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProj);

  // Create and set the view transformation
  D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(0.0f, 0.0f, -500.0f), &D3DXVECTOR3(0.0f, 0.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
  g_pD3DDevice->SetTransform(D3DTS_VIEW, &matView);

  // Create the vertices
  SetupParticles();

  return TRUE;
}

BOOL DoShutdown()
{
  // Free particles
  if(g_pParticles != NULL)
    delete [] g_pParticles;

  // Release textures and vertex buffers
  if(g_pParticleTexture != NULL)
    g_pParticleTexture->Release();

  if(g_pParticleVB != NULL)
    g_pParticleVB->Release();

  // Release device and 3D objects
  if(g_pD3DDevice != NULL)
    g_pD3DDevice->Release();

  if(g_pD3D != NULL)
    g_pD3D->Release();

  return TRUE;
}

BOOL DoFrame()
{
  D3DXMATRIX matView, matWorld, matTransposed, matTrans;
  static D3DMATERIAL8 Mat;
  static BOOL InitMat = TRUE;
  static DWORD Counter = timeGetTime();

  // Limit to 30fps
  if(timeGetTime() < Counter+33)
    return TRUE;
  Counter = timeGetTime();

  // Configure the material if first time called
  if(InitMat == TRUE) {
    InitMat = FALSE;
    ZeroMemory(&Mat, sizeof(Mat));
    Mat.Diffuse.a = Mat.Ambient.a = 0.5f;
  }

  // Clear device backbuffer
  g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(0,64,128,255), 1.0f, 0);

  if(SUCCEEDED(g_pD3DDevice->BeginScene())) {

    // Set the particle source, shader, and texture
    g_pD3DDevice->SetStreamSource(0, g_pParticleVB, sizeof(sVertex));
    g_pD3DDevice->SetVertexShader(VERTEXFVF);
    g_pD3DDevice->SetTexture(0, g_pParticleTexture);

    // Get and set the transposed view matrix (billboard technique)
    g_pD3DDevice->GetTransform(D3DTS_VIEW, &matView);
    D3DXMatrixTranspose(&matTransposed, &matView);

    // Enable alpha blending
    g_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
    g_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
    g_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);

    // Loop through all particles and draw them
    for(short i=0;i<512;i++) {

      // Move particle first
      g_pParticles[i].XPos += g_pParticles[i].XAdd;
      g_pParticles[i].YPos += g_pParticles[i].YAdd;
      g_pParticles[i].ZPos += g_pParticles[i].ZAdd;

      // Reverse movements if past counter
      if((g_pParticles[i].Timer += 1) >= g_pParticles[i].Counter) {
        g_pParticles[i].Timer = 0;
        g_pParticles[i].XAdd *= -1.0f;
        g_pParticles[i].YAdd *= -1.0f;
        g_pParticles[i].ZAdd *= -1.0f;
      }

      // Setup the particle's world transformation
      D3DXMatrixTranslation(&matTrans, g_pParticles[i].XPos, \
                                       g_pParticles[i].YPos, \
                                       g_pParticles[i].ZPos);
      D3DXMatrixMultiply(&matWorld, &matTrans, &matTransposed);
      g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);

      // Set the particle's material
      Mat.Diffuse.r = Mat.Ambient.r = g_pParticles[i].Red;
      Mat.Diffuse.g = Mat.Ambient.g = g_pParticles[i].Green;
      Mat.Diffuse.b = Mat.Ambient.b = g_pParticles[i].Blue;
      g_pD3DDevice->SetMaterial(&Mat);

      // Draw the particle
      g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
    }

    // Clear the texture usage
    g_pD3DDevice->SetTexture(0, NULL);

    // End the scene
    g_pD3DDevice->EndScene();
  }

  // Display the scene
  g_pD3DDevice->Present(NULL, NULL, NULL, NULL);

  return TRUE;
}

BOOL SetupParticles()
{
  BYTE *Ptr;
  sVertex Verts[4] = {
    { -50.0f, 50.0f, 0.0f, 0xFFFFFFFF, 0.0f, 0.0f },
    {  50.0f, 50.0f, 0.0f, 0xFFFFFFFF, 1.0f, 0.0f },
    { -50.0f,  0.0f, 0.0f, 0xFFFFFFFF, 0.0f, 1.0f },
    {  50.0f,  0.0f, 0.0f, 0xFFFFFFFF, 1.0f, 1.0f }
  };

  // Create vertex buffers and set data
  g_pD3DDevice->CreateVertexBuffer(sizeof(Verts)*4, 0,        \
                  VERTEXFVF, D3DPOOL_DEFAULT, &g_pParticleVB);
  g_pParticleVB->Lock(0,0, (BYTE**)&Ptr, 0);
  memcpy(Ptr, Verts, sizeof(Verts));
  g_pParticleVB->Unlock();

  // Get textures 
  D3DXCreateTextureFromFile(g_pD3DDevice, "Particle.bmp", &g_pParticleTexture);

  // Create some particles
  g_pParticles = new sParticle[512]();

  return TRUE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -