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

📄 uclass.pas

📁 机器人足球赛比赛平台源代码
💻 PAS
📖 第 1 页 / 共 3 页
字号:
///修改纪录:2002.8.25, 在球运动之后马上就判断是否进球,改变了以前球和人都运动过之后
///                     再判断的情况。
///         2002.8.25,  球门大小改变为原来的1/2
///         2002.9.10,  球门大小改变为原来的350
unit uClass;

interface
uses classes, Dialogs, Math, Sysutils, Windows;

{$DEFINE ROBOT_RANDOM}
const   CROBOTNUM  = 5;          {一个team的robot个数}
        CMAXV      = 40;         {球员最大速度}
        CMAXACC    = 13;         {球员最大加速度}
        CRADIUS    = 100;        {机器人的半径}
        CDOORWIDTH = 350;        {一侧是350,实际长度是2 * 350}
//        CDOORWIDTH = 200;        {一侧是200,实际长度是2 * 200}
        CPNZWIDTH  = 1500;       {禁区的宽度}
        CPNZLEN    = 800;        {禁区的长度}
        CFLDWIDTH  = 2500;       {场地宽度}
        CFLDLEN    = 4000;       {场地长度}
        {$IFDEF ROBOT_RANDOM}
        CMaxError  = 0.26;       {传球最大误差}
//        CMaxError  = 0;       {传球最大误差}
        {$ELSE}
        CMaxError  = 0;       {传球最大误差}
        {$ENDIF}
        CMINBALLV  = 20;         {最小球速度}
        CMAXBALLV  = 200;        {最大球速度}
        CMATCHTIME = 3000;       {初赛、复赛仿真周期}
        CDEATHTIME = 1000;       {加时赛仿真周期}
        CJSTIME    = 5000;       {决赛仿真周期}
        CBALLACC   = 0.1;        {球的加速度系数k}
        CVCANBALL  = 120;
        CVCANNOTBALL = 240;
        CTIMECNT   = 5000;
        CMINNEARZERO = 0.1;       {最小的除数}
        RobotsPosition : array[1..CROBOTNUM, 1..2] of integer = ((30,1250),(1000,1250),(1000,100),(1000,2400),(1700,1250));

type
   {下面涉及到的坐标全部为绝对坐标}
  TCMD = record
     ifresetmovement : integer;        //如果需要重新设置机器人的移动方向和移动速度此参数置为1,否则置0
     TargetX         : integer;        //目标的X坐标,如果ifresetmovement=0 则此参数忽略
     TargetY         : integer;        //目标的Y坐标,如果ifresetmovement=0 则此参数忽略
     TargetV         : double;         //移动的目标速度,如果ifresetmovement=0 则此参数忽略
     Preactiontype   : integer;        //触球之后的动作类型:0表示不作任何动作,
     PreAparam0      : integer;        //1:表示以PreAparam0速度把球踢向(PreAparam1, PreAparam2)坐标
     PreAparam1      : integer;        //2: 表示以PreAparam0速度把球踢向(PreAparam1, PreAparam2)方向
     PreAparam2      : integer;        //请注意1,2的区别,详情请看http://tianwei.dlut.edu.cn/robocup/
   end;

   TCMDS = array [0..4] of TCMD;
   pCMD = ^TCMDS;

   TMatchStat = record
     iTeam1Score : integer;             //A队得分
     iTeam2Score : integer;             //B队得分
     iTimeTipCnt : integer;             //总的时间
     iTimeNow    : integer;             //当前时间
     iTimeFromGoal:integer;             //距离上次进球的时间
     iHMPETB     : integer;             // How many people effect the ball since the match start.
   end;
   
   TRobotState = record
      no          : integer;             {号码}
      team        : integer;             {组号码1,或者2}
      x           : integer;             {当前的x坐标}
      y           : integer;             {当前的y坐标}
      vx          : double;              {速度的x方向映射}
      vy          : double;              {速度的y方向映射}
   end;

   TRobotStats = array [0..4] of TRobotState;

   TBallState = record
      x           : integer;    {当前的x坐标}
      y           : integer;    {当前的y坐标}
      vx          : double;     {速度的x方向映射}
      vy          : double;     {速度的y方向映射}
      crn         : integer;    {控球队员号码}
      crt         : integer;    {控球队号码1 or 2}
   end;

   PMS = ^TMatchStat;
   PTS = ^TRobotStats;
   PBS = ^TBallState;
   
   TRobot = class(TObject)
      no          : integer;    {号码}
      team        : integer;    {队号码1,或者2}
      x           : integer;    {当前的x坐标}
      y           : integer;    {当前的y坐标}
      acc         : double;     {当前的加速度}
      owner       : TObject;    {场地}
      vx          : double;     {速度的x方向映射}
      vy          : double;     {速度的y方向映射}
      tvx         : double;     {目标速度X 分量}
      tvy         : double;     {目标速度Y 分量}
      targetX     : integer;    {目标x}
      targetY     : integer;    {目标y}
      preaction   : integer;    {预设动作类型0:清空动作,}
                                 {1:把球以TargetV踢向坐标TargetX, TargetY;}
                                 {2: 把球以TargetV踢向方向DirectX, DirectY;}
      param0      : integer;     {速度TargetV}
      param1      : integer;     {preaction 为0时 无意义; }
      param2      : integer;     {如果preaction不为0,则param1,param2表示TargetX,TargetY, or , DirectX, DirectY}
      function  getabsolutex : integer;
      function  getabsolutey : integer;
      function  tv : Double;
    public
      procedure move(TargetX, TargetY, TargetV: integer);  {以速度TargetV跑向坐标(TargetX, TargetY)}
      procedure SetPreAction(ipretype, prm0, prm1, prm2 : integer);  {设置预动作指令}
      constructor Create(aowner :TObject);
      procedure doAction;         {做预设动作}
      procedure doMove;           {做移动}
      property  posx:integer read x;
      property  posy:integer read y;
      property  absolutex : integer read getabsolutex;
      property  absolutey : integer read getabsolutey;
   end;

   TBall = class(TObject)
      x           : integer;    {当前的x坐标}
      y           : integer;    {当前的y坐标}
      owner       : TObject;    {场地}
      vx          : double;     {速度的x方向映射}
      vy          : double;     {速度的y方向映射}
      function speedmo : double;
    public
       constructor Create(owner :TObject);
       procedure doMove(var bGoal :boolean;var goalteam :integer);
       property posx:integer read x;
       property posy:integer read y;
       property spdx :double read vx;
       property spdy :double read vy;
      {做移动, 如果移动产生进球, bGoal为true, goalteam为对应的队伍的id}
   end;

   TMatchField = class(TObject)
       robots : array [1..2, 1..CROBOTNUM] of TRobot;
       ball   : TBall;          {球}
       preCP  : TRobot;         {上一个控球的球员}
       Scores : array [1..2] of integer; {比分}
       firstGoalTeam : integer; {第一个进球的队伍}
       lastGoalTeam  : integer; {上一个进球的队伍}
       crt    : integer;        {上次触球的队伍(大多数情况是控球的队伍)}
       crn    : integer;        {控球队员号码(大多数情况下是控球的队员)}
       iNow   : integer;        {当前的时间}
       iTFG   : integer;        {Time From Goal}
       iHMPETB: integer;        {How many player effect the ball}          
    public
       constructor Create();
       destructor Destory();
       procedure TimeTip;       {时间片动作}
       procedure InitMatch;
       procedure playerEffectball;
       procedure setfirstteamaction;
       procedure setsecondteamaction;
       procedure getMatchState(apms : PMS);
       procedure firstgetTeamAState(apts : PTS);
       procedure FirstgetTeamBState(apts : PTS);
       procedure FirstgetBallState(apbs : PBS);
       procedure SecondGetTeamAState(apts: PTS);
       procedure SecondGetTeamBState(apts: PTS);
       procedure SecondGetBallState(apbs : PBS);
       procedure UpdateScores;
   end;

function  ifinPZ(iteamid, ixiangdux, ixiangduiy :integer):boolean;  {是否再禁区内}
procedure ballcrashplayer(playerx,playery, ballx,bally : integer; vx1, vy1 :double; var vx2, vy2:double);
function ifgoal(oldx, oldy, newx, newy :integer):integer;
procedure speedmotospeedxy(yuanx, yuany, targetx, targety : integer; speedmo :double; var vx, vy:double);
procedure speedmotospeedxy2(yuanx, yuany, directx, directy: integer; speedmo :double; var vx, vy:double);
procedure giveballerror(vx, vy :double;var newvx, newvy:double);
function vectorAngle(sx,sy,dx,dy:double):double;
function distancebetween(x0,y0,x1,y1:integer):double;

implementation
uses uMain;

//////////////////////////////////////////////////////////
////   是否在禁区内
/////////////////////////////////////////////////////////
function ifinPZ(iteamid, ixiangdux, ixiangduiy: integer): boolean;
begin
  if iteamid = 1 then
  begin
    if (ixiangdux < CPNZLEN) and (abs(ixiangduiy - CFLDWIDTH / 2) < CPNZWIDTH /2) then
      result := true
    else
      result := false;
  end else
  begin
    if (ixiangdux > CFLDLEN - CPNZLEN) and( abs(ixiangduiy - CFLDWIDTH / 2) < CPNZWIDTH/2) then
      result := true
    else
      result := false;  
  end;
end;
/////////////////////////////////////////////
///   矢量和水平方向的夹角
/////////////////////////////////////////////
function vectorAngle(sx,sy,dx,dy:double):double;
var vx, vy, d, va : double;
begin
  if (dx=sx) and (dy=sy) then
  begin
    result := 0;
  end
  else
  begin
    vx := dx-sx;
    vy := dy-sy;
    d  := sqrt(sqr(vx) + sqr(vy));
    if d<>0 then
    begin
      va := arcsin(abs(vy)/d);
      if (vx>=0) and (vy>=0) then
        result := va
      else if (vx>=0) and (vy<=0) then
        result := -va
      else if (vx<=0) and (vy<=0) then
        result := va + PI
      else if (vx<=0) and (vy>=0) then
        result := PI - va
      else result := 0;
    end
    else
      result:=0;
  end;
end;

//////////////////////////////////////////////////
///  给球一个15度的误差
/////////////////////////////////////////////////
procedure giveballerror(vx, vy :double;var newvx, newvy:double);
var
  r : double;
  aold : double;
  randseed : double;
begin
  //
    r:= sqr(vx) + sqr(vy);
    r := sqrt(r);
  //
  if r<0.01 then
    begin
      newvx := 0;
      newvy := 0;
    end else begin
                aold := arcsin(abs(vy) / r);
                if (vx > 0) and (vy > 0) then
                  aold := aold
                else if (vx > 0) and (vy < 0) then
                  aold := -aold
                else if (vx < 0) and (vy > 0) then
                  aold := Pi - aold
                else aold := aold + Pi;

                randseed := random;
////========================================================////
////     randseed := (randseed -0.5) * 2 * CMaxError;       ////
////     version:  0.2.1.2                                  ////
////     传球的准确程度和目标速度有关                       ////
////========================================================////
                randseed := (randseed -0.5) * 2 * CMaxError * r / CMAXBALLV;
                newvx :=  r * cos(aold + randseed);
                newvy :=  r * sin(aold + randseed);
             end;
end;

procedure speedmotospeedxy(yuanx, yuany, targetx, targety : integer; speedmo :double; var vx, vy:double);
var
  yx,yy,tx,ty:double;
begin
  yx:=yuanx;
  yy:=yuany;
  tx:=targetx;
  ty:=targety;
  if (tx = yx) and (ty = yy) then
    begin
      vx := 0;
      vy := 0;
    end else begin
                  vx:=(sqr(tx - yx)) + (sqr(ty - yy));
                  vx := speedmo * (tx - yx) / sqrt(vx);
                  vy:=sqr(tx - yx) + sqr(ty - yy);
                  vy := speedmo * (ty - yy) / sqrt(vy);
             end;
end;

procedure speedmotospeedxy2(yuanx, yuany, directx, directy: integer; speedmo :double; var vx, vy:double);
var
  yx,yy,dx,dy:double;
begin
  yx:=yuanx;
  yy:=yuany;
  dx:=directx;
  dy:=directy;
  if (dx = 0) and (dy = 0) then
    begin
      vx := 0;
      vy := 0;
    end else begin
               vx:=sqr(dx) + sqr(dy);
               vx := speedmo * dx / sqrt(vx);
               vy:=sqr(dx) + sqr(dy);
               vy := speedmo * dy / sqrt(vy);
             end;
end;

function ifgoal(oldx, oldy, newx, newy :integer):integer;
var jy : double;
begin
  if (newx = CFLDLEN) then
  begin
      if (newy > CFLDWIDTH /2 - CDOORWIDTH) and (newy < CFLDWIDTH/2 + CDOORWIDTH) then
        result := 1
      else result := 0;
  end else if (newx = 0) then
  begin
      if (newy > CFLDWIDTH /2 - CDOORWIDTH) and (newy < CFLDWIDTH/2 + CDOORWIDTH) then
        result := 2
      else result := 0;
  end else
  begin
      if ((oldx >= 0) and (oldx <= CFLDLEN) and (newx >= CFLDLEN)) then
      begin
          jy := ((newy - oldy)*(CFLDLEN - oldx))/(newx - oldx)  + oldy;
          if (jy > CFLDWIDTH /2 - CDOORWIDTH) and ( jy < CFLDWIDTH/2 + CDOORWIDTH) then
            result := 1
          else result := 0;
      end
      else if ((oldx >= 0) and (oldx <= CFLDLEN) and (newx <= 0)) then
      begin
          jy := ((newy - oldy)*(0 - oldx))/(newx - oldx)  + oldy;
          if (jy > CFLDWIDTH /2 - CDOORWIDTH) and ( jy < CFLDWIDTH/2 + CDOORWIDTH) then
            result := 2
          else result := 0;
      end
      else
        result := 0;
  end;
end;

///////////////////////////////////////
////  zvictor版本,改正了fct版本中的球在人后的bug
///////////////////////////////////////
procedure ballcrashplayer(playerx,playery, ballx,bally : integer; vx1, vy1 :double; var vx2, vy2:double);
var
  va : double;  //人->球的矢量的角度
  vb : double;  //球的速度的矢量的角度
  vr : double;  //结果的矢量的角度
  vsm: double;  //速度的模
  px,py,bx,by:double;
begin
  px:=playerx;
  py:=playery;
  bx:=ballx;
  by:=bally;
  if (px=bx) and (py=by) then
  begin
    vx2 := -vx1;
    vy2 := -vy1;
  end
  else
  begin
    va := vectorAngle(px, py, bx, by);
    vb := vectorAngle(bx, by, bx+vx1, by+vy1);
    vr := PI - vb + 2*va;
    //
      vsm:=sqr(vx1) + sqr(vy1);
      vsm:= sqrt(vsm);
    //  
    vx2 := vsm * cos(vr);
    vy2 := vsm * sin(vr);
  end;   
end;

{ TMatchField }

constructor TMatchField.Create;
begin
  inherited;
  {things to do}
  ball := TBall.Create(self);
  lastGoalTeam := 0;
  InitMatch;
end;

destructor TMatchField.Destory;
var i,j : integer;
begin
  {things to do}
  for i:=1 to 2 do
   for j:=1 to CROBOTNUM do
     begin
       robots[i,j].free;
     end;

  inherited;
end;


procedure TMatchField.FirstgetBallState(apbs: PBS);
begin
  apbs^.x := ball.x;
  apbs^.y := ball.y;
  apbs^.vx := ball.vx;
  apbs^.vy := ball.vy;
  apbs^.crn:= crn;
  apbs^.crt:= crt;
end;

procedure TMatchField.getMatchState(apms: PMS);
begin
  apms^.iTeam1Score := scores[1];
  apms^.iTeam2Score := scores[2];
  apms^.iTimeTipCnt := CTIMECNT;
  apms^.iTimeNow := iNow;
  apms^.iTimeFromGoal := iTFG;
  apms^.iHMPETB := iHMPETB;
end;

procedure TMatchField.FirstgetTeamAState(apts: PTS);
var i:integer;
begin
  for i:=0 to 4 do
  begin
    apts^[i].no := i+1;
    apts^[i].team := 1;
    apts^[i].x := robots[1,i+1].x;
    apts^[i].y := robots[1,i+1].y;
    apts^[i].vx:= robots[1,i+1].vx;
    apts^[i].vy:= robots[1,i+1].vy;
  end;
end;

procedure TMatchField.FirstgetTeamBState(apts: PTS);

⌨️ 快捷键说明

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