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

📄 calien.cpp

📁 游戏开发人工智能技术 很好的一本书 讲解游戏中的人工智能技术 希望大家喜欢 ps 英文原版
💻 CPP
字号:
#include "CAlien.h"



//the vertices making up its shape
const int NumAlienVerts = 19;
const SPoint Alien[NumAlienVerts] = { SPoint(1,3),
                                      SPoint(4,1),
                                      SPoint(4,-1),
                                      SPoint(2,-4),
                                      SPoint(1,-1),
                                      SPoint(0,-2),
                                      SPoint(-1,-1),
                                      SPoint(-2,-4),
                                      SPoint(-4,-1),
                                      SPoint(-4,1),
                                      SPoint(-1,3),

                                      SPoint(-2,1),
                                      SPoint(-1.5,0.5),
                                      SPoint(-2,0),
                                      SPoint(-2.5,1),

                                      SPoint(2,1),
                                      SPoint(1.5,0.5),
                                      SPoint(2,0),
                                      SPoint(2.5,1)};




//--------------------------------- ctor ---------------------------------
//
//------------------------------------------------------------------------
CAlien::CAlien(): m_dScale(CParams::dAlienScale),
                  m_vVelocity(SVector2D(0, 0)),
                  m_dMass(CParams::dAlienMass),
                  m_iAge(0),
                  m_bWarning(false)
{ 
  //set its position
  m_vPos = SVector2D(RandInt(0, CParams::WindowWidth), CParams::WindowHeight);
  
  //create the vertex buffer
  for (int i=0; i<NumAlienVerts; ++i)
  {
    m_vecAlienVB.push_back(Alien[i]);
  }

  //setup its bounding box
  m_AlienBBox.left  = m_vPos.x - (4*CParams::dAlienScale);
  m_AlienBBox.right = m_vPos.x + (4*CParams::dAlienScale);
  m_AlienBBox.top   = m_vPos.y + (3*CParams::dAlienScale);
  m_AlienBBox.bottom= m_vPos.y - (4*CParams::dAlienScale);

}


//------------------------------ Render ----------------------------------
void CAlien::Render(HDC &surface, HPEN &GreenPen, HPEN &RedPen)
{
  //transform the vertices
  WorldTransform();

  //select in green pen
  HPEN OldPen = (HPEN)SelectObject(surface, GreenPen);
 
  //draw body
  MoveToEx(surface, m_vecAlienVBTrans[0].x, m_vecAlienVBTrans[0].y, NULL);

  for (int vtx=0; vtx<11; ++vtx)
  {
    LineTo(surface, m_vecAlienVBTrans[vtx].x, m_vecAlienVBTrans[vtx].y);
  }

  LineTo(surface, m_vecAlienVBTrans[0].x, m_vecAlienVBTrans[0].y);

  //select in red pen
  SelectObject(surface, RedPen);
  
  //left eye
  MoveToEx(surface, m_vecAlienVBTrans[11].x, m_vecAlienVBTrans[11].y, NULL);

  for (vtx=12; vtx<15; ++vtx)
  {
    LineTo(surface, m_vecAlienVBTrans[vtx].x, m_vecAlienVBTrans[vtx].y);
  }

  //right eye
  MoveToEx(surface, m_vecAlienVBTrans[15].x, m_vecAlienVBTrans[15].y, NULL);

  for (vtx=16; vtx<19; ++vtx)
  {
    LineTo(surface, m_vecAlienVBTrans[vtx].x, m_vecAlienVBTrans[vtx].y);
  }


  //replace the old pen
  SelectObject(surface, OldPen);

  //display warning if a problem with the network
  if (m_bWarning)
  {
    string s = "Wrong amount of inputs!";
	  TextOut(surface, 110, 200, s.c_str(), s.size());
  }

}


//---------------------WorldTransform--------------------------------
//
//	sets up the translation matrices for the ship and applies the
//	world transform to the ships vertex buffer
//-------------------------------------------------------------------
void CAlien::WorldTransform()
{
	//copy the original vertices into the buffer about to be transformed
  m_vecAlienVBTrans = m_vecAlienVB;
  
  //create a transformation matrix
	C2DMatrix matTransform;
	
	//scale
	matTransform.Scale(m_dScale, m_dScale);

	//and translate
	matTransform.Translate(m_vPos.x, m_vPos.y);
	
  //now transform the ships vertices
  matTransform.TransformSPoints(m_vecAlienVBTrans);
}

//----------------------------- GetActionFromNetwork ---------------------
//
//  this function updates the neural net and returns the action the 
//  network selects as its output
//------------------------------------------------------------------------
action_type CAlien::GetActionFromNetwork(const vector<CBullet> &bullets,
                                         const SVector2D       &GunPos)
{
  //the inputs into the net 
  vector<double> NetInputs;

  //This will hold the outputs from the neural net
  static vector<double> outputs(0,3);

  //add in the vector to the gun turret
  int XComponentToTurret = GunPos.x - m_vPos.x;
  int YComponentToTurret = GunPos.y - m_vPos.y;

  NetInputs.push_back(XComponentToTurret);
  NetInputs.push_back(YComponentToTurret);

  //now any bullets
  for (int blt=0; blt<bullets.size(); ++blt)
  {
    if (bullets[blt].Active())
    {
      
      double xComponent = bullets[blt].Pos().x - m_vPos.x;
      double yComponent = bullets[blt].Pos().y - m_vPos.y;

      NetInputs.push_back(xComponent);
      NetInputs.push_back(yComponent);
    }

    else
    {
      //if a bullet is innactive just input the vector to
      //the gun turret
      NetInputs.push_back(XComponentToTurret);
      NetInputs.push_back(YComponentToTurret);
    }
  }

  //feed the inputs into the net and get the outputs
  outputs = m_ItsBrain.Update(NetInputs);

  //this is set if there is a problem with the update
  if (outputs.size() == 0)
  {
     m_bWarning = true;
  }

  //determine which action is valid this frame. The highest valued
  //output over 0.9. If none are over 0.9 then just drift with
  //gravity
  double BiggestSoFar = 0;

  action_type action = drift;

  for (int i=0; i<outputs.size(); ++i)
  {
    if( (outputs[i] > BiggestSoFar) && (outputs[i] > 0.9))
    {
      action = (action_type)i;
      
      BiggestSoFar = outputs[i];
    }
  }

  return action;
}


//----------------------------- Update -----------------------------------
//
//  Checks for user keypresses and updates the aliens parameters accordingly
//------------------------------------------------------------------------
bool CAlien::Update(vector<CBullet> &bullets,const SVector2D &GunPos)
{
  //update age
  ++m_iAge;

  //get the next action from the neural network
  int action = GetActionFromNetwork(bullets, GunPos);

  //switch on the action
  switch(action)
  {
  case thrust_left:
    {
      m_vVelocity.x -= CParams::dMaxThrustLateral/m_dMass;
    }

    break;

  case thrust_right:
    {
      m_vVelocity.x += CParams::dMaxThrustLateral/m_dMass;
    }

    break;

  case thrust_up:
    {
      m_vVelocity.y += CParams::dMaxThrustVertical/m_dMass;
    }

    break;

    default:break;
  }

  //add in gravity
  SVector2D gravity(0, CParams::dGravityPerTick); 
                                                         
  m_vVelocity += gravity;

  //clamp the velocity of the alien
  Clamp(m_vVelocity.x, -CParams::dMaxVelocity, CParams::dMaxVelocity);
  Clamp(m_vVelocity.y, -CParams::dMaxVelocity, CParams::dMaxVelocity);
  
  //update the alien's position
	m_vPos += m_vVelocity;

  //wrap around window width 
  if (m_vPos.x < 0)
  {
    m_vPos.x = CParams::WindowWidth;
  }

  if (m_vPos.x > CParams::WindowWidth)
  {
    m_vPos.x = 0;
  }

  //update the bounding box 
  m_AlienBBox.left  = m_vPos.x - (4*CParams::dAlienScale);
  m_AlienBBox.right = m_vPos.x + (4*CParams::dAlienScale);
  m_AlienBBox.top   = m_vPos.y + (3*CParams::dAlienScale);
  m_AlienBBox.bottom= m_vPos.y - (4*CParams::dAlienScale);

  //an alien dies if it drops below the gun, flys too high
  //or is hit by a bullet
  if ( (m_vPos.y > (CParams::WindowHeight + 5)) ||
       (m_vPos.y < 15)                          || 
       CheckForCollision(bullets))
  {   
    return false;
  }
      
  return true;
}


//------------------------- CheckForCollision ---------------------------
//
//  tests the aliens bounding box against each bullet's bounding box.
//  returns true if a collision is detected
//-----------------------------------------------------------------------
bool CAlien::CheckForCollision(vector<CBullet> &bullets)const
{
  //for each bullet  
  for (int blt=0; blt<bullets.size(); ++blt)
  {
    //if bullet is not active goto next bullet
    if (!bullets[blt].Active())
    {
      continue;
    }
    
    RECT blts = bullets[blt].BBox();

    //test for intersection between bounding boxes
    if (!((blts.bottom > m_AlienBBox.top) ||
          (blts.top < m_AlienBBox.bottom) ||
          (blts.left > m_AlienBBox.right) ||
          (blts.right < m_AlienBBox.left)))
    {
      bullets[blt].SwitchOff();
      
      return true;
    }
  }

  return false;
}


//--------------------------------- Reset --------------------------------
//
//------------------------------------------------------------------------
void CAlien::Reset()
{
  m_iAge      = 0;
  m_vVelocity = SVector2D(0, 0);
  m_vPos      = SVector2D(RandInt(0, CParams::WindowWidth), CParams::WindowHeight);
}


//------------------------------ mutate ----------------------------------
//
//  mutates the connection weights in the alien's neural network.
//------------------------------------------------------------------------
void CAlien::Mutate()
{

  //grab the weights for the neural net
  vector<double> weights = m_ItsBrain.GetWeights();

  //mutate them
  for (int w=0; w<weights.size(); ++w)
  {
    //do we perturb this weight?
    if (RandFloat() < CParams::dMutationRate)
		{
			//add a small value to the weight
			weights[w] += (RandomClamped() * CParams::dMaxPerturbation);
		}
	}

  //put 'em back!
  m_ItsBrain.PutWeights(weights);
}

⌨️ 快捷键说明

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