home *** CD-ROM | disk | FTP | other *** search
- /*
- Company: Sensaura
- Copyright: (C) 1999
-
- Software Project: Sensaura DirectSound3D Demo
- File Name: dxworld.cpp
- File Description: Source file for implementation of DirectXWorld class. This is the overall
- control class for all our DirectX world.
- Author: Adam Philp
- File Version: 1.02.000
- Last Update: 10-FEB-99
-
- Target Compiler: Microsoft Visual C++ Version 5.0
- */
-
- /////////////////////// Included files ////////////////////////////////////////////////////////////
-
- #include <windows.h>
-
- #include "dxworld.h" // DirectXWorld class declaration
- #include "dxwldobj.h" // Classes for 3D objects
- #include "sensaura.h" // Sensaura-specific DirectSound functions
- #include "directx.h" // DirectX error handling functions and macros
- #include "resource.h" // Wave audio resources for DirectSound buffers
-
- #include "debug.h"
-
- /////////////////////// Constants /////////////////////////////////////////////////////////////////
-
- const D3DVALUE MAX_SPEED = D3DVAL(25.0);
- const D3DVALUE MAX_TURN = D3DVAL(1.0);
- const D3DVALUE SPEED_STEP = D3DVAL(1.0);
- const D3DVALUE TURN_STEP = D3DVAL(0.1);
- const D3DVALUE ROLLOFF_FACTOR = D3DVAL(0.2);
- const D3DVALUE DOPPLER_FACTOR = D3DVAL(2.0);
- const D3DVALUE MAX_DISTANCE = D3DVAL(200.0);
- const D3DVALUE BACK_DISTANCE = D3DVAL(500.0);
- const D3DVALUE FLOOR_Y = D3DVAL(-2.0);
- const D3DVALUE CAMERA_X = D3DVAL(0);
- const D3DVALUE CAMERA_Y = D3DVAL(0);
- const D3DVALUE CAMERA_Z = D3DVAL(-MAX_DISTANCE/4);
- const D3DVALUE MAX_CAMERA_X = D3DVAL(MAX_DISTANCE/2);
- const D3DVALUE MAX_CAMERA_Y = D3DVAL(10.0);
- const D3DVALUE MAX_CAMERA_Z = D3DVAL(MAX_DISTANCE/2);
-
- const int NUM_SAUCER_WAVS = 3; // Number of different wav resources available available
- const int NUM_METEOR_WAVS = 3; // for each type of 3D object in the game
- const int NUM_EXPLOSIONS = 20;
- const int ID_EXPLOSION_SAUCER = ID_EXPLOSION+ID_SAUCER;
- const int ID_EXPLOSION_METEOR = ID_EXPLOSION+ID_METEOR;
-
- /////////////////////// DirectXWorld class implementation /////////////////////////////////////////
-
- DirectXWorld::DirectXWorld(HINSTANCE hInstance)
- :Direct3DRMObject(BACK_DISTANCE), DirectSound3DObject(hInstance)
- {
- m_hInstance = hInstance;
-
- m_pCamera = NULL;
- m_pView = NULL;
- m_FrameRate = 0;
-
- m_pSaucerBuilder = NULL; // Initialize all pointers to NULL
- m_pMeteorBuilder = NULL;
- m_pBulletBuilder = NULL;
- m_pExplosionBuilder = NULL;
- m_pGlobeBuilder = NULL;
-
- LoadDirectXObjects(); // Pre-load DirectX geometry files
- }
-
- DirectXWorld::~DirectXWorld()
- {
- DestroyObjects();
- ReleaseDirectXObjects(); // Free DirectX geometry files
- }
-
- /*
- Function: Create
- Description: Set up the DirectX base classes which are required to make up our world work,
- then create the objects which are world contains at startup.
- Parameters: hwnd - handle of window to which to attach Direct3DRM and DirectSound object
- hinst - application instance handle
- Return value: true if all objects were successfully created, false otherwise
- */
-
- bool DirectXWorld::Create(HWND hwnd)
- { // Check that parameters passed are OK
- if(hwnd == NULL || m_hInstance == NULL || !DirectXOK())
- return false;
- // Set up windowed Direct3DRM, DirectSound, DirectInput
- if(!Direct3DRMObject::Create(hwnd))
- return false;
- if (!DirectSound3DObject::Create(hwnd))
- return false;
- if (!DirectInputObject::Create(hwnd, m_hInstance))
- return false;
-
- if(!CreateViewer()) // Set up camera, viewport and listener
- return false;
- if(!CreateLights()) // Need some light in our world
- return false;
- if(!CreateEnvironment()) // Set up static objects
- return false;
- m_bFirstUpdate = true;
-
- return Reset(); // Set world variables to startup conditions
- }
-
- /*
- Function: Update
- Description: Update the 3D objects and the viewer. This is the function called by the
- application once the world has been created. The application basically calls
- this function as often as it can until termination.
- Return value: true if all objects were successfully updated, false otherwise
- */
-
- bool DirectXWorld::Update()
- {
- D3DVALUE delta = UpdateTime();
- // It's important to update the Direct3D scene first as
- if(!UpdateScene(delta)) // this takes the lion's share of processor time and must
- return false; // be called at least once before objects are created
- if(!DirectInputObject::Update(&m_dwFlags))
- return false;
- if(!UpdateInput())
- return false;
-
- if(m_bFirstUpdate)
- if(!CreateObjects()) // Create the objects which exist at the beginning of the
- return false; // world
-
- if(!UpdateObjects(delta))
- return false;
- if(!UpdateViewer(delta))
- return false;
-
- m_bFirstUpdate = false;
-
- return true;
- }
-
- /*
- Function: Resize
- Description: Rebuild the windowed Direct3DRM object and the viewport when the user resizes
- the application window
- Parameters: cx - the width of the resized window
- cy - the height of the resized window
- Return value: true if all objects were successfully updated, false otherwise
- */
-
- bool DirectXWorld::Resize(int cx, int cy)
- {
- long lVolume;
-
- TRY_DS(m_pPrimary->GetVolume(&lVolume)) // Mute primary buffer whilst rebuilding device
- TRY_DS(m_pPrimary->SetVolume(DSBVOLUME_MIN))
-
- RELEASE(m_pView) // Destroy the old viewport
- // Rebuild the Direct3DRM device
- if(!Direct3DRMObject::Resize(cx, cy))
- return false;
- // Rebuild the viewport
- TRY_D3DRM(m_pD3DRM->CreateViewport(m_pDevice, m_pCamera, 0, 0, cx, cy, &m_pView))
- TRY_D3DRM(m_pView->SetBack(m_BackDistance))
- TRY_DS(m_pPrimary->SetVolume(lVolume)) // Unmute primary buffer
-
- return true;
-
- DS_ERROR:
- D3DRM_ERROR:
- RELEASE(m_pView)
- return false;
- }
-
- /*
- Function: SetDirectSound
- Description: Cycle through the supplied list of 3D objects and recreate their attached
- sound buffers to reflect the change in our DirectSound type
- Return value: true if all objects were successfully updated, false otherwise
- */
-
- bool DirectXWorld::SetDirectSound(DIRECTSOUND3DTYPE type)
- {
- LPD3DRMNODE pNode;
- LPCSTR pSound;
- // Set the DirectSound type
- if(!DirectSound3DObject::SetDirectSound(type))
- return false;
-
- pNode = m_Objects.m_pHead; // Cycle through the 3D object list
- while(pNode)
- {
- pSound = pNode->pObject->GetSound();
- if(pSound)
- {
- pNode->pObject->DetachSound();
- pNode->pObject->AttachSound(pSound);
- }
- pNode = pNode->pNext;
- }
-
- return true;
- }
-
- /*
- Function: SetSpeakerConfig
- Description: Set the DirectSound speaker configuration
- Parameters: dwConfig - the DirectSound speaker configuration
- Return value: true if speaker configuration was successfully updated, false otherwise
- */
-
- bool DirectXWorld::SetSpeakerConfig(DWORD dwConfig)
- {
- TRY_DS(m_pDS->SetSpeakerConfig(dwConfig))
- return true;
-
- DS_ERROR:
- return false;
- }
-
- bool DirectXWorld::CreateObject(DWORD dwId)
- {
- switch(dwId)
- {
- case ID_GLOBE:
- return CreateGlobe();
-
- default:
- return false;
- }
- }
-
- void DirectXWorld::DestroyObject(DWORD dwId)
- {
- LPD3DRMNODE pNode = m_Objects.First(dwId);
- if(pNode)
- {
- delete pNode->pObject;
- m_Objects.Remove(pNode);
- }
- }
-
- /////////////////////// DirectXWorld private member functions /////////////////////////////////////
-
- /*
- Function: LoadDirectXObjects
- Description: Create mesh builders for the 3D objects in our world
- Return value: true if all objects were successfully loaded, false otherwise
- */
-
- bool DirectXWorld::LoadDirectXObjects()
- {
- ASSERT(!m_pSaucerBuilder);
- ASSERT(!m_pMeteorBuilder);
- ASSERT(!m_pBulletBuilder);
- ASSERT(!m_pExplosionBuilder);
-
- TRY_D3DRM(m_pD3DRM->CreateMeshBuilder(&m_pSaucerBuilder))
- TRY_D3DRM(m_pSaucerBuilder->Load(".\\Objects\\saucer.x", NULL, D3DRMLOAD_FROMFILE, NULL, NULL))
- TRY_D3DRM(m_pSaucerBuilder->SetQuality(m_Quality))
- TRY_D3DRM(m_pD3DRM->CreateMeshBuilder(&m_pMeteorBuilder))
- TRY_D3DRM(m_pMeteorBuilder->Load(".\\Objects\\meteor.x", NULL, D3DRMLOAD_FROMFILE, NULL, NULL))
- TRY_D3DRM(m_pMeteorBuilder->SetQuality(m_Quality))
- TRY_D3DRM(m_pMeteorBuilder->Scale(D3DVAL(0.5), D3DVAL(0.5), D3DVAL(0.5)))
- TRY_D3DRM(m_pD3DRM->CreateMeshBuilder(&m_pBulletBuilder))
- TRY_D3DRM(m_pBulletBuilder->Load(".\\Objects\\bullet.x", NULL, D3DRMLOAD_FROMFILE, NULL, NULL))
- TRY_D3DRM(m_pBulletBuilder->SetQuality(m_Quality))
- TRY_D3DRM(m_pBulletBuilder->Scale(D3DVAL(0.2), D3DVAL(0.2), D3DVAL(0.2)))
- TRY_D3DRM(m_pD3DRM->CreateMeshBuilder(&m_pExplosionBuilder))
- TRY_D3DRM(m_pExplosionBuilder->Load(".\\Objects\\star.x", NULL, D3DRMLOAD_FROMFILE, NULL, NULL))
- TRY_D3DRM(m_pExplosionBuilder->SetQuality(m_Quality))
- TRY_D3DRM(m_pExplosionBuilder->Scale(D3DVAL(0.1), D3DVAL(0.1), D3DVAL(0.1)))
- return true;
-
- D3DRM_ERROR:
- ReleaseDirectXObjects();
- return false;
- }
-
- /*
- Function: ReleaseDirectXObjects
- Description: Free all 3D object data
- */
-
- void DirectXWorld::ReleaseDirectXObjects()
- {
- RELEASE(m_pSaucerBuilder)
- RELEASE(m_pMeteorBuilder)
- RELEASE(m_pBulletBuilder)
- RELEASE(m_pExplosionBuilder)
- RELEASE(m_pGlobeBuilder)
- }
-
- /*
- Function: CreateViewer
- Description: Create Direct3DRM camera and viewport to allow us to see our 3D world. Set
- DirectSound3D listener position to camera position.
- Return value: true if viewer was successfully created, false otherwise
- */
-
- bool DirectXWorld::CreateViewer()
- {
- D3DVECTOR position, front, top;
-
- ASSERT(m_pScene);
- ASSERT(!m_pCamera);
-
- if(!m_pListener)
- return false;
- // Create camera and viewport
- TRY_D3DRM(m_pD3DRM->CreateFrame(m_pScene, &m_pCamera))
- TRY_D3DRM(m_pD3DRM->CreateViewport(m_pDevice, m_pCamera,
- 0, 0, m_pDevice->GetWidth(), m_pDevice->GetHeight(),
- &m_pView))
- TRY_D3DRM (m_pView->SetBack(m_BackDistance))
- // Set listener position and orientation
- TRY_D3DRM(m_pCamera->GetPosition(m_pScene, &position))
- TRY_D3DRM(m_pCamera->GetOrientation(m_pScene, &front, &top))
- TRY_DS(m_pListener->SetPosition(position.x, position.y, position.z, DS3D_DEFERRED))
- TRY_DS(m_pListener->SetOrientation(front.x, front.y, front.z,
- top.x, top.y, top.z, DS3D_DEFERRED))
- TRY_DS(m_pListener->SetRolloffFactor(ROLLOFF_FACTOR, DS3D_DEFERRED))
- TRY_DS(m_pListener->SetDopplerFactor(DOPPLER_FACTOR, DS3D_DEFERRED))
- TRY_DS(m_pListener->CommitDeferredSettings())
- return true;
-
- DS_ERROR:
- D3DRM_ERROR:
- RELEASE(m_pCamera)
- RELEASE(m_pView)
- return false;
- }
-
- /*
- Function: CreateLights
- Description: Create Direct3DRM light objects to allow us to see our 3D world.
- Return value: true if all lights were successfully created, false otherwise
- */
-
- bool DirectXWorld::CreateLights()
- {
- LPDIRECT3DRMLIGHT pLight = NULL;
- bool bCreated = false;
- // Create a light for the camera to illuminate objects as we approach them
- TRY_D3DRM(m_pD3DRM->CreateLightRGB(D3DRMLIGHT_SPOT, 1, 1, 1, &pLight))
- TRY_D3DRM(pLight->SetLinearAttenuation(D3DVAL(0.3)))
- TRY_D3DRM(pLight->SetUmbra(1))
- TRY_D3DRM(pLight->SetPenumbra(2))
- TRY_D3DRM(m_pCamera->AddLight(pLight))
- RELEASE(pLight)
- // Create ambient light source to illuminate everything
- TRY_D3DRM(m_pD3DRM->CreateLightRGB(D3DRMLIGHT_AMBIENT,
- D3DVAL(0.5), D3DVAL(0.5), D3DVAL(0.5),
- &pLight))
- TRY_D3DRM(m_pScene->AddLight(pLight))
- bCreated = true;
-
- D3DRM_ERROR:
- RELEASE(pLight)
- return bCreated;
- }
-
- /*
- Function: CreateEnvironment
- Description: Create the objects which are there but which we don't interact with - floor,
- walls, sky or whatever
- Return value: true if all object were successfully created, false otherwise
- */
-
- bool DirectXWorld::CreateEnvironment()
- {
- return true;
- }
-
- /*
- Function: CreateObjects
- Description: Create the 3D objects which we want when our world starts.
- Return value: true if all object were successfully created, false otherwise
- */
-
- bool DirectXWorld::CreateObjects()
- {
- if(!CreateGlobe())
- return false;
- if(!CreateSaucer()) // Start off with one flying saucer ...
- return false;
- return CreateMeteor(); // ... and one meteor
- }
-
- /*
- Function: Reset
- Description: Set all world parameters to their initial values.
- Return value: true if all objects were successfully reset, false otherwise
- */
-
- bool DirectXWorld::Reset()
- {
- m_dwFlags = 0; // Set camera position and velocity to zero
- m_YVelocity = 0;
- m_ZVelocity = 0;
- m_XTurnVelocity = 0;
-
- TRY_D3DRM(m_pCamera->SetPosition(m_pScene, CAMERA_X, CAMERA_Y, CAMERA_Z))
- TRY_D3DRM(m_pCamera->SetOrientation(m_pScene, 0, 0, 1, 0, 1, 0))
- TRY_D3DRM(m_pCamera->SetVelocity(m_pScene, 0, 0, 0, FALSE))
-
- m_dwTime = timeGetTime();
- return true;
-
- D3DRM_ERROR:
- return false;
- }
-
- /*
- Function: DestroyObjects
- Description: Destroy all the 3D objects in our world.
- */
-
- void DirectXWorld::DestroyObjects()
- {
- while(m_Objects.m_pHead) // m_Objects maintains a list of all 3D objects
- {
- delete m_Objects.m_pHead->pObject;
- m_Objects.RemoveHead();
- }
- }
-
- /*
- Function: CreateGlobe
- Description: Create a new globe object.
- */
-
- bool DirectXWorld::CreateGlobe()
- {
- LPD3DRMOBJECT pObject; // Create globe builder here because it is modified
- // by the D3DRMGlobeObject class
- TRY_D3DRM(m_pD3DRM->CreateMeshBuilder(&m_pGlobeBuilder))
- TRY_D3DRM(m_pGlobeBuilder->Load(".\\Objects\\sphere.x", NULL, D3DRMLOAD_FROMFILE, NULL, NULL))
- TRY_D3DRM(m_pGlobeBuilder->SetQuality(m_Quality))
-
- pObject = new D3DRMGlobeObject(this, &m_pGlobeBuilder, D3DRMOBJECT_SOUNDLOOPING, 0);
- if(!pObject)
- return false;
- if(!pObject->AttachSound(MAKEINTRESOURCE(IDR_WAVE_GLOBE)))
- {
- delete pObject;
- return false;
- }
- m_Objects.Insert(pObject); // Add it to our object list
- // Set its initial position, speed etc.
- return true;
-
- D3DRM_ERROR:
- RELEASE(m_pGlobeBuilder)
- return false;
- }
-
- /*
- Function: CreateSaucer
- Description: Create a new flying saucer object.
- Return value: true if the object was successfully created, false otherwise
- */
-
- bool DirectXWorld::CreateSaucer()
- {
- LPD3DRMOBJECT pObject;
- static int nSaucer = 0;
- // Create the object
- pObject = new D3DRMSaucerObject(this, m_pSaucerBuilder, D3DRMOBJECT_SOUNDLOOPING, 0);
- if(!pObject)
- return false;
- if(!pObject->AttachSound(MAKEINTRESOURCE(IDR_WAVE_SAUCER1+nSaucer)))
- {
- delete pObject;
- return false;
- }
- nSaucer = (nSaucer+1)%NUM_SAUCER_WAVS;
- m_Objects.Insert(pObject); // Add it to our object list
- // Set its initial position, speed etc.
- return true;
- }
-
- /*
- Function: CreateMeteor
- Description: Create a new meteor object.
- Return value: true if the object was successfully created, false otherwise
- */
-
- bool DirectXWorld::CreateMeteor()
- {
- LPD3DRMOBJECT pObject;
- static int nMeteor = 0;
-
- pObject = new D3DRMMeteorObject(this, m_pMeteorBuilder, D3DRMOBJECT_SOUNDLOOPING, 0);
- if(!pObject)
- return false;
- if(!pObject->AttachSound(MAKEINTRESOURCE(IDR_WAVE_METEOR1+nMeteor)))
- {
- delete pObject;
- return false;
- }
- nMeteor = (nMeteor+1)%NUM_METEOR_WAVS;
- m_Objects.Insert(pObject);
- return true;
- }
-
- /*
- Function: CreateExplosion
- Description: Create an explosion made up of several stars objects. One star has the
- explosion sound attached to it.
- Parameters: position - pointer to vector containing position at which to create explosion
- dwId - id of the object which was blown up in order to create this explosion
- Return value: true if the object was successfully created, false otherwise
- */
-
- bool DirectXWorld::CreateExplosion(LPD3DVECTOR position, DWORD dwId)
- {
- LPD3DRMOBJECT pObject;
- int i;
- // Create the star with the attached sound
- pObject = new D3DRMExplosionObject(this, dwId, m_pExplosionBuilder, position,
- D3DRMOBJECT_KILLWITHSOUND, 0);
- if (!pObject)
- return false;
- if(!pObject->AttachSound(MAKEINTRESOURCE(IDR_WAVE_EXPLOSION)))
- {
- delete pObject;
- return false;
- }
- m_Objects.Insert(pObject); // Add it to our object list
-
- for(i = 1; i < NUM_EXPLOSIONS; i++) // Create other star objects
- {
- pObject = new D3DRMExplosionObject(this, dwId+i, m_pExplosionBuilder, position, 0, 0);
- if(!pObject)
- return false;
- m_Objects.Insert(pObject); // Add them to object list
- }
- return true;
- }
-
- /*
- Function: DestroyExplosion
- Description: Destroy and remove from the object list all explosion objects with the supplied
- id value
- Return value: true if the object was successfully created, false otherwise
- */
-
- void DirectXWorld::DestroyExplosion(DWORD dwId)
- {
- LPD3DRMNODE pNode = m_Objects.m_pHead;
-
- while(pNode)
- {
- if(pNode->pObject->GetID() >= dwId && pNode->pObject->GetID() < dwId+NUM_EXPLOSIONS)
- pNode->pObject->Kill();
- pNode = pNode->pNext;
- }
- }
-
- /*
- Function: UpdateTime
- Description: Update the world time. Calculate how much time has elapsed since the last
- update and calculate the frame rate. Use the frame rate to calculate how much
- to advance the game so as to make game speed independent of PC speed
- Return value: Amount indicating how much to advance the Direct3D scene, objects etc.
- */
-
- D3DVALUE DirectXWorld::UpdateTime()
- {
- DWORD dwNewTime = timeGetTime();
- m_FrameRate = 1000/(D3DVAL(dwNewTime-m_dwTime));
- m_dwTime = dwNewTime;
- return D3DVAL(1.0)/m_FrameRate;
- }
-
- /*
- Function: UpdateScene
- Description: Update and render our Direct3DRM world
- Parameters: delta - the time in seconds since the last call to UpdateScene
- Return value: true if everything successfully updated, false otherwise
- */
-
- bool DirectXWorld::UpdateScene(D3DVALUE delta)
- {
- TRY_D3DRM(m_pScene->Move(delta))
- TRY_D3DRM(m_pView->Clear())
- TRY_D3DRM(m_pView->Render(m_pScene))
- TRY_D3DRM(m_pDevice->Update())
- // Calculate the frame rate so that the speed of the game
- return true;
-
- D3DRM_ERROR:
- return false;
- }
-
- /*
- Function: UpdateInput
- Description: Respond to input from the user
- Return value: true successfully updated, false otherwise
- */
-
- bool DirectXWorld::UpdateInput()
- {
- if(m_dwFlags & KF_SPACE) // Fire a bullet
- Fire();
- if(m_dwFlags & KF_UPARROW) // Accelerate forward
- MoveZ(SPEED_STEP);
- else if(m_dwFlags & KF_DOWNARROW) // Accelerate backwards
- MoveZ(-SPEED_STEP);
- else // No forward/backward key pressed
- m_ZVelocity = m_ZVelocity >= SPEED_STEP ? m_ZVelocity-SPEED_STEP :
- m_ZVelocity <= -SPEED_STEP ? m_ZVelocity+SPEED_STEP : 0;
-
- if(m_dwFlags & KF_PAGEUP) // Accelerate up
- MoveY(SPEED_STEP);
- else
- if(m_dwFlags & KF_PAGEDOWN) // Accelerate down
- MoveY(-SPEED_STEP);
- else // No up/down key pressed
- m_YVelocity = m_YVelocity >= SPEED_STEP ? m_YVelocity-SPEED_STEP :
- m_YVelocity <= -SPEED_STEP ? m_YVelocity+SPEED_STEP : 0;
-
- if(m_dwFlags & KF_RIGHTARROW) // Accelerate left turn
- TurnX(TURN_STEP);
- else if(m_dwFlags & KF_LEFTARROW) // Accelerate right turn
- TurnX(-TURN_STEP);
- else // No left/right turn key pressed
- m_XTurnVelocity = m_XTurnVelocity >= TURN_STEP ? m_XTurnVelocity-TURN_STEP :
- m_XTurnVelocity <= -TURN_STEP ? m_XTurnVelocity+TURN_STEP : 0;
- return true;
- }
-
- /*
- Function: UpdateObjects
- Description: Update the status of all the objects in our object list. This function
- controls the progress of all objects that currently exist in our 3D world.
- Parameters: delta - the time in seconds since the last call to UpdateObjects
- Return value: true if all objects were successfully updated, false otherwise
- */
-
- bool DirectXWorld::UpdateObjects(D3DVALUE delta)
- {
- if(!DestroyDeadObjects())
- return false;
- if(!CheckCollisions(delta))
- return false;
- if(!MoveObjects(delta))
- return false;
-
- return true;
- }
-
- /*
- Function: DestroyDeadObjects
- Description: Remove all dead objects from the object list
- Return value: true if all objects were successfully removed, false otherwise
- */
-
- bool DirectXWorld::DestroyDeadObjects()
- {
- LPD3DRMNODE pNode = m_Objects.m_pHead;
- DWORD dwId;
- bool bSaucer = false;
- bool bMeteor = false;
-
- while(pNode) // Cycle through our object list
- {
- if(pNode->pObject->IsDead()) // Remove dead object from list
- { // What kind of object is it
- dwId = pNode->pObject->GetID();
- if(dwId == ID_EXPLOSION_SAUCER)
- bSaucer = true; // Explosion from flying saucer
- if(dwId == ID_EXPLOSION_METEOR)
- bMeteor = true; // Explosion from meteor
-
- delete pNode->pObject;
- pNode = m_Objects.Remove(pNode);
- }
- else
- pNode = pNode->pNext; // Get next object in our list
- }
- // Finished cycling through our object list
- if(bSaucer) // Did a saucer explosion end?
- {
- DestroyExplosion(ID_EXPLOSION_SAUCER);
- CreateSaucer(); // Create a new flying saucer
- }
- if(bMeteor) // Did a meteor explosion end?
- {
- DestroyExplosion(ID_EXPLOSION_METEOR);
- CreateMeteor(); // Create a new meteor
- }
- return true;
- }
-
- /*
- Function: CheckCollisions
- Description: Check whether any objects have collided with each other and take appropriate
- action depending on the object type
- Parameters: delta - the time in seconds since the last call to CheckCollisions
- Return value: true if all objects were successfully checked, false otherwise
- */
-
- bool DirectXWorld::CheckCollisions(D3DVALUE delta)
- {
- LPD3DRMOBJECT pObject;
- LPD3DRMNODE pNode = m_Objects.m_pHead;
- DWORD dwId;
- bool bHitCamera;
- LPD3DRMNODE pHitObject;
-
- while(pNode) // Cycle through our object list
- {
- pObject = pNode->pObject; // Get the 3D object
- dwId = pObject->GetID(); // Get the type of 3D object
- // Determine whether the object hit us
- bHitCamera = HitCamera(pObject, delta);
- pHitObject = HitObject(pObject, delta);
-
- switch(dwId) // What happens to an object in the event of a collision
- { // depends on what it is ...
- case ID_GLOBE:
- break;
-
- case ID_SAUCER:
- case ID_METEOR:
- break;
-
- case ID_BULLET:
- if(pHitObject) // Ooh, our bullet hit something
- {
- DWORD dwHitId = pHitObject->pObject->GetID();
- if(dwHitId == ID_SAUCER || dwHitId == ID_METEOR)
- {
- D3DVECTOR p;
-
- pHitObject->pObject->m_pFrame->GetPosition(m_pScene, &p);
- pHitObject->pObject->Kill();
- pObject->Kill();
- if(!CreateExplosion(&p, dwHitId))
- return false;
- }
- }
- break;
- }
- pNode = pNode->pNext; // Get next object in our list
- }
- return true;
- }
-
- /*
- Function: MoveObjects
- Description: Update the positions and velocities of all the objects in our object list
- Parameters: delta - the time in seconds since the last call to MoveObjects
- Return value: true if all objects were successfully moved, false otherwise
- */
-
- bool DirectXWorld::MoveObjects(D3DVALUE delta)
- {
- LPD3DRMOBJECT pObject;
- LPD3DRMNODE pNode = m_Objects.m_pHead;
-
- while(pNode) // Cycle through our object list
- {
- pObject = pNode->pObject; // Get the 3D object
- pObject->Update(delta); // Update the 3D object's position, velocity etc.
- pNode = pNode->pNext; // Get next object in our list
- }
- return true;
- }
-
- /*
- bool DirectXWorld::UpdateObjects(D3DVALUE delta)
- {
- LPD3DRMOBJECT pObject;
- LPD3DRMNODE pNode = m_Objects.m_pHead;
- bool bDead;
- DWORD dwId, dwIdExplosion = 0;
-
-
- while(pNode) // Cycle through our object list
- {
- pObject = pNode->pObject; // Get the 3D object
- pObject->Update(delta); // Update the 3D object's position, velocity etc.
- dwId = pObject->GetID(); // Get the type of 3D object
- bDead = pObject->IsDead(); // Should the object be destroyed?
- // switch(dwId) // What happens to an object depends on what it is ...
- {
- }
- if(bDead)
- { // Remove this object from the list and destroy it
- delete pNode->pObject;
- pNode = m_Objects.Remove(pNode);
- }
- else
- pNode = pNode->pNext; // Get next object in our list
- }
- return true;
- }*/
-
- /*
- Function: UpdateViewer
- Description: Update the status of our view of the world. This function moves the camera and
- the listener and responds to user actions.
- Parameters: delta - the time in seconds since the last call to UpdateViewer
- Return value: true if everything successfully updated, false otherwise
- */
-
- bool DirectXWorld::UpdateViewer(D3DVALUE delta)
- {
- D3DVECTOR p, v;
- D3DVECTOR front, up, right;
- // Get the camera position and orientation
- TRY_D3DRM(m_pCamera->GetPosition(m_pScene, &p))
- TRY_D3DRM(m_pCamera->GetOrientation(m_pScene, &front, &up))
- D3DRMVectorCrossProduct(&right, &up, &front);
- // Update the camera velocity
- v.x = m_ZVelocity*front.x+m_YVelocity*up.x;
- v.y = m_ZVelocity*front.y+m_YVelocity*up.y;
- v.z = m_ZVelocity*front.z+m_YVelocity*up.z;
- // We've reached the edge of our 3D world
- if((p.x > MAX_CAMERA_X && v.x > 0) || (p.x < -MAX_CAMERA_X && v.x < 0) ||
- (p.z > MAX_CAMERA_Z && v.z > 0) || (p.z < -MAX_CAMERA_Z && v.z < 0))
- { // Dead stop in horizontal plane
- v.x = 0;
- v.z = 0;
- m_ZVelocity = 0;
- }
- if((p.y > MAX_CAMERA_Y && v.y > 0) || (p.y < -MAX_CAMERA_Y && v.y < 0))
- { // Dead stop in vertical plane
- v.y = 0;
- m_YVelocity = 0;
- }
-
- TRY_D3DRM(m_pCamera->SetVelocity(m_pScene, v.x, v.y, v.z, FALSE))
- TRY_D3DRM(m_pCamera->SetRotation(m_pScene, up.x, up.y, up.z, m_XTurnVelocity))
-
- if(m_pListener) // Update the 3D listener object to match the camera
- {
- TRY_DS(m_pListener->SetPosition(p.x, p.y, p.z, DS3D_DEFERRED))
- TRY_DS(m_pListener->SetVelocity(m_ZVelocity*front.x+m_YVelocity*up.x,
- m_ZVelocity*front.y+m_YVelocity*up.y,
- m_ZVelocity*front.z+m_ZVelocity*up.z,
- DS3D_DEFERRED))
- TRY_DS(m_pListener->SetOrientation(front.x, front.y, front.z,
- up.x, up.y, up.z, DS3D_DEFERRED))
- TRY_DS(m_pListener->CommitDeferredSettings())
- }
- return true;
-
- DS_ERROR:
- D3DRM_ERROR:
- return false;
- }
-
- /*
- Function: MoveY
- Description: Update the viewer's vertical velocity
- Parameters: step - amount by which to change velocity
- */
-
- void DirectXWorld::MoveY(D3DVALUE step)
- {
- m_YVelocity += step;
- if(m_YVelocity > MAX_SPEED) // Limit vertical velocity to +/-MAX_SPEED
- m_YVelocity = MAX_SPEED;
- else
- if(m_YVelocity < -MAX_SPEED)
- m_YVelocity = -MAX_SPEED;
- }
-
- /*
- Function: MoveZ
- Description: Update the viewer's forward velocity
- Parameters: step - amount by which to change velocity
- */
-
- void DirectXWorld::MoveZ(D3DVALUE step)
- {
- m_ZVelocity += step;
- if(m_ZVelocity > MAX_SPEED) // Limit forward velocity to +/-MAX_SPEED
- m_ZVelocity = MAX_SPEED;
- else
- if(m_ZVelocity < -MAX_SPEED)
- m_ZVelocity = -MAX_SPEED;
- }
-
- /*
- Function: MoveZ
- Description: Update the viewer's left/right turn rate
- Parameters: step - amount by which to change turn rate
- */
-
- void DirectXWorld::TurnX(D3DVALUE step)
- {
- m_XTurnVelocity += step;
- if(m_XTurnVelocity > MAX_TURN) // Limit turn rate to +/-MAX_TURN
- m_XTurnVelocity = MAX_TURN;
- else
- if(m_XTurnVelocity < -MAX_TURN)
- m_XTurnVelocity = -MAX_TURN;
- }
-
- /*
- Function: Fire
- Description: Create a new bullet object
- Return value: true if bullet successfully created, false otherwise
- */
-
- bool DirectXWorld::Fire()
- {
- LPD3DRMOBJECT pObject;
- static DWORD dwLastTime = 0;
-
- if(timeGetTime() < dwLastTime+500) // Time required for bullet sound buffer to become
- return false; // available again
-
- pObject = new D3DRMBulletObject(this, m_pBulletBuilder,
- D3DRMOBJECT_MORTAL|D3DRMOBJECT_DONTMOVESOUND, 1500);
- if(!pObject)
- return false;
- if(!pObject->AttachSound(MAKEINTRESOURCE(IDR_WAVE_BULLET)))
- {
- delete pObject;
- return false;
- }
- dwLastTime = timeGetTime();
- m_Objects.Insert(pObject);
- return true;
- }
-
- /*
- Function: HitCamera
- Description: Determine whether the supplied object has collided with the camera. If it has,
- reverse the camera's velocity
- Parameters: pObject - pointer to the object to check
- delta - time of travel for the object
- Return value: true if the object did collide with the camera, false otherwise
- */
-
- bool DirectXWorld::HitCamera(LPD3DRMOBJECT pObject, D3DVALUE delta)
- {
- D3DVECTOR p, v;
-
- if(pObject->Collided(m_pCamera, delta))
- { // Reverse velocity of camera as if bouncing off object
- TRY_D3DRM(m_pCamera->GetPosition(pObject->m_pFrame, &p))
- TRY_D3DRM(m_pCamera->GetVelocity(pObject->m_pFrame, &v, FALSE))
- TRY_D3DRM(m_pCamera->SetVelocity(pObject->m_pFrame, -v.x, -v.y, -v.z, FALSE))
- m_ZVelocity = -m_ZVelocity;
- return true;
- }
- D3DRM_ERROR:
- return false;
- }
-
- /*
- Function: HitObject
- Description: Determine whether the supplied object has collided with another object in our
- world
- Parameters: pObject - pointer to the object to check
- delta - time of travel for the object
- Return value: Pointer to the object with which the supplied object collided or NULL
- */
-
- LPD3DRMNODE DirectXWorld::HitObject(LPD3DRMOBJECT pObject, D3DVALUE delta)
- {
- LPD3DRMNODE pNode;
-
- pNode = m_Objects.m_pHead;
- while(pNode) // Cycle through our object list
- {
- if(pNode->pObject != pObject) // Don't check whether object hit itself
- {
- if(pNode->pObject->Collided(pObject->m_pFrame, delta))
- break; // We hit something
- }
- pNode = pNode->pNext;
- }
- return pNode;
- }
-