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

📄 ccontroller.cpp

📁 基于遗传算法的飞船游戏
💻 CPP
字号:
#include "CController.h"

//number of stars
const int NumStars = 20;

//this defines the vertices for the lander shape
const int	 NumPadVerts = 4;

const SPoint Pad[NumPadVerts] = {SPoint(-20, 0),
                                 SPoint(20, 0),
                                 SPoint(20, 5),
                                 SPoint(-20, 5)};
                                      

//-----------------------------ctor---------------------------------------
//
//------------------------------------------------------------------------
CController::CController(int cxClient,
                         int cyClient):m_bFastRender(false),
                                       m_bShowFittest(false),
                                       m_bSuccess(false),
                                       m_iGeneration(0),
                                       m_cxClient(cxClient),
                                       m_cyClient(cyClient),
                                       m_iFittest(0)
                                       
{
   //setup the GA
  m_pGA = new CgaLander(CROSSOVER_RATE,
                         MUTATION_RATE,
                         POP_SIZE,
                         CHROMO_LENGTH,
                         cxClient,
                         cyClient);

  //grab the genomes
  m_vecPop = m_pGA->GrabPop();

  //create a starting postion for the landers
  SVector2D vStartPos = SVector2D(RandFloat()*cxClient, cyClient-50);

  //and the landing pad
  m_vPadPos = SVector2D(50 + RandFloat() * (m_cxClient-100), 50);

  //create the landers and insert their genomes
  for (int i=0; i<POP_SIZE; ++i)
  {
    m_vecLanders.push_back(CLander(cxClient, cyClient, PI, vStartPos, m_vPadPos));

    m_vecLanders[i].Decode(m_vecPop[i].vecActions);
  }

  //set up the VB for the landing pad
  for (i=0; i<NumPadVerts; ++i)
  {
    m_vecPadVB.push_back(Pad[i]);
  }

  //setup the stars
  for (i=0; i<NumStars; ++i)
  {
    m_vecStarVB.push_back(SPoint(RandInt(0, cxClient), RandInt(100, cyClient)));
  }

}
//------------------------------- NewRun ---------------------------------
//
//  reinitializes all the variables for a new run
//------------------------------------------------------------------------
void CController::NewRun()
{
  //delete the old GA and create a new population of genomes
  if (m_pGA)
  {
    delete m_pGA;
  }

  m_pGA = new CgaLander(CROSSOVER_RATE,
                         MUTATION_RATE,
                         POP_SIZE,
                         CHROMO_LENGTH,
                         m_cxClient,
                         m_cyClient);

    //grab the genomes
  m_vecPop = m_pGA->GrabPop();
  
  //change position of landing pad
  m_vPadPos = SVector2D(50 + RandFloat() * (m_cxClient-100), 50);

  //insert the landers genomes
  for (int i=0; i<POP_SIZE; ++i)
  {
    m_vecLanders[i].Reset(m_vPadPos);

    m_vecLanders[i].Decode(m_vecPop[i].vecActions);
  }

  m_iGeneration = 0;
  m_iFittest    = 0;
  m_bSuccess    = false;
}

//-----------------------Render--------------------------------------
//
//	given a GDI surface this function renders the ship and the
//	landing pad
//-------------------------------------------------------------------
void CController::Render(HDC &surface)
{

  //change the mapping mode so that the origin is at the bottom left
  //of our window and so that the y axis increases as it goes from
  //bottom to top     
  SetMapMode( surface, MM_ANISOTROPIC );
  SetViewportExtEx( surface, 1, -1, NULL );
  SetWindowExtEx( surface, 1, 1, NULL );
  SetViewportOrgEx( surface, 0, m_cyClient, NULL );   
  
  //select in the pen we want to use
  HPEN OldPen = (HPEN)SelectObject(surface, GetStockObject(WHITE_PEN));

  //first render the stars
  for (int i=0; i<m_vecStarVB.size(); ++i)
  {
    //make them twinkle
    if (RandFloat() > 0.1)
    {
      SetPixel(surface, m_vecStarVB[i].x, m_vecStarVB[i].y, RGB(255, 255, 255));
    }
  }
  
  if(!m_bShowFittest)
  {
    //render all landers
    for (int i=0; i<m_vecLanders.size(); ++i)
    {
      m_vecLanders[i].Render(surface);
    }
  }

  else
  {
    //just render the best this generation
    m_vecLanders[m_iFittest].Render(surface);
  }
 
  //render the landing pad
  RenderLandingPad(surface);

  //return the mapping mode to its default state so text is rendered
  //correctly
  SetMapMode( surface, MM_ANISOTROPIC );
  SetViewportExtEx( surface, 1, 1, NULL );
  SetWindowExtEx( surface, 1, 1, NULL );
  SetViewportOrgEx( surface, 0, 0, NULL );

  //Render additional information
  SetBkMode(surface, TRANSPARENT);
  SetTextColor(surface, RGB(0,0,255));
  
	string s = "Generation: " + itos(m_iGeneration);
	TextOut(surface, 5, 2, s.c_str(), s.size());


  s = "F-Toggle Fast Render";
	TextOut(surface, 250, m_cyClient-15, s.c_str(), s.size());

  s = "B-Show Fittest";
	TextOut(surface, 5, m_cyClient-15, s.c_str(), s.size());

  s = "R-Reset";
	TextOut(surface, 150, m_cyClient-15, s.c_str(), s.size());


    //replace the pen
  SelectObject(surface, OldPen);
}
//----------------------------- RenderLandingPad ------------------------
//
//  Does exactly that
//-----------------------------------------------------------------------
void CController::RenderLandingPad(HDC &surface)
{
    //create a temp buffer
  vector<SPoint> PadVB = m_vecPadVB;

  //transform the vertices
  WorldTransform(PadVB);

  //draw the lines which describe the landing pad
  MoveToEx(surface, (int)PadVB[0].x, (int)PadVB[0].y, NULL);

  for (int vert=1; vert<4; ++vert)
	{
		LineTo(surface, (int)PadVB[vert].x, (int)PadVB[vert].y);
	}

  LineTo(surface, (int)PadVB[0].x, (int)PadVB[0].y);
}

//---------------------WorldTransform--------------------------------
//
//	sets up the translation matrices for the landing pad and applies
//  the world transform to the pads vertex buffer
//-------------------------------------------------------------------
void CController::WorldTransform(vector<SPoint> &pad)
{
	//create a transformation matrix
	C2DMatrix matTransform;
	
	//and translate
	matTransform.Translate(m_vPadPos.x, m_vPadPos.y);
	
  //now transform the pads vertices
  matTransform.TransformSPoints(pad);

}
//------------------------------- Update ---------------------------------
//
//------------------------------------------------------------------------
bool CController::Update()
{

  //if number of generations exceeds a predifined maximum before
  //finding a solution restart the GA
  if (m_iGeneration > MAX_GENERATIONS_ALLOWED)
  {
    NewRun();
  }

  //this is set if all the landers have finished performing all their
  //actions
  static bool bAllFinished = false;

  if (!bAllFinished)
  {
     bAllFinished = true;
     
     //for each lander
     for (int lndr=0; lndr<POP_SIZE; ++lndr)
     {
       //update the lander's position. 
       if (m_vecLanders[lndr].UpdateShip())
       {
         //the ship still has actions to perform so we set this to 
         //false in order for the loop to continue
         bAllFinished = false;
       }
     }

   }

   else
   {
     m_iFittest = 0;
     double BestScoreSoFar = 0;
       
     //grab the updated fitness scores and insert into the GA
     for (int lndr=0; lndr<POP_SIZE; ++lndr)
     {
       m_vecPop[lndr].dFitness = m_vecLanders[lndr].Fitness();

       //keep a track of the fittest lander each generation
       if (m_vecPop[lndr].dFitness > BestScoreSoFar)
       {
         BestScoreSoFar = m_vecPop[lndr].dFitness;

         m_iFittest = lndr;
       }

       //check for success
       if ( (m_vecPop[lndr].dFitness >= BIG_NUMBER) && !m_bSuccess)
       {
         m_bSuccess = true;

         Success();
       }

       //reset the landers
       m_vecLanders[lndr].Reset(m_vPadPos);
     }

     //reset finished flag
     bAllFinished = false;

     //only perform an Epoch of the GA if we haven't been successful
     //in producing a ship which can land
     if (!m_bSuccess)
     {
       //insert the genomes back into the GA and get a new population
        m_pGA->UpdatePop(m_vecPop);

        //put the new genomes back into the lander population
        for (lndr=0; lndr<POP_SIZE; ++lndr)
        {
          m_vecLanders[lndr].Decode(m_vecPop[lndr].vecActions);
        }

        //increment the generation counter
        m_iGeneration++; 
     }
   
   
  }//end else

  return true;
}
//-------------------------- Success --------------------------------
//
//  if a ship lands this sets the appropriate flags so we may view it
//  and plays a soundfile
//-------------------------------------------------------------------
void CController::Success()
{
  //make sure rendering toggles are set so we can see the successful
  //ship land in all its graceful glory
  if (!m_bShowFittest)
  {
    m_bShowFittest = true;
  }

  if (m_bFastRender)
  {
    m_bFastRender = false;
  }
  
  //play one of two victory wavs
  if (RandBool())
  {
    PlaySound("landed.wav", NULL, SND_ASYNC|SND_FILENAME);
  }
  else
  {
    PlaySound("leap.wav", NULL, SND_ASYNC|SND_FILENAME);
  }
           
   MessageBox(NULL, "Landed! Press OK to view", "Success", 0);
}

//----------------------- ToggleShowFittest ----------------------------
//
//  setting this means that we only render the fittest member of each
//  generation. Plays an appropriate sound file.
//----------------------------------------------------------------------
void CController::ToggleShowFittest()
{
  m_bShowFittest = !m_bShowFittest;
    
  if (m_bShowFittest)
  {
    PlaySound("view_best.wav", NULL, SND_ASYNC|SND_FILENAME);
  }
}

⌨️ 快捷键说明

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