显示给定某一点所能达到的距离范围.
这个范围会受到地图上各种障碍物的影响.
思路:
– 先确定最大可能范围(即无视障碍物的范围).
– 对可能范围内的所有格子做相对定点的寻径计算.
– 如果路径可以被找到, 则该格可选, 如果不能被找到, 则视为不可选.
[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
- 本文固定链接: http://iprocessing.cn/2018/10/31/习作dc_四边方格地图应用寻径到计算移动范围/
- 转载请注明: constrain 于 Processing编程艺术 发表
《习作DC_四边方格地图应用寻径到计算移动范围》有 1 条评论