首页 > Sktech > 习作DC_四边方格地图应用寻径到计算移动范围
2018
10-31

习作DC_四边方格地图应用寻径到计算移动范围

习作DC_四边方格地图应用寻径到计算移动范围 - 第1张  | Processing编程艺术


显示给定某一点所能达到的距离范围.
这个范围会受到地图上各种障碍物的影响.


思路:
– 先确定最大可能范围(即无视障碍物的范围).
– 对可能范围内的所有格子做相对定点的寻径计算.
– 如果路径可以被找到, 则该格可选, 如果不能被找到, 则视为不可选.


[W|S|A|D]:移动起始点
[F]:改变移动力
[R]:重置地图
[Q]:退出程序


在2.0内制作, 用3.0以上运行可能会报错:


//- --- --- ---
//- public
//- --- --- ---
//-
static final float C_MAP_OBSTACLE_PERCENTAGE=0.85f;
static final int C_MAP_OBSTACLE_MAX_VALUE=4;
static final int C_MAP_GRIDWIDTH_MAX=12;
//-
//-
int pbGridScale =16;
int pbGridFill  =16;
//--
int pbUnitGridX =0;
int pbUnitGridY =0;
int pbMAbility  =4;

int pbTargetGridX =999; //--we dont need a target now
int pbTargetGridY =999; //--but well need em soon
//-
ArrayList<EcMask> pbTestBufferList=null;
//-
EcMap pbTheMap;

void setup() {size(320, 240);noStroke();frameRate(16);textAlign(LEFT, TOP);ellipseMode(CENTER);
  frame.setTitle("UnitMap");
  //--
  pbTheMap=new EcMap(C_MAP_GRIDWIDTH_MAX);
  //--
}//+++

void draw(){background(0);
  //--
  //--

  for(EcMask it:pbTheMap.cmMaskList){
    it.ccSetReachable(false);
    if(it.ccTellPureAbility()){
      pbTestBufferList=pbTheMap.ccTellPosiblePath(pbUnitGridX, pbUnitGridY, it.cmGridX, it.cmGridY);
      it.ccSetReachable(!pbTestBufferList.isEmpty());
    }
    it.ccUpdate();
  }
  //--
}//+++

void keyPressed(){switch(key){
  //--
  case 'w':fsShiftTarget( 0, -1);break;
  case 's':fsShiftTarget( 0,  1);break;
  case 'a':fsShiftTarget(-1,  0);break;
  case 'd':fsShiftTarget( 1,  0);break;
  //--
  case 'f':
    pbMAbility++;pbMAbility&=0x07;
    pbMAbility=pbMAbility==0?1:pbMAbility;
    break;
  case 'r':
    {
      for(EcMask it:pbTheMap.cmMaskList){
        it.cmObsatcleLevel=random(1)>C_MAP_OBSTACLE_PERCENTAGE?((int)random(1,C_MAP_OBSTACLE_MAX_VALUE)):0;
      }
    }
    break;
  //--
  case 'q':fsPover();
  default:break;
}}//+++

//* *** *** *** *** ***
//*
//* Operate
//*
//* *** *** *** *** ***
//- --- --- ---

void fsShiftTarget(int pxX, int pxY){
  pbUnitGridX+=pxX;pbUnitGridX=constrain(pbUnitGridX,0,pbTheMap.cmGridDivide-1);
  pbUnitGridY+=pxY;pbUnitGridY=constrain(pbUnitGridY,0,pbTheMap.cmGridDivide-1);
}//+++

void fsPover(){
  exit();
}//+++
//< <<< <<< <<< <<< <<< operate

//* *** *** *** *** ***
//*
//* Class
//*
//* *** *** *** *** ***

class EcMap{
  ArrayList<EcMask> cmMaskList;
  int cmGridDivide;
  //--
  EcMap(int pxDivide){
    cmMaskList=new ArrayList<EcMask>();
    int lpCapa=pxDivide*pxDivide;
    for(int i=0;i<lpCapa;i++){
      int lpX=i%pxDivide;
      int lpY=i/pxDivide;
      cmMaskList.add(
        new EcMask(lpX, lpY,
          random(1)>C_MAP_OBSTACLE_PERCENTAGE?((int)random(1,C_MAP_OBSTACLE_MAX_VALUE)):0
        )
      );
    }
    cmGridDivide=pxDivide;
  }
  //--** 
  ArrayList<EcMask> ccTellDirectPath(int pxStartX, int pxStartY, int pxEndX, int pxEndY){
    ArrayList<EcMask> lpRes=new ArrayList<EcMask>();
    //--
    int lpSampleX=pxStartX;
    int lpSampleY=pxStartY;
    //--
    int lpDiffX=pxEndX-pxStartX;
    int lpDiffY=pxEndY-pxStartY;
    int lpStage=abs(lpDiffX)<abs(lpDiffY)?2:1;
    int lpStagePusher=lpStage==2?-1:1;
    //--
    //--
    while((lpStage==1)||(lpStage==2)){
      switch(lpStage){
        case 1:
          for(int i=0,s=(int)abs(lpDiffX);i<=s;i++){
            if(lpSampleX==pxEndX){break;}
            lpSampleX+=(lpDiffX<0)?-1:1;
            lpRes.add(cmMaskList.get(ccTellIndexByGrid(lpSampleX, lpSampleY)));
            //[DEBUG]::print("got::X--"+nf(lpSampleX,2));print("::Y--"+nf(lpSampleY,2));println("::ID--"+nf(ccTellIndexByGrid(lpSampleX, lpSampleY),2));
          }lpStage+=lpStagePusher;
          break;
        case 2:
          for(int i=0,s=(int)abs(lpDiffY);i<=s;i++){
            if(lpSampleY==pxEndY){break;}
            lpSampleY+=(lpDiffY<0)?-1:1;
            lpRes.add(cmMaskList.get(ccTellIndexByGrid(lpSampleX, lpSampleY)));
            //[DEBUG]::print("got::X--"+nf(lpSampleX,2));print("::Y--"+nf(lpSampleY,2));println("::ID--"+nf(ccTellIndexByGrid(lpSampleX, lpSampleY),2));
          }lpStage+=lpStagePusher;
          break;
        default:break;
      }
    }
    //[DEBUG]::println(">>> end");
    return lpRes;
    //--
  }
  //--  
  ArrayList<EcMask> ccTellPosiblePath(int pxStartX, int pxStartY, int pxEndX, int pxEndY){
    ArrayList<EcMask> lpRes=new ArrayList<EcMask>();    
    int lpCost;
    //--
    int lpSampleX=pxStartX;
    int lpSampleY=pxStartY;
    //--
    int lpDiffX=pxEndX-pxStartX;
    int lpDiffY=pxEndY-pxStartY;
    boolean lpIsXFirst=abs(lpDiffY)>abs(lpDiffX);
    //--
    lpRes.clear();
    lpRes.addAll(ccTellDirectPath(lpSampleX, lpSampleY, pxEndX, pxEndY));
    //--    
    if(lpDiffX==0||lpDiffY==0){
      lpCost=ccTellCostValueByPath(lpRes);
      if(lpCost<=pbMAbility){
        return lpRes;
      }else{
        lpRes.clear();
        return lpRes;
      }
    }
    //--
    for(int i=0,s=lpIsXFirst?
                    (int)abs(lpDiffX):(int)abs(lpDiffY);
                    i<s;i++){
      lpCost=ccTellCostValueByPath(lpRes);
      if(lpCost<=pbMAbility){return lpRes;}else{
        lpRes.clear();
        int lpTryX=lpSampleX;
        int lpTryY=lpSampleY;
        for(int j=0;j<=i;j++){
          if(lpIsXFirst){lpTryX+=(lpDiffX<0)?-1:1;}
          else{          lpTryY+=(lpDiffY<0)?-1:1;}
          lpRes.add(cmMaskList.get(ccTellIndexByGrid(lpTryX, lpTryY)));
        }
        lpRes.addAll(ccTellDirectPath(lpTryX, lpTryY, pxEndX, pxEndY));
      }
    }
    lpCost=ccTellCostValueByPath(lpRes);
    if(lpCost<=pbMAbility){return lpRes;}
    lpRes.clear();
    return lpRes;
  }
  //--
  int ccTellCostValueByPath(ArrayList<EcMask> pxPath){
    int lpRes=0;
    if(pxPath==null){return 255;}
    if(pxPath.isEmpty()){return 255;}    
    for(EcMask it:pxPath){lpRes+=(it.cmObsatcleLevel+1);}
    return lpRes;
  }
  //--
  int ccTellIndexByGrid(int pxX, int pxY){return pxY*cmGridDivide+pxX;}
  //--
}//+++

class EcMask{
  //--
  int cmGridX, cmGridY;
  int cmAbsoX, cmAbsoY;
  int cmGridDist;
  int cmObsatcleLevel;
  boolean cmIsOnPath, cmIsReachable;
  EcMask(int pxGridX, int pxGridY, int pxObsatcleLevel){
    cmGridX=pxGridX;cmAbsoX=0;
    cmGridY=pxGridY;cmAbsoY=0;
    cmGridDist=0;
    cmObsatcleLevel=pxObsatcleLevel;
    cmIsOnPath=false;
    cmIsReachable=false;
  }
  //--**
  void ccUpdate(){
    cmAbsoX=cmGridX*pbGridFill;
    cmAbsoY=cmGridY*pbGridFill;
    cmGridDist=
      (int)abs(pbUnitGridX-cmGridX)+
      (int)abs(pbUnitGridY-cmGridY);
    //--
    int lpColor=ccTellColor();
    if(ccIsMouseOver()){lpColor+=0x00111111;lpColor|=0xFF000000;}
    //--
    fill(lpColor); rect(cmAbsoX, cmAbsoY, pbGridScale, pbGridScale);
    if(cmObsatcleLevel!=0){
      fill(color(0xCC,0xCC,0x33));
      text(nf(cmObsatcleLevel,1),cmAbsoX,cmAbsoY);
    }
    //--
  }
  //--**
  void ccSetOnPath(boolean pxStat){cmIsOnPath=pxStat;}
  void ccSetObstacle(int pxValue){cmObsatcleLevel=pxValue;}
  //--
  int ccTellColor(){
    //-- ** <<< earlier one gets higher priority
    if(ccIsPathStart()){return color(0xCC,0xCC,0x33);}
    if(ccIsPathEnd()){return color(0xCC,0x33,0x33);}
    if(cmIsOnPath){return color(0xCC,0x99,0x33);}
    if(cmIsReachable){return color(0x99,0x99,0x99);}
    return color(0x66,0x66,0x66);
  }
  //--
  void ccSetReachable(boolean pxStats){cmIsReachable=pxStats;}
  boolean ccTellPureAbility(){return cmGridDist<=pbMAbility;}
  boolean ccIsMouseOver(){return ccIsContaining(mouseX, mouseY);}  
  boolean ccIsPathStart(){return (pbUnitGridX==cmGridX)&&(pbUnitGridY==cmGridY);}
  boolean ccIsPathEnd(){return (pbTargetGridX==cmGridX)&&(pbTargetGridY==cmGridY);}
  boolean ccIsContaining(int pxX, int pxY){
    return (pxX>cmAbsoX)&&(pxX<cmAbsoX+pbGridScale)&&
           (pxY>cmAbsoY)&&(pxY<cmAbsoY+pbGridScale);
    //--
  }
  //--
}//+++

//< <<< <<< <<< <<< <<< Class

//EOF

 



最后编辑:
作者:constrain
nullpointerexception

习作DC_四边方格地图应用寻径到计算移动范围》有 1 条评论

肖志喜的回复 取消回复

你的email不会被公开。