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

📄 ch11p1_simplefire.cpp

📁 游戏开发特殊技巧-special.effects.game.programming
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
#############################################################################

  Ch11p1_SimpleFire.cpp: a program that demonstrates the fire algorithm,
  without any annoying bells and/or whistles.
  
#############################################################################
*/

// include files ////////////////////////////////////////////////////////////
#define STRICT
#include <stdio.h>
#include <math.h>
#include <D3DX8.h>
#include "D3DApp.h"
#include "D3DFile.h"
#include "D3DFont.h"
#include "D3DUtil.h"
#include "DXUtil.h"
#include "Ch11p1_FirePalette.h"
#include "D3DHelperFuncs.h"
#include "Ch11p1_resource.h"

// A structure for our custom vertex type. 
struct CUSTOMVERTEX
{
  D3DXVECTOR3 position; // The position
  D3DCOLOR    color;    // The color
  FLOAT       tu, tv;   // The texture coordinates
};

const int TEXTURESIZE = 128; // size of the fire texture

// Our custom FVF, which describes our custom vertex structure
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)

//-----------------------------------------------------------------------------
// Name: class CMyD3DApplication
// Desc: Application class. The base class (CD3DApplication) provides the 
//       generic functionality needed in all Direct3D samples. CMyD3DApplication 
//       adds functionality specific to this sample program.
//-----------------------------------------------------------------------------
class CMyD3DApplication : public CD3DApplication
{
  // Font for drawing text
  CD3DFont* m_pFont;
  CD3DFont* m_pFontSmall;

  // Scene
  LPDIRECT3DVERTEXBUFFER8 m_pVB;
  DWORD        m_dwNumVertices;
  
  // Texture
  LPDIRECT3DTEXTURE8 m_pTexture;

  // Texture Palette
  PALETTEENTRY m_Palette[256];
  char m_strTextureSurfFormat[256];
  unsigned char m_cFireField[TEXTURESIZE*TEXTURESIZE];  // first fire array
  unsigned char m_cFireField2[TEXTURESIZE*TEXTURESIZE]; // second fire array
  unsigned char *m_pFireActive;   // we use these two pointers to flip
  unsigned char *m_pFireScratch;  // the active fire array back and forth.

protected:
  HRESULT OneTimeSceneInit();
  HRESULT InitDeviceObjects();
  HRESULT RestoreDeviceObjects();
  HRESULT InvalidateDeviceObjects();
  HRESULT DeleteDeviceObjects();
  HRESULT FinalCleanup();
  HRESULT Render();
  HRESULT FrameMove();
  HRESULT ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior, D3DFORMAT Format );
  LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );

public:
  CMyD3DApplication();
};

//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: Entry point to the program. Initializes everything, and goes into a
//       message-processing loop. Idle time is used to render the scene.
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
  CMyD3DApplication d3dApp;

  if( FAILED( d3dApp.Create( hInst ) ) )
    return 0;

  return d3dApp.Run();
}

//-----------------------------------------------------------------------------
// Name: CMyD3DApplication()
// Desc: Application constructor. Sets attributes for the app.
//-----------------------------------------------------------------------------
CMyD3DApplication::CMyD3DApplication()
{
  m_strWindowTitle    = _T("Ch11p1_SimpleFire");
  m_bUseDepthBuffer   = TRUE;

  m_pFont            = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
  m_pFontSmall       = new CD3DFont( _T("Arial"),  9, D3DFONT_BOLD );
  m_pVB              = NULL;
  m_dwNumVertices    = 6;
  m_pTexture         = NULL;
}

/****************************************************************************

 ProcessFire: this function processes our fire.  It takes two input buffers,
 the fire dimensions, and the cooling amount.  It calculates the new fire
 values from firefield1 and puts them into firefield2.

 ****************************************************************************/
void ProcessFire(unsigned char *firefield, unsigned char *firefield2, int firesizex, int firesizey, int coolamount)
{
  // loop through all the fire values...
  for (int y=0; y < firesizey; y++) {
    for (int x=0; x < firesizex-0; x++) {
      // these will store, temporarily, the fire values immediately to the
      // left, right, top, and bottom of this fire value.
      unsigned char firevalue_left, firevalue_right, firevalue_bottom, firevalue_top;
      int finalfirevalue;

      // x+-1 and y+-1 aren't always that simple; we must account for wrapping
      // around the horizontal edge (not vertical, however).
      // so we calculate x/y +- 1 and store them temporarily.
      int xplus1, xminus1, yplus1, yminus1;
      xplus1 = x+1; if (xplus1 >= firesizex) xplus1=0;
      xminus1= x-1; if (xminus1 < 0) xminus1 = firesizex-1;
      yplus1 = y+1; if (yplus1 >= firesizey) yplus1=firesizey-1;
      yminus1= y-1; if (yminus1 < 0) yminus1 = 0;
      
      // now we can get the fire values of the neighboring pixels
      firevalue_right = firefield[(y*firesizex)+xplus1];
      firevalue_left  = firefield[(y*firesizex)+xminus1];
      firevalue_bottom= firefield[((yplus1)*firesizex)+x];
      firevalue_top   = firefield[((yminus1)*firesizex)+x];

      // now, the most important part-  calculate the new fire value..
      finalfirevalue = (firevalue_left+firevalue_right+firevalue_top+firevalue_bottom)/4;

      // subtract a certain amount to simulate the fire "cooling."
      // this is where you'd apply your cooling map.
      finalfirevalue -= coolamount;

      // make sure that the subtraction of the coolamount didn't take us
      // below zero.
      if (finalfirevalue < 0) finalfirevalue = 0;

      // store the fire value on the scratch array, up one line from where
      // it originally was.  This simulates the flames rising.
      firefield2[((yminus1)*firesizex)+x] = finalfirevalue;
    }
  }

  // add fuel to the fire.  This particular fueling method is one of my
  // favorite; it creates little jet streams of flame.

  // we work in blocks of 2x1...
  for (int x=0; x < firesizex; x+=2) {
    // we add fuel only to the last row.
    int y=firesizey-1;
    
    // determine whether this particular spot gets fuel added or taken
    // away from it, by adding a number between (-31..31)
    int fuel = firefield[(y*firesizex)+x] + (rand() % 64) - 32;

    // we must be between 0-255.
    if (fuel > 255) fuel = 255;
    if (fuel < 0) fuel = 0;

    // apply the new fuel value to two adjacent pixels.  This helps reduce
    // the "dithering" effect that the fire is prone to.
    firefield2[(y*firesizex)+x] = (unsigned char)fuel;
    firefield2[(y*firesizex)+x+1] = (unsigned char)fuel;
  }
}

//-----------------------------------------------------------------------------
// Name: OneTimeSceneInit()
// Desc: Called during initial app startup, this function performs all the
//       permanent initialization.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::OneTimeSceneInit()
{
  // set up the texture palette - in this program, we just grab it directly
  // from our palette header file.
  for (int q=0; q < 255; q++) {
    m_Palette[q].peRed   = g_FireRed[q];
    m_Palette[q].peGreen = g_FireGreen[q];
    m_Palette[q].peBlue  = g_FireBlue[q];
    m_Palette[q].peFlags = 0;
  }
  return S_OK;
}

//-----------------------------------------------------------------------------
// Name: FrameMove()
// Desc: Called once per frame, the call is the entry point for animating
//       the scene.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::FrameMove()
{
  FLOAT fSecsPerFrame = m_fElapsedTime;

  // process the fire
  ProcessFire(m_pFireActive, m_pFireScratch, TEXTURESIZE, TEXTURESIZE, 1);

  // flip-flop the buffers.
  unsigned char *temp = m_pFireActive;
  m_pFireActive = m_pFireScratch;
  m_pFireScratch = temp;

  return S_OK;
}

//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Called once per frame, the call is the entry point for 3d
//       rendering. This function sets up render states, clears the
//       viewport, and renders the scene.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::Render()
{
  HRESULT hr;
  
  // Clear the backbuffer
  m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
                       0x000000, 1.0f, 0L );
  
  // lock texture
  D3DLOCKED_RECT lockedrect;
  ::ZeroMemory(&lockedrect, sizeof(lockedrect));
  

⌨️ 快捷键说明

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