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

📄 winmain.cpp

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

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

Required libraries:
  D3D8.LIB, D3DX8.LIB, D3DXOF.LIB, DXGUID.LIB,
  DINPUT8.LIB, DSOUND.LIB, and WINMM.LIB 
**************************************************/

//#define FULLSCREENMODE
#include "Global.h"

///////////////////////////////////////////////////////////
// Global declarations
///////////////////////////////////////////////////////////
#define MENU_BACK   1
#define MENU_LOAD   2
#define MENU_SAVE   4

long g_MenuOptions = 0;

// Global names of character meshes
char *g_CharMeshNames[] = {
    { "..\\Data\\Warrior1.x" },   // Mesh # 0
    { "..\\Data\\Warrior2.x" },   // Mesh # 1
    { "..\\Data\\Yodan1.x"   },   // Mesh # 2
    { "..\\Data\\Yodan2.x"   },   // Mesh # 3
    { "..\\Data\\Yodan3.x"   },   // Mesh # 4
    { "..\\Data\\Yodan4.x"   }    // Mesh # 5
  };

// Global character animation information
sCharAnimationInfo g_CharAnimations[] = {
    { "Idle",  TRUE  },
    { "Walk",  TRUE  },
    { "Swing", FALSE },
    { "Spell", FALSE },
    { "Swing", FALSE },
    { "Hurt",  FALSE },
    { "Die",   FALSE },
    { "Idle",  TRUE  }
  };

// Global spell mesh information
char *g_SpellMeshNames[] = {
    { "..\\Data\\Fireball.x"   },
    { "..\\Data\\Explosion.x"  },
    { "..\\Data\\Ice.x"        },
    { "..\\Data\\Heal.x"       },
    { "..\\Data\\Teleport.x"   },
    { "..\\Data\\Groundball.x" },
    { "..\\Data\\Bomb.x"       },
    { "..\\Data\\Force.x"      }
  };

// Global sound effect filenames
#define NUM_SOUNDS 9
char *g_SoundFilenames[NUM_SOUNDS] = {
    { "..\\Data\\Attack1.wav" },
    { "..\\Data\\Attack2.wav" },
    { "..\\Data\\Spell.wav"   },
    { "..\\Data\\Roar.wav"    },
    { "..\\Data\\Hurt1.wav"   },
    { "..\\Data\\Hurt2.wav"   },
    { "..\\Data\\Die1.wav"    },
    { "..\\Data\\Die2.wav"    },
    { "..\\Data\\Beep.wav"    }
  };

// Global music filenames
long g_CurrentMusic = -1;
char *g_MusicFilenames[] = {
    { "..\\Data\\Cathedral_Sunrise.mid" },
    { "..\\Data\\Distant_tribe.mid"     },
    { "..\\Data\\Escape.mid"            },
    { "..\\Data\\Jungle1.mid"           },
    { "..\\Data\\Magic_Harp.mid"        },
    { "..\\Data\\Medi_Strings.mid"      },
    { "..\\Data\\Medi_techno.mid"       },
    { "..\\Data\\Song_of_the_sea.mid"   },
    { "..\\Data\\Storm.mid"             }
  };

// Global character pointer to PC, bartering NPC, and barter ICS
sCharacter *g_PCChar = NULL;
sCharacter *g_BarterChar = NULL;
char        g_BarterICS[MAX_PATH];

///////////////////////////////////////////////////////////
// cApp function code
///////////////////////////////////////////////////////////
cApp::cApp()
{ 
  m_Width  = 640; 
  m_Height = 480;
  m_Style  = WS_BORDER | WS_CAPTION |                         \
             WS_MINIMIZEBOX | WS_SYSMENU;
  strcpy(m_Class, "GameClass");
  strcpy(m_Caption, "The Tower by Jim Adams");
}

BOOL cApp::Init()
{
  // Initialize the graphics device
  m_Graphics.Init();

  // Determine to use fullscreen mode or not
#ifdef FULLSCREENMODE
  m_Graphics.SetMode(GethWnd(), FALSE, TRUE, 640, 480);
#else
  m_Graphics.SetMode(GethWnd(), TRUE, TRUE);
#endif

  // Set perspective
  m_Graphics.SetPerspective(0.6021124f,1.33333f,1.0f,20000.0f);

  // Enable cursor
  ShowMouse(TRUE);

  // Create a font
  m_Font.Create(&m_Graphics, "Arial", 16, TRUE);

  // Initialize input and input devices
  m_Input.Init(GethWnd(), GethInst());
  m_Keyboard.Create(&m_Input, KEYBOARD);
  m_Mouse.Create(&m_Input, MOUSE, TRUE);

  // Initialize the sound system and channels
  m_Sound.Init(GethWnd(), 22050, 1, 16);
  m_SoundChannel.Create(&m_Sound, 22050, 1, 16);
  m_MusicChannel.Create(&m_Sound);
  
  // Load the master item list
  FILE *fp;
  for(long i=0;i<1024;i++)
    ZeroMemory(&m_MIL[i], sizeof(sItem));
  if((fp=fopen("..\\Data\\Game.mil", "rb")) != NULL) {
    for(i=0;i<1024;i++)
      fread(&m_MIL[i], 1, sizeof(sItem), fp);
    fclose(fp);
  }

  // Initialize the character controller
  m_CharController.SetData(this);
  m_CharController.Init(&m_Graphics, &m_Font,                 \
      "..\\Data\\Game.mcl", (sItem*)&m_MIL,                   \
      m_SpellController.GetSpell(0),                          \
      sizeof(g_CharMeshNames)/sizeof(char*), g_CharMeshNames, \
      "..\\Data\\", "..\\Data\\",                             \
      sizeof(g_CharAnimations) / sizeof(sCharAnimationInfo),  \
      (sCharAnimationInfo*)&g_CharAnimations,                 \
      &m_SpellController);

  // Initialize the spell controller
  m_SpellController.SetData(this);
  m_SpellController.Init(&m_Graphics,                         \
     "..\\Data\\Game.msl",                                    \
     sizeof(g_SpellMeshNames)/sizeof(char*),g_SpellMeshNames, \
     "..\\Data\\", &m_CharController);

  // Get the options bitmap
  m_Options.Load(&m_Graphics, "..\\Data\\Options.bmp");

  // Create the main, header, and stats windows
  m_Window.Create(&m_Graphics, &m_Font);
  m_Header.Create(&m_Graphics, &m_Font);
  m_Stats.Create(&m_Graphics, &m_Font);

  // Position all windows
  m_Window.Move(2,2, 636, 476);
  m_Header.Move(2,2,128,32,-1,-1,D3DCOLOR_RGBA(128,16,16,255));
  m_Stats.Move(2,2,128,48);

  // Set script application pointer
  m_Script.SetData(this);

  // Push the main menu state, setting menu options first
  g_MenuOptions = MENU_LOAD;
  m_StateManager.Push(MenuFrame, this);

  return TRUE;
}

BOOL cApp::Shutdown()
{
  // Pop all states
  m_StateManager.PopAll(this);

  // Free controllers
  m_CharController.Free();
  m_SpellController.Free();

  // Free script object
  m_Script.Free();

  // Free level data
  FreeLevel();

  // Free the options texture
  m_Options.Free();

  // Free the text windows
  m_Window.Free();
  m_Header.Free();
  m_Stats.Free();

  // Shutdown sound
  m_MusicChannel.Free();
  m_SoundChannel.Free();
  m_Sound.Shutdown();

  // Shutdown input
  m_Keyboard.Free();
  m_Mouse.Free();
  m_Input.Shutdown();

  // Shutdown graphics
  m_Font.Free();
  m_Graphics.Shutdown();

  return TRUE;
}

BOOL cApp::Frame()
{
  static DWORD UpdateTimer = timeGetTime();

  // Limit all frame updates to 30 fps
  if(timeGetTime() < UpdateTimer + 33)
    return TRUE;
  UpdateTimer = timeGetTime();

  // Acquire input devices and read input for all states
  m_Keyboard.Acquire(TRUE);   // Read keyboard
  m_Keyboard.Read();
  m_Mouse.Acquire(TRUE);      // Read mouse
  m_Mouse.Read();

  // Process state, returning result
  return m_StateManager.Process(this);
}

BOOL cApp::RenderFrame(long Elapsed)
{
  long i, j;

  // Render simplified mesh for z-values
  m_Graphics.EnableZBuffer(TRUE);
  m_SceneObject.Render();

  // Draw the backdrop (composed of six textures)
  m_Graphics.EnableZBuffer(FALSE);
  m_Graphics.BeginSprite();
  for(i=0;i<2;i++) {
    for(j=0;j<3;j++)
      m_SceneTextures[i*3+j].Blit(j*256,i*256);
  }
  m_Graphics.EndSprite();

  // Draw the 3-D objects
  m_Graphics.EnableZBuffer(TRUE);
  m_CharController.Render(Elapsed);
  m_SpellController.Render();

  return TRUE;
}

float cApp::GetHeightBelow(float XPos, float YPos, float ZPos)
{
  BOOL  Hit;
  float u, v, Dist;
  DWORD FaceIndex;

  D3DXIntersect(m_SceneMesh.GetParentMesh()->m_Mesh, 
                &D3DXVECTOR3(XPos,YPos,ZPos),
                &D3DXVECTOR3(0.0f, -1.0f, 0.0f),
                &Hit, &FaceIndex, &u, &v, &Dist);
  if(Hit == TRUE)
    return YPos-Dist;
  return YPos;
}

BOOL cApp::CheckIntersect(                                    \
                    float XStart, float YStart, float ZStart, \
                    float XEnd,   float YEnd,   float ZEnd,   \
                    float *Length)
{
  BOOL  Hit;
  float u, v, Dist;
  float XDiff, YDiff, ZDiff, Size;
  DWORD FaceIndex;
  D3DXVECTOR3 vecDir;

  XDiff = XEnd - XStart;
  YDiff = YEnd - YStart;
  ZDiff = ZEnd - ZStart;

  D3DXVec3Normalize(&vecDir, &D3DXVECTOR3(XDiff, YDiff, ZDiff));

  D3DXIntersect(m_SceneMesh.GetParentMesh()->m_Mesh,          \
                &D3DXVECTOR3(XStart,YStart,ZStart), &vecDir,  \
                &Hit, &FaceIndex, &u, &v, &Dist);

  if(Hit == TRUE) {
    Size = (float)sqrt(XDiff*XDiff+YDiff*YDiff+ZDiff*ZDiff);
    if(Dist > Size)
      Hit = FALSE;
    else {
      if(Length != NULL)
        *Length = Dist;
    }
  }

  return Hit;
}

float cApp::GetNextFloat(FILE *fp)
{
  char Buf[1024];
  long Pos = 0;
  int c;

  // Read until EOF or EOL
  while(1) {
    if((c = fgetc(fp)) == EOF)
      break;
    if(c == 0x0a || c == ' ')
      break;
    if((c >= '0' && c <= '9') || c == '.' || c == '-')
      Buf[Pos++] = c;
  }
  Buf[Pos] = 0;

  return (float)atof(Buf);
}

BOOL cApp::LoadLevel(long Num)
{
  char Filename[MAX_PATH];
  FILE *fp;
  long i;
  float XPos, YPos, ZPos, XAt, YAt, ZAt;

  FreeLevel(); // Free a prior level

  // Record scene number
  m_SceneNum = Num;

  // Load the backdrop textures
  for(i=0;i<6;i++) {
    sprintf(Filename, "..\\Data\\Scene%u%u.bmp", Num, i+1);
    if(m_SceneTextures[i].Load(&m_Graphics, Filename) == FALSE)
      return FALSE;
  }

  // Load the scene mesh and configure object
  sprintf(Filename, "..\\Data\\Scene%u.x", Num);
  if(m_SceneMesh.Load(&m_Graphics, Filename) == FALSE)
    return FALSE;
  m_SceneObject.Create(&m_Graphics, &m_SceneMesh);

  // Load the camera data
  sprintf(Filename, "..\\Data\\Cam%u.txt", Num);
  if((fp=fopen(Filename, "rb"))==NULL)
    return FALSE;
  XPos = GetNextFloat(fp);
  YPos = GetNextFloat(fp);
  ZPos = GetNextFloat(fp);
  XAt  = GetNextFloat(fp);
  YAt  = GetNextFloat(fp);
  ZAt  = GetNextFloat(fp);
  fclose(fp);
  m_Camera.Point(XPos, YPos, ZPos, XAt, YAt, ZAt);

  // Position the camera for the scene
  m_Graphics.SetCamera(&m_Camera);

  // Set no monsters in last frame
  m_MonstersLastFrame = FALSE;

  // Execute the script for loading this scene
  sprintf(Filename, "..\\Data\\Scene%lu.mls", Num);
  m_Script.Execute(Filename);

  return TRUE;
}

BOOL cApp::FreeLevel()
{
  sCharacter *CharPtr, *NextChar;
  long i;

  // Free scene mesh and textures
  m_SceneMesh.Free();
  m_SceneObject.Free();
  for(i=0;i<6;i++)
    m_SceneTextures[i].Free();

  // Free triggers and barriers
  m_Barrier.Free();
  m_Trigger.Free();

  // Free all non-pc characters
  if((CharPtr=m_CharController.GetParentCharacter()) != NULL) {
    while(CharPtr != NULL) {
      // Remember next character
      NextChar = CharPtr->Next;

      // Remove non-PC character
      if(CharPtr->Type != CHAR_PC)
        m_CharController.Remove(CharPtr);

      // Go to next character
      CharPtr = NextChar;
    }
  }  

  // Free all spell effects
  m_SpellController.Free();

  return TRUE;
}

BOOL cApp::PlaySound(long Num)
{
  if(Num >=0 && Num < NUM_SOUNDS) {
    m_SoundData.Free();

    if(m_SoundData.LoadWAV(g_SoundFilenames[Num]) == TRUE)
      m_SoundChannel.Play(&m_SoundData);

    return TRUE;
  }

  return FALSE;
}

BOOL cApp::PlayMusic(long Num)
{
  // Don't bother changing song if same already playing
  if(g_CurrentMusic == Num)
    return TRUE;

  // Stop and free current song
  m_MusicChannel.Stop();
  m_MusicChannel.Free();

  // Fade music out, giving DirectMusic enough time
  // to finish up last song (or else new song doesn't
  // play correctly.  The 700 is based on play volume
  // of music, so adjust ahead.
  DWORD Timer = timeGetTime() + 700;
  while(timeGetTime() < Timer) {
    DWORD Level = (Timer - timeGetTime()) / 10;
    m_MusicChannel.SetVolume(Level);
  }

  // Load and play new song
  m_MusicChannel.Load(g_MusicFilenames[Num]);
  m_MusicChannel.Play(70,0);

  // Remember new song #
  g_CurrentMusic = Num;

  return TRUE;
}

BOOL cApp::StopMusic()
{
  // Stop and free music, marking current song as none
  m_MusicChannel.Stop();
  m_MusicChannel.Free();
  g_CurrentMusic = -1;

  return TRUE;
}

BOOL cApp::WinGame()
{
  m_StateManager.PopAll(this);
  g_MenuOptions = MENU_LOAD;
  m_StateManager.Push(MenuFrame, this);

  return TRUE;

⌨️ 快捷键说明

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