官术网_书友最值得收藏!

實驗7 貪吃蛇

簡介

1976年,Gremlin平臺推出了一款經典街機游戲Blockade。游戲中,兩名玩家分別控制一個角色在屏幕上移動,所經之處砌起圍欄。角色只能向左、右方向90°轉彎,游戲的目標是讓對方先撞上邊界或圍欄。聽起來有些復雜,其實就是兩條每走一步都會長大的貪吃蛇比誰堅持的時間長,玩家要做的就是避免撞上障礙物和越來越長的身體。更多照片、視頻可以看 GamesDBase的介紹。

Blockade很受歡迎,類似的游戲先后出現在 Atari 2600、TRS-80、蘋果2等早期游戲機、計算機上。但真正讓這種游戲形式紅遍全球的還是21年后隨諾基亞手機走向世界的貪吃蛇游戲——Snake,如圖1-24所示。

圖1-24 諾基亞貪吃蛇游戲

貪吃蛇算法

首先用Jscex把整個游戲的Loop搭建起來:

        var moveAsync=eval(Jscex.compile("async", function (p) {
        while (true) {
        //...
        //code here
        //...
                  $await(Jscex.Async.sleep(100));
                }
            }));

然后把相關的算法加進去。首先是蛇的移動算法,采用每一個時間間隔去掉尾部一個節點,并且向蛇的頭部運動方向增加一個節點的方法。

        if (direction=="right") {
                      p.push({
                        x: p[p.length-1].x+1,
                        y: p[p.length-1].y
                      });
                  }
        if (direction=="left") {
                      p.push({
                        x: p[p.length-1].x-1,
                        y: p[p.length-1].y
                      });
                  }
        if (direction=="up") {
                      p.push({
                        x: p[p.length-1].x,
                        y: p[p.length-1].y-1
                      });
                  }
        if (direction=="down") {
                      p.push({
                        x: p[p.length-1].x,
                        y: p[p.length-1].y+1
                      });
                  }

蛇的頭部運動方向共有4個,蛇在運動時都是往頭部運動方向增加一個節點,因為當蛇吃到食物時節點增加一個,所以不是每次都會去掉尾部節點,在判斷到蛇沒有吃到食物時去掉尾部的一個節點:

        if (p[p.length-1].x==foodPositions.x && p[p.length-1].y==foodPositions.y) {
                      foodPositions.x=-1;
                      foodPositions.y=-1;
                  }
        else {
                      clearColor(p[0]);
                      p.shift();
                  }

然后是隨機生成蛇的食物(這里可以加一個遞歸,如果生成的位置和蛇的位置重疊,則重新生成,一直遞歸下去,直到沒有重疊)。

        var MR=Math.random;
        function drawSnakeAndFood(p) {
        if (foodPositions.x==-1 && foodPositions.y==-1) {
                  foodPositions.x=MR() * 40 | 0;
                  foodPositions.y=MR() * 40 | 0;
                }
                cxt.fillStyle=randomColor();
                cxt.fillRect(foodPositions.x * width, foodPositions.y * height, height, width);
        for (i=0; i < p.length; i++) {
                  cxt.fillStyle="#D1EEEE";
                  cxt.fillRect(p[i].x * width, p[i].y * height, height, width);
                }
            }

GameOver的判定:

        if (p[p.length-1].x < 0 || p[p.length-1].x > 39 || p[p.length-1].y < 0 || p[p.length-1].y > 39) {
                      gameOver=true;
                  }
        if (isInSnake(p, { x: p[p.length-1].x, y: p[p.length-1].y })) {
                      gameOver=true;
                  }

GameOver分兩種情況,一種是撞到墻壁和障礙物,一種是撞到自己的身體,代碼如下:

        var moveAsync=eval(Jscex.compile("async", function (p) {
        while (true) {
        if (p[p.length-1].x < 0 || p[p.length-1].x > 39 || p[p.length-1].y < 0 || p[p.length-1].y > 39) {
                      gameOver=true;
                  }
        if (p[p.length-1].x==foodPositions.x && p[p.length-1].y==foodPositions.y) {
                      foodPositions.x=-1;
                      foodPositions.y=-1;
                  }
        else {
                      clearColor(p[0]);
                      p.shift();
                  }
        if (direction=="right") {
                      p.push({
                        x: p[p.length-1].x+1,
                        y: p[p.length-1].y
                      });
                  }
        if (direction=="left") {
                      p.push({
                        x: p[p.length-1].x-1,
                        y: p[p.length-1].y
                      });
                  }
        if (direction=="up") {
                      p.push({
                        x: p[p.length-1].x,
                        y: p[p.length-1].y-1
                      });
                  }
        if (direction=="down") {
                      p.push({
                        x: p[p.length-1].x,
                        y: p[p.length-1].y+1
                      });
                  }
                  drawSnakeAndFood(p);
        if (gameOver) {
                      drawGameOver();
                      document.getElementById("btnReset").disabled=";
        break;
                  }
                  $await(Jscex.Async.sleep(100));
                }
            }));

運行效果如圖1-25所示。

圖1-25 Canvas中的貪吃蛇游戲

主站蜘蛛池模板: 靖州| 安吉县| 同江市| 吴堡县| 石林| 保山市| 南江县| 正阳县| 包头市| 察隅县| 永安市| 合阳县| 定陶县| 溧水县| 饶阳县| 永和县| 渭南市| 盘锦市| 科技| 巫山县| 承德县| 石柱| 渝中区| 乌兰浩特市| 镶黄旗| 县级市| 崇信县| 龙海市| 商城县| 潼关县| 静宁县| 延安市| 昌宁县| 革吉县| 昌黎县| 宜宾县| 两当县| 北辰区| 泊头市| 孟村| 屏东县|