Populating the sound emitters

Open the Engine.h file and add a new prototype for a populateEmitters function and a new STL vector of Vector2f objects:

   ... 
   ... 
   ... 
   // Run will call all the private functions 
   bool detectCollisions(PlayableCharacter& character); 
 
   // Make a vector of the best places to emit sounds from
   void populateEmitters(vector <Vector2f>& vSoundEmitters,
     int** arrayLevel);

   // A vector of Vector2f for the fire emitter locations
   vector <Vector2f> m_FireEmitters; 
    
public: 
   ... 
   ... 
   ... 

The populateEmitters function takes as a parameter a vector of Vector2f objects, as well as a pointer to int (a two-dimensional array). The vector will hold the location of each emitter in a level and the array is our two-dimensional array, which holds the layout of a level.

Coding the populateEmitters function

The job of the populateEmitters function is to scan through all the elements of arrayLevel and decide where to put the emitters. It will store its results in m_FireEmitters.

Right-click Source Files in the Solution Explorer and select Add | New Item.... In the Add New Item window, highlight (by left-clicking) C++ File (.cpp) and then in the Name field, type PopulateEmitters.cpp. Finally, click the Add button. Now we can code the new function, populateEmitters.

Add the code in its entirety; be sure to study the code as you do, and then we can discuss it:

#include "stdafx.h" 
#include "Engine.h" 
 
using namespace sf; 
using namespace std; 
 
void Engine::populateEmitters( 
   vector <Vector2f>& vSoundEmitters, int** arrayLevel) 
{ 
 
   // Make sure the vector is empty 
   vSoundEmitters.empty(); 
 
   // Keep track of the previous emitter 
   // so we don't make too many 
   FloatRect previousEmitter; 
 
   // Search for fire in the level 
   for (int x = 0; x < (int)m_LM.getLevelSize().x; x++) 
   { 
      for (int y = 0; y < (int)m_LM.getLevelSize().y; y++) 
      { 
         if (arrayLevel[y][x] == 2)// fire is present 
         { 
            // Skip over any fire tiles too  
            // near a previous emitter 
            if (!FloatRect(x * TILE_SIZE, 
               y * TILE_SIZE, 
               TILE_SIZE, 
               TILE_SIZE).intersects(previousEmitter)) 
            { 
               // Add the coordiantes of this water block 
               vSoundEmitters.push_back( 
                  Vector2f(x * TILE_SIZE, y * TILE_SIZE)); 
 
               // Make a rectangle 6 blocks x 6 blocks, 
               // so we don't make any more emitters  
               // too close to this one 
               previousEmitter.left = x * TILE_SIZE; 
               previousEmitter.top = y * TILE_SIZE; 
               previousEmitter.width = TILE_SIZE * 6; 
               previousEmitter.height = TILE_SIZE * 6; 
            } 
 
         } 
 
      } 
 
   } 
   return; 
 
} 

Some of the code might appear complex at first glance. Understanding the technique we use to choose where an emitter will make it simpler. In our levels, there are, regularly, large blocks of fire tiles. In one of the levels I designed there are more than 30 fire tiles together. The code makes sure that there is only one emitter within a given rectangle. This rectangle is stored in previousEmitter and is 300 pixels by 300 pixels (TILE_SIZE * 6).

The code sets up a nested for loop that loops through arrayLevel looking for fire tiles. When it finds one, it makes sure that it does not intersect with previousEmitter. Only then does it use the pushBack function to add another emitter to vSoundEmitters. After doing so, it also updates previousEmitter to avoid getting large clusters of sound emitters.

Let's make some noise.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.135.36