熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> JSP教程 >> 正文

Robocode 高手的秘訣:圓周瞄准

2013-11-15 11:50:09  來源: JSP教程 

  在您精通了直線瞄准之後下一步就是圓周瞄准該系統用到的數學略高深一些以使您能極為准確的命中做圓周運動的機器人同時仍能保留對付直線運動的機器人的有效性Alisdair Owens 將向您展示如何實現這一技巧並提供示例機器人您可以把它拿出來試玩一次
  
  這篇小技巧會讓您深入理解圓周瞄准的工作原理我們會從討論基本技巧的工作原理開始接著闡釋一個簡單的迭代它能顯著提高准確性我還提供源代碼它很容易適應在您自己的機器人中工作
  
  工作原理
  計算做圓周運動的機器人的 change in x(x 方向上的變化)和 change in y(y 方向上的變化)的偽碼相當簡單假定您以弧度為單位進行計算
  
  change in x = cos(initialheading) * radius cos(initialheading + changeinheading) * radius
  
  change in y = sin(initialheading + changeinheading) * radius sin(initialheading) * radius
  式中 initialheading 是敵方機器人在初始位置的方向子彈飛行期間的方向變化為 changeinheading我們假定它以 radius 為圓周半徑運動
  
  計算必要的數據
  圖 說明了我們需要的大部分數據r 是機器人運動所繞的圓周半徑方向變化為 a而 v 則是敵方機器人運動的即時速度
  
  圖 沿圓周移動
  

  
  為了要准確瞄准敵人我們需要某些特定的數據機器人當前的方向每轉的方向變化當前的速度我們的子彈到達的時刻我們可以使用這些數據計算出敵人轉圈的圓半徑以及它最後的方向(即我們的子彈到達敵人的瞬間敵人的方向)我們計算子彈擊中位置的方法如下
  
  每轉的方向變化我們用 headingchangeperturn = (heading heading)/time 得到這個值其中 time 是兩次測量的間隔時間您還必須使結果標准化如下面代碼中所示
  
  子彈時間我們使用簡單的 time = getTime()+(range/((*firepower))) 就可以滿足需要了其中 range 是發射時我們和敵人之間的距離而 firepower 是我們計劃使用的射擊火力假定子彈擊中時目標到我方的距離不變這個假設並不合適但是我們在本文後面的內容中開發出迭代之前有它就足夠了
  
  半徑我們用 radius = velocity/headingchangeperturn 得出這個值
  代碼
  圓周路徑預測只需要清單 但是請注意如果目標的方向變化很小那麼就要使用直線瞄准由於一旦半徑過大將導致存儲它所用的 double 溢出因而我們使用這種方式來緩解這一風險不過條件是方向變化比較小我們也就不必太擔心了
  
  清單 圓周瞄准代碼
  public PointDDouble guessPosition(long when) {
  /**time is when our scan data was produced when is the time
  that we think the bullet will reach the target diff is the
  difference between the two **/
  double diff = when time;
  double newX newY;
  /**if there is a significant change in heading use circular
  path prediction**/
  if (Mathabs(changehead) > ) {
  double radius = speed/changehead;
  double tothead = diff * changehead;
  newY = y + (Mathsin(heading + tothead) * radius)
  (Mathsin(heading) * radius);
  newX = x + (s(heading) * radius)
  (s(heading + tothead) * radius);
  }
  /**if the change in heading is insignificant use linear
  path prediction**/
  else {
  newY = y + s(heading) * speed * diff;
  newX = x + Mathsin(heading) * speed * diff;
  }
  return new PointDDouble(newX newY);
  }
  
  改進結果
  如果您已經試過清單 中的代碼那麼您會發現對付 spinbot(沿圓周移動的樣本機器人)的情況明顯好多了但您很可能還會注意到機器人發出的炮彈中仍有不少沒有命中目標這不單單是因為瞄的不准還要歸因於您對子彈要花費多長時間才能到達目標的估算不准要提高您的技術可以通過使用一個非常簡單的迭代來估算一下時間然後把這個估算值送入瞄准系統得到當子彈到達目標時您與目標之間的距離的更精確的估算值反復執行幾次這一步您將得到近乎完美的估值
  
  清單 迭代代碼
  /**This function predicts the time of the intersection between the
  bullet and the target based on a simple iteration It then moves
  the gun to the correct angle to fire on the target**/
  void doGun() {
  long time;
  long nextTime;
  PointDDouble p;
  p = new PointDDouble(targetx targety);
  for (int i = ; i < ; i++){
  nextTime =
  (intMathround((getRange(getX()getY()pxpy)/((*firePower))));
  time = getTime() + nextTime;
  p = targetguessPosition(time);
  }
  /**Turn the gun to the correct angle**/
  double gunOffset = getGunHeadingRadians()
  (MathPI/ Mathatan(py getY() px getX()));
  setTurnGunLeftRadians(normaliseBearing(gunOffset));
  }
  
  double normaliseBearing(double ang) {
  if (ang > MathPI)
  ang = *PI;
  if (ang < MathPI)
  ang += *MathPI;
  return ang;
  }
  
  public double getrange(double xdouble y double xdouble y) {
  double x = xx;
  double y = yy;
  double h = Mathsqrt( x*x + y*y );
  return h;
  }
  
  改進圓周瞄准的性能
  作為瞄准系統圓周瞄准基本成形了也就是說既在我們能力所及范圍內又能在此基礎上更進一步的事並不多但是能改善性能的小改動有兩處
  
  平均速度您也許願意保持一個補償加速效應的移動平平均速度而不是根據目標的最後速度進行計算
  
  每一回合方向的平均變化測量在每一回合內目標方向變化絕對量的平均值有助於我們對付那些不如 spinbot 有規律的目標
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19724.html
  • 上一篇文章:

  • 下一篇文章:
  • Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.