首页 > Sktech > 习作CC_直角三角形范围判定应用场景地图墙壁碰撞判定
2017
12-14

习作CC_直角三角形范围判定应用场景地图墙壁碰撞判定

习作CC_直角三角形范围判定应用场景地图墙壁碰撞判定 - 第1张  | Processing编程艺术


用基本图形判定拼接成墙面和物体判定形成场景地图.
地图内有墙壁和障碍物, 角色只能在墙壁和障碍物以外的部分移动.
场景样式妄图模仿某著名游戏


思路:
– 要有一个地图类, 包含一个泛型容器容纳地图上的所有障碍物.
– 地图类顺序对比某一点(即角色)的位置和容器内所有障碍物的判定, 如果内包则视为碰撞.
– 地图类只做障碍物的判定, 不做描画, 描画应该交给外部位图或矢量图文件. (因为不方便读取文件, 这里仍然在类内部做了一部分描画, 在外部做了另一部分简单描画)
– 要有一个角色类, 为保证简单角色位置虽用矢量保存但移动不做矢量计算.
– 角色先计算移动位置, 判定后再决定是否移动.


[W|S|A|D]:移动角色
[Q]:退出程序


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


//- --- --- ---
//- public
//- --- --- ---
//-
EcMap pbTheMap=new EcMap(800,400);
EcProtagon pbTheKid=new EcProtagon();
//-

public void setup() {size(320, 240);noStroke();frameRate(32);textAlign(LEFT, TOP);ellipseMode(CENTER);
  frame.setTitle("CharaMap");
  //--
  pbTheMap.ccAddObstacle(new EcRectangleObstacle(0, 0, 800, 300));
  pbTheMap.ccAddObstacle(new EcTrangleObstacle(0, 280, 120, 120,'a'));
  pbTheMap.ccAddObstacle(new EcTrangleObstacle(680, 280, 120, 120,'b'));
  pbTheMap.ccAddObstacle(new EcRectangleObstacle(150, 295, 60, 27));
  pbTheMap.ccAddObstacle(new EcRectangleObstacle(450, 295, 60, 27));
  pbTheMap.ccAddObstacle(new EcRoundObstacle(350, 350, 50));
  //--
  pbTheKid.ccInit(pbTheMap,400,350);
  pbTheMap.ccRepos(-300, -200);
  //--
}//+++

public void draw(){
  //--
  background(0);
  //--
  pbTheMap.ccUpdate();
  spDrawMapAA(pbTheMap.cmPos.x,pbTheMap.cmPos.y);
  pbTheKid.ccUpdate();
  //--
}//+++

public void keyPressed() {switch(key){
  //--
  case 'w':pbTheKid.ccMoveCharactor(0, -1f);pbTheKid.cmHeading=2*PI;break;
  case 's':pbTheKid.ccMoveCharactor(0, 1f);pbTheKid.cmHeading=PI;break;
  case 'a':pbTheKid.ccMoveCharactor(-1f, 0);pbTheKid.cmHeading=PI*3/2;break;
  case 'd':pbTheKid.ccMoveCharactor(1f, 0);pbTheKid.cmHeading=PI/2;break;
  //--
  case 'q':fsPover();
  default:break;
}}//+++

//< <<< <<< <<< <<< <<< Overrided


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

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

void spDrawMapAA(float pxX, float pxY){
  stroke(0xFF);noFill();{
    rect(pxX+150,pxY+295,60,27); 
    rect(pxX+450,pxY+295,60,27);
    ellipse(pxX+350,pxY+350,50,50);
    quad(
      pxX+0,pxY+0,
      pxX+100,pxY+0,
      pxX+100,pxY+300,
      pxX+0,pxY+400
    );
    quad(
      pxX+700,pxY+0,
      pxX+800,pxY+0,
      pxX+800,pxY+400,
      pxX+700,pxY+300
    );
  }noStroke();
  fill(0xFF);
  text("chair",pxX+455,pxY+305);
  text("another\n chair",pxX+155,pxY+292);
  text("table",pxX+340,pxY+340);
  text("wall",pxX+400,pxY+280);
  text("wall",pxX+50,pxY+300);
  text("wall",pxX+750,pxY+300);
}//+++
  
//< <<< <<< <<< <<< <<< operate
  
//* *** *** *** *** ***
//*
//* Class
//*
//* *** *** *** *** ***
  
class EcMap{
  //--
  PVector cmPos, cmDia;
  ArrayList<EcObstacle> cmObsatcleList;
  float cmCameraRange;
  //--
  EcMap(int pxW,int pxH){
    cmPos=new PVector(0,0);
    cmDia=new PVector(pxW, pxH);
    cmObsatcleList=new ArrayList<EcObstacle>();
    cmCameraRange=100;
  }
  //--
  void ccRepos(int pxX, int pxY){
    cmPos.x=(float)pxX;
    cmPos.y=(float)pxY;
  }
  //--
  void ccAddObstacle(EcObstacle pxObstacle){
    cmObsatcleList.add(pxObstacle);
  }
  //--
  void ccUpdate(){
    fill(0xEE,0xAA,0x33);rect(cmPos.x,cmPos.y,cmDia.x,cmDia.y);
    if(!cmObsatcleList.isEmpty()){for(EcObstacle itObstacle:cmObsatcleList){
      itObstacle.ccRepos((int)cmPos.x, (int)cmPos.y);
      itObstacle.ccUpdate();
    }}
  }
  //--
  void ccMoveCamera(float pxX, float pxY){
    float lpRangeX=cmCameraRange;
    float lpRangeY=cmCameraRange;
    float lpRangeW=width-(cmCameraRange*2);
    float lpRangeH=height-(cmCameraRange*2);
    if(pxX<=lpRangeX){cmPos.x+=(lpRangeX-pxX);}
    if(pxX>=(lpRangeX+lpRangeW)){cmPos.x-=(pxX-lpRangeX-lpRangeW);}
  }
  //--
  boolean ccIsInRange(float pxX, float pxY){
    if(
      (pxX>cmPos.x)&&(pxX<cmPos.x+cmDia.x)&&(pxY>cmPos.y)&&(pxY<cmPos.y+cmDia.y)
    ){
      if(!cmObsatcleList.isEmpty()){for(EcObstacle itObstacle:cmObsatcleList){
        boolean lpRes=itObstacle.ccIsContaining((int)pxX, (int)pxY);
        if(lpRes){return false;}
      }}
      return true;
    }
    return false;
  }
  //--
}//+++
  
class EcProtagon{
  EcMap cmMap;
  PVector cmRelatePos;
  //--
  float cmSpeed;
  float cmHeading;
  int cmFoot;
  //--
  EcProtagon(){
    cmMap=null;
    cmRelatePos=new PVector(0, 0);
    cmSpeed=3.3f;
    cmHeading=PI/2;
    cmFoot=0;
  }
  //--
  void ccInit(EcMap pxMap, int pxX, int pxY){
    cmMap=pxMap;
    cmRelatePos.x=(float)pxX;
    cmRelatePos.y=(float)pxY;
  }
  //--
  void ccUpdate(){
    if(cmMap==null){return;}
    int lpAbsoX=(int)(cmRelatePos.x+cmMap.cmPos.x);
    int lpAbsoY=(int)(cmRelatePos.y+cmMap.cmPos.y);
    
    fill(0xFF);stroke(0);pushMatrix();{
      translate(lpAbsoX, lpAbsoY);
      rotate(cmHeading);
      quad(
        -6,-10,
        +6,-10,
        +12,+10,
        -12,+10
      );
      fill(cmFoot<3?0x33:0xCC);rect(2,2,4,4);
      fill(cmFoot<3?0xCC:0x33);rect(-6,2,4,4);
    }popMatrix();noStroke();
    
   // ellipse(lpAbsoX, lpAbsoY, 16, 16);
  }
  //--
  void ccMoveCharactor(float pxX, float pxY){
    float lpNewPosX=cmRelatePos.x+pxX*cmSpeed;
    float lpNewPosY=cmRelatePos.y+pxY*cmSpeed;
    if(cmMap.ccIsInRange(lpNewPosX+cmMap.cmPos.x,lpNewPosY+cmMap.cmPos.y)){
      cmFoot++;cmFoot&=0x07;
      cmRelatePos.x=lpNewPosX;
      cmRelatePos.y=lpNewPosY;
      cmMap.ccMoveCamera(lpNewPosX+cmMap.cmPos.x, lpNewPosY+cmMap.cmPos.y);
    }
  }
}//+++
  
//- --- --- ---
//- Obsatcle
//- --- --- ---
  
abstract class EcObstacle{
  int cmFollowX,cmFollowY;
  int cmAbsoX,cmAbsoY;
  int cmX,cmY,cmW,cmH;
  int cmOnColor;
  boolean cmAct;
  EcObstacle(){
    cmX=cmY=cmW=cmH=9;
    cmOnColor=color(0xEE,0xEE,0x33);
    cmAct=false;
    cmFollowX=0;cmFollowY=0;
    cmAbsoX=cmFollowX+cmX;cmFollowY=cmFollowY+cmY;
  }
  //--
  void ccRepos(int pxX, int pxY){
    cmFollowX=pxX;
    cmFollowY=pxY;
  }
  void ccRefreshPos(){
    cmAbsoX=cmFollowX+cmX;
    cmAbsoY=cmFollowY+cmY;
  }
  //--
  abstract void ccUpdate();
  abstract boolean ccIsContaining(int pxX, int pxY);
}//+++

class EcRectangleObstacle extends EcObstacle{
  //--
  EcRectangleObstacle(int pxX, int pxY, int pxW, int pxH) {
    super();
    cmX=pxX;cmY=pxY;
    cmW=pxW;cmH=pxH;
  }
  //--
  @Override void ccUpdate(){
    ccRefreshPos();
    fill(cmAct?cmOnColor:0x55);
    rect(cmAbsoX,cmAbsoY,cmW,cmH);
  }
  //--
  @Override boolean ccIsContaining(int pxX, int pxY){
    return (pxX>cmAbsoX)&&(pxX<cmAbsoX+cmW)&&(pxY>cmAbsoY)&&(pxY<cmAbsoY+cmH);
  }
  //--
  }//+++

class EcRoundObstacle extends EcObstacle{
  //--
  int cmR;
  //--
  EcRoundObstacle(int pxX, int pxY, int pxD){
    super();
    cmX=pxX;cmY=pxY;
    cmW=cmH=pxD;
    cmR=pxD/2;
  }
  //--
  @Override void ccUpdate(){
    ccRefreshPos();
    fill(cmAct?cmOnColor:0x55);
    ellipse(cmAbsoX,cmAbsoY,cmW,cmH);
  }
  //--
  @Override boolean ccIsContaining(int pxX, int pxY){
    if(!((pxX>cmAbsoX-cmR)&&(pxX<cmAbsoX+cmR)&&(pxY>cmAbsoY-cmR)&&(pxY<cmAbsoY+cmR))){return false;}else{
      PVector lpCenter=new PVector(cmAbsoX,cmAbsoY);
      PVector lpTarget=new PVector(pxX,pxY);
      return ceil(PVector.dist(lpTarget,lpCenter))<cmR;
    }
  }
}//+++

class EcTrangleObstacle extends EcObstacle{
  //--
  char cmMode;
  /** *
   * @param pxMode_abcd [a]north west point..[b]north east point..
   * [c]south east point..[d]south west point
   */
  EcTrangleObstacle(int pxX, int pxY, int pxW, int pxH, char pxMode_abcd){
    super();
    cmX=pxX;cmY=pxY;
    cmW=pxW;cmH=pxH;
    cmMode=pxMode_abcd;
  }
  //--
  @Override void ccUpdate(){
    ccRefreshPos();
    fill(cmAct?cmOnColor:0x55);
    switch(cmMode){
      case 'a':triangle(cmAbsoX, cmAbsoY, cmAbsoX+cmW, cmAbsoY, cmAbsoX, cmAbsoY+cmH);break;
      case 'b':triangle(cmAbsoX, cmAbsoY, cmAbsoX+cmW, cmAbsoY, cmAbsoX+cmW, cmAbsoY+cmH);break;
      case 'c':triangle(cmAbsoX+cmW, cmAbsoY, cmAbsoX+cmW, cmAbsoY+cmH, cmAbsoX, cmAbsoY+cmH);break;
      case 'd':triangle(cmAbsoX, cmAbsoY, cmAbsoX+cmW, cmAbsoY+cmH, cmAbsoX, cmAbsoY+cmH);break;
      default:break;
    }
  }
  //--
  @Override boolean ccIsContaining(int pxX, int pxY){
    if(!((pxX>cmAbsoX)&&(pxX<cmAbsoX+cmW)&&(pxY>cmAbsoY)&&(pxY<cmAbsoY+cmH))){return false;}else{
      int lpDPointL=(pxX-cmAbsoX)*cmH/cmW+cmAbsoY;
      int lpDPointR=(cmAbsoX+cmW-pxX)*cmH/cmW+cmAbsoY;
      switch(cmMode){
        case 'a':return pxY<lpDPointR;
        case 'b':return pxY<lpDPointL;
        case 'c':return pxY>lpDPointR;
        case 'd':return pxY>lpDPointL;
        default:return false;
      }
    }
  }
  //--
}//+++

//EOF

 



最后编辑:
作者:constrain
nullpointerexception

留下一个回复

你的email不会被公开。