Logo Search packages:      
Sourcecode: race version File versions

emitter_controller.cpp

#include <ClanLib/core.h>
#include <ClanLib/display.h>
#include <vector>
#include <cmath>

#include "pixel.h"
#include "emitter_controller.h"
#include "emitter.h"

EmitterController::EmitterController()
{
      active = false;
}

void EmitterController::add_emitters( CL_Surface *sur, int sur_x, int sur_y )
{
      int x = 0;
      int y = 0;

      /* 
       * calculating the particle emitters position and direction
       * ---------------------------------------------------------
       * 
       * First we need the direction coefficient for a tangent to the surface.
       * That we get by calculating a lines equation that is approximately on the
       * edge of the surface. Then we calculate the tangents normal to get the particles
       * to be emitted in a 90 deg angle from the surface in every point.
       * 
       * We get the posititons of the emitters by checking where the opaque area begins.
       * Starting from 0, 0 of the surface we add points with 'n' pixel intervalls. First left
       * to right, then up-down, left-right and down-up.
       * 
       * Then check where the points are close to eachother and calc a normal to the line that can
       * be drawn trough the two points.
       * 
       * Then find out the angle between the normal and the x-axis. That's the angle the particles
       * will finally be emitted in...
       * 
       * Or something like that... I'm not really a math kinda guy :-)
       */

      // this is a bit ugly but I'm too lazy to clean it up :-Q 

      std::vector<int> lr_ex;  // left-right emitter x 
      std::vector<int> lr_ey;  // left-right emitter y
      std::vector<Pixel> l_pixels;

      std::vector<int> rl_ex;  // left-right emitter x 
      std::vector<int> rl_ey;  // left-right emitter y
      std::vector<Pixel> r_pixels;

      int height = sur->get_height();
      int width  = sur->get_width();

      float red, green, blue, alpha;

      CL_SurfaceProvider *provider = sur->get_provider();

      // ---> left to right edge detect --->

      provider->lock();

      for( y=0; y < height; y+=3 )
      {
            for( x=0; x < width; x++ )
            {
                  provider->get_pixel( x, y, &red, &green, &blue, &alpha );
                  
                  if( alpha > 0.9 )
                  {
                        // the first semi opaque pixel on the line will get an emittor
                        
                        lr_ex.push_back( sur_x + x );
                        lr_ey.push_back( sur_y + y );
                  
                        Pixel p( red, green, blue, alpha );
                        l_pixels.push_back( p );
                        break;
                  }
            }
      }



      // <--- right to left edge detect <---

      provider->lock();

      for( y=1; y < height; y+=2 )
      {
            for( x=width; x > 0; x-- )
            {
                  provider->get_pixel( x, y, &red, &green, &blue, &alpha );
                  
                  if( alpha > 0.3 )
                  {
                        rl_ex.push_back( sur_x + x );
                        rl_ey.push_back( sur_y + y );
                  
                        Pixel p( red, green, blue, alpha );
                        r_pixels.push_back( p );
                        break;
                  }
            }
      }




      provider->unlock();

      int size = lr_ex.size();
      
      std::cout << "number of emitters on left side:" << lr_ex.size() << std::endl;

      int a = 0;
      while( a + 2 < size )
      {
            int pos1_x = lr_ex[a];
            int pos1_y = lr_ey[a];
      
            int pos2_x = lr_ex[a+1];
            int pos2_y = lr_ey[a+1];

            int pos3_x = lr_ex[a+2];
            int pos3_y = lr_ey[a+2];

            // normal between points generated in the left->right edge detect
      
            float normal = -1 * ( (pos3_x - pos1_x)/(pos3_y - pos1_y) );

            float angle = atan( normal );
      
            emitters.push_back( new Emitter( pos2_x, pos2_y, M_PI + angle, l_pixels[a+1], this ) );
            a++;
      }
      
      // right side...
      
      size = rl_ex.size();
      a = 0;
      while( a + 2 < size )
      {
            int pos1_x = rl_ex[a];
            int pos1_y = rl_ey[a];
      
            int pos2_x = rl_ex[a+1];
            int pos2_y = rl_ey[a+1];

            int pos3_x = rl_ex[a+2];
            int pos3_y = rl_ey[a+2];

            // normal between points generated in the left->right edge detect
      
            float normal = -1 * ( (pos3_x - pos1_x)/(pos3_y - pos1_y) );

            float angle = atan( normal );
      
            emitters.push_back( new Emitter( pos2_x, pos2_y, angle, r_pixels[a+1], this ) );
            a++;
      }
       
       
}




void EmitterController::update( float time_elapsed )
{
      std::vector<Emitter*>::iterator it;

      for( it = emitters.begin();
             it != emitters.end();
             it++)
      {
            (*it)->update( time_elapsed );
      }
}



Generated by  Doxygen 1.6.0   Back to index