【Html5】-- 塔臺管制

 想作這個遊戲已久,今天終於初步完成,先解釋下,這是一個模擬機場塔臺管制指揮的遊戲,飛機從不一樣的方向飛入管制空域,有不一樣的目的地,飛機名稱最後一個字母表示飛機要到達的目的地,分ABCD和R。A-D表示四個方向,R表示到本場的跑道降落。飛機有H,M,S三種速度,離場必須不能是最快的速度(H),降落必須是S的速度這樣才能得分。默認設置是20架飛機,最多容量默認是10架飛機。固然實際的指揮比這個要複雜。html

基本原理

整個遊戲是基於canvas的,純JavaScript,四種朝向的飛機是用四張圖片實現的,全部要不斷渲染的對象都在airspace這個數組裏面。有Plane,Runway和Exit三個對象。正確指揮一架飛機到目的地有5分。前端

function Plane(id,sx,sy,heading,url){
    this.x=sx;
    this.y=sy;
    this.flightId=id;
    this.h=heading||"down";//up down left right
    this.img=url||"down.png";
    this.draw=drawPlane
    this.move=movePlane
    this.speed=airspeed[getRandom(3)];
    this.D=destination[getRandom(5)];
    this.state="cruise";
    this.width=size;
    this.height=size;
    this.getCenter=getCenter;
}
function Runway(name,x,y,w,h){
    this.name=name;
    this.x=y;
    this.y=y;
    this.width=w;
    this.height=h;
    this.draw=drawRunway;
    this.getCenter=getCenter;
}

點擊捕獲

到canvas上選中一架飛機以後會用紅色邊框,表示當前正在指揮的飛機。canvas自己沒有提供對象的click事件git

 因此要根據鼠標的位置來判斷是否選中了目標:github

function eventDispature(canvas){
  canvas.onclick=function(e){
     console.log(e.offsetX,e.offsetY,e.type)
     detectEvent(e.offsetX,e.offsetY,e.type)
  }
}

function detectEvent(x,y,type){
  //判斷是否擊中
  airspace.forEach(function(p){
      //範圍 x,x+size y,y+size
      var maX=p.x+p.width;
      var maY=p.y+p.height;
      if(x>=p.x&&x<=maX&&y>=p.y&&y<=maY){
          p.selected=true;
          taget=p;
          console.log("選中",p.flightId,p.x,p.y)
          airspace.filter(n=>n.flightId!=p.flightId).forEach(n=>n.selected=false);
      }
  })
}

根據e.offsetX和e.offsetY得到事件的位置,判斷是否在某個飛機的座標範圍裏,而後標記選中,並去除其餘被標記selected的飛機。固然這個地方還能夠完善成一個事件系統,並支持其餘的事件。算法

碰撞檢測

碰撞有四種狀況,首先是飛機與飛機相撞,飛機飛出邊界(是否正確飛向入口),飛機飛入跑道(是否對準入口進入)。錯誤操做的飛機將會被移除airspace數組。canvas

function isIntersect(p1,p2){
    var center=p1.getCenter();
    var c1=p2.getCenter();
     var dx=Math.abs(center.x-c1.x);
     var dy=Math.abs(center.y-c1.y);
     return dx<(p1.width/2+p2.width/2)&&dy<(p1.height/2+p2.height/2)
   }

三種狀況的判斷主要依靠上面這個方法,而後再有區分,飛機飛入跑道,首先是座標矩形會與跑道矩形相交,而後y1,y2在跑道的y軸範圍以內便可。數組

if(isIntersect(plane,runway)&&plane.state==states.cruise){
    console.warn(plane.flightId+"進入跑道");
    //進入跑道的條件是 左邊的兩個點 和右邊的兩個點
    var y1=plane.y;
    var y2=plane.y+plane.height;
        //速度最慢,方向是跑道才能得分
    if(y1>runway.y&&y1<runway.y+runway.height&&y2>runway.y&&y2<runway.y+runway.height
      &&plane.D==destination[4]&&plane.speed==airspeed[2])
        {
        plane.state=states.landing;
        score+=5;
        info(plane.flightId+"正確降落跑道");
        showPlaneNum();
        plane.state=states.stop;
        removePlane(plane.flightId);
    }else{
        plane.state=states.crash;
        info(plane.flightId+"墜毀,航向"+plane.h+",速度"+plane.speed);
        removePlane(plane.flightId);
    }

判斷進入入口的道理同樣。右下角幾個按鈕分別表示四個方向和三種速度。dom

不足:

1.飛機用了四張圖片仍是有點笨,由於當初旋轉移動沒有搞定,後續繼續研究。測試

2.飛機碰撞的算法還不夠準確,離場的判斷只判斷了一個點。這裏是考慮到離場判斷和入場飛機有衝突,這裏須要再優化下。優化

3.還能夠增長一些效果。

PS:這實際上是當時入學時一個測試程序,當時就記住了,今天用前端實現一回。來玩一玩吧,喜歡就給個贊,歡迎拍磚。

git:https://github.com/stoneniqiu/ATC 

演示地址:https://stoneniqiu.github.io/tower.html

相關文章
相關標籤/搜索