亚洲国产精品人久久,亚洲va国产日韩欧美精品色婷婷,久久久久88色偷偷,免费人成黄页在线观看国际

17站長網

17站長網 首頁 編程 JavaScript 查看內容

JS+Canvas實現貪吃蛇小游戲

2022-10-26 19:07| 查看: 2314 |來源: 互聯網

今天呢,主要和小伙伴們分享一下一個貪吃蛇游戲從構思到實現的過程~因為我不是很喜歡直接PO代碼,所以只copy代碼的童鞋們請出門左轉不謝。

今天呢,主要和小伙伴們分享一下一個貪吃蛇游戲從構思到實現的過程~因為我不是很喜歡直接PO代碼,所以只copy代碼的童鞋們請出門左轉不謝。

按理說canvas與其應用是老生常談了,可我在準備階段卻搜索不到有用的資料(不是代碼!),所以說呢,只能自力更生 -_- 

首先是大致要考慮的東西:

1.要有蛇(沒蛇怎么叫貪吃蛇)。

2.然后要有地圖(蛇是不能上天的)。

3.不能水平\垂直掉頭(如果想掉頭,需要至少變換方位并且至少移動一格才可)。

4.食物(不然怎么貪吃)。

5.吃了食物要變長(這才是精髓)。

PS:~現在我回想起來,當時的確只想到這么多(⊙﹏⊙)

構思完畢,開工!

怎么做呢?從大到小,先畫個矩形作地圖,可我覺得太丑,于是畫了一張圖出來:

1

2

3

4

5

context.beginPath();

var bgImg = new Image();

bgImg.src = "img/background.png";

context.drawImage(bgImg, 0, 0, 600, 600);

context.closePath();

現在我們有地圖了

地圖上好像缺點什么……沒錯就是禮物,所以我們現在生成禮物,那么問題來了:禮物最多有幾個、生成位置、何時生成。

我這里暫時定義為:最多2個、隨機位置生成、當禮物個數小于2時生成至2個。

接下來就很簡單了,上圖中,允許蛇活動的范圍是14顆樹(周圍兩顆樹是墻),然后16顆樹=600px,很容易我們得到每格多寬~

所以呢,我們只需要定義一個隨機生成1-14整數的方法就可以很輕松找到應該生成的位置:

1

2

3

4

//隨機數

function selectfrom() {

   return Math.floor(Math.random() * 14 + 1);

}

然后再用求出的數乘以每一格子的寬度,即可求出生成的具體X坐標,因為是正方形,所以Y也一樣:

1

2

var x = selectfrom() * (600/16);

var y = selectfrom() * (600/16);

并且每得到一組禮物坐標后,都需要存儲在一個數組內(一會兒有大用處),至于畫矩形太基礎我就不說了。

And Now,我們有了禮物,有了地圖,就差蛇了,那么問題又來了:出生的蛇多長、出生地、死亡方式、移動方式、轉彎方式、如何判斷吃掉了禮物、吃掉了禮物變長到哪里。

出生蛇長度:實際編寫過程中,我發現默認長度1和2都不能夠很好的體現“蛇的轉彎”,所以定義為3,并且需將蛇身所有坐標記錄在數組內。

出生地:地圖中央或者自己定一個位置(按照格子來分),XY坐標求取方式上面已經說過不再贅述。

死亡方式:碰到障礙,或者(吃到自己)蛇頭碰到蛇身。

移動方式:通過定義一個全局變量記錄當前方向(0、1、2、3,默認1),并且使用計時器驅動蛇運動。

轉彎方式:加入鍵盤按鍵檢測事件,當方向鍵按下的時候修改-記錄方向的全部變量即可。

如何判斷吃掉了禮物:每次蛇頭移動時,都要遍歷下禮物集合(上面有說過),如果蛇頭將要移動到的下個坐標與之重合了,則視為吃掉了禮物。

吃掉了禮物變長到哪里:直接加在頭部可能會導致意外的死亡,所以我決定吃到禮物后的下一次移動不消除蛇尾(最后一個元素)。

有了上面的構思,我們可以著手定義一些可能會用到的公共變量:

移動方式:通過定義一個全局變量記錄當前方向(0、1、2、3,默認1),并且使用計時器驅動蛇運動。

轉彎方式:加入鍵盤按鍵檢測事件,當方向鍵按下的時候修改-記錄方向的全部變量即可。

如何判斷吃掉了禮物:每次蛇頭移動時,都要遍歷下禮物集合(上面有說過),如果蛇頭將要移動到的下個坐標與之重合了,則視為吃掉了禮物。

吃掉了禮物變長到哪里:直接加在頭部可能會導致意外的死亡,所以我決定吃到禮物后的下一次移動不消除蛇尾(最后一個元素)。

有了上面的構思,我們可以著手定義一些可能會用到的公共變量:

移動方式:通過定義一個全局變量記錄當前方向(0、1、2、3,默認1),并且使用計時器驅動蛇運動。

轉彎方式:加入鍵盤按鍵檢測事件,當方向鍵按下的時候修改-記錄方向的全部變量即可。

如何判斷吃掉了禮物:每次蛇頭移動時,都要遍歷下禮物集合(上面有說過),如果蛇頭將要移動到的下個坐標與之重合了,則視為吃掉了禮物。

吃掉了禮物變長到哪里:直接加在頭部可能會導致意外的死亡,所以我決定吃到禮物后的下一次移動不消除蛇尾(最后一個元素)。

有了上面的構思,我們可以著手定義一些可能會用到的公共變量:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

var canvas = document.getElementById("mycanvas");//畫布主體

var context = canvas.getContext("2d");

var timer;//計時器

const WIDTH = canvas.width;//畫布寬

const HEIGHT = canvas.height;//畫布高

const XSUM = 16; //畫布寬分為幾格

const YSUM = 15; //畫布高分為幾格

const MAXFFOD = 2; //最大食物數量

var score = 0;//定義記錄游戲得分

var xsplit = WIDTH / XSUM; //x每一格子的寬度

var ysplit = HEIGHT / YSUM; //y每一格子的高度

var foodcount = 0; //當前食物數量

var sinak = []; //貪吃蛇坐標集

var get = []; //禮物坐標集

var MoveTo = 1; //移動方向 默認1(右)

有了這些變量,是不是發現很多東西都通了呢?

我們先來畫蛇:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

//畫貪吃蛇

function drawsinak(sl) { //sl默認長度

    context.beginPath();

    context.fillStyle = "#000";

    var ling = 0; //貪吃蛇被打印長度

    for (var r = 0; r < sinak.length; r++) {

        context.fillRect(sinak[r].split(',')[0], sinak[r].split(',')[1], xsplit, ysplit);

        ling++;

    }

    if (ling == 0) {

        for (var i = 0; i < sl; i++) {

            context.fillRect(xsplit * (7 - i), ysplit * 6, xsplit, ysplit); //默認出生點:7,6默認中心點

            sinak.push(xsplit * (7 - i) + ',' + ysplit * 6);

        }

    }

    context.fill();

    context.closePath();

}

可以看到我將生成的蛇的坐標都計入了數組內,生成的禮物自然也要計入:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

context.beginPath();

  var x = selectfrom(XSUM - 2) * xsplit;

  var y = selectfrom(YSUM - 2) * ysplit;

  context.fillStyle = "red";

  for (var i = 0; i < get.length; i++) {

      context.fillRect(get[i].split(',')[0], get[i].split(',')[1], xsplit, ysplit);

      context.fill();

      foodcount++;

  }

  if (MAXFFOD > foodcount) {

      context.fillRect(x, y, xsplit, ysplit);

      context.fill();

      foodcount++;

      get.push(x + ',' + y);

  }

  context.closePath();

接下來比較重要了,蛇的移動,以及吃到禮物和觸發死亡判斷:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

//移動方法

//[c]移動方向 上右下左 0123

function sinakMove(c) {

    context.beginPath();

  

    //默認右側為頭

    var tou = sinak[0]; //頭

    var weiba = sinak[sinak.length - 1]; //尾巴

  

    var oldX = tou.split(',')[0]; //頭部舊X坐標

    var oldY = tou.split(',')[1]; //頭部舊Y坐標

  

    var newX = 0; //頭部最新X坐標

    var newY = 0; //頭部最新Y坐標

  

    //計算頭部最新XY坐標

    switch (c) {

        case 0:

            newX = oldX;

            newY = oldY - ysplit;

            break;

        case 1:

            newX = (oldX - 0) + xsplit;

            newY = oldY;

            break;

        case 2:

            newX = oldX;

            newY = (oldY - 0) + ysplit;

            break;

        case 3:

            newX = oldX - xsplit;

            newY = oldY;

            break;

    }

  

    var flag = 0; //有沒有吃到禮物 0沒有1有

  

    //如果吃到了禮物,則不消減尾部最后元素

    for (var i = 0; i < get.length; i++) {

        if (newX == get[i].split(',')[0] && newY == get[i].split(',')[1]) {

            sinak.unshift(newX + ',' + newY);

            foodcount--; //禮物計數減少1個

            get.splice(i, 1); //清空禮物

            flag = 1;

        }

    }

    //如果沒有吃到禮物,則判斷是否碰到障礙或吃到自己

    if (flag == 0) {

        for (var i = 0; i < sinak.length; i++) {

            if (newX == sinak[i].split(',')[0] && newY == sinak[i].split(',')[1]) {

                if (confirm('吃掉了自己,游戲失敗!是否重新開始?')) {

                    location.reload(true);

                } else {

                    context.clearRect(0, 0, WIDTH, HEIGHT);

                }

            }

        }

        if (xsplit * (XSUM - 2) < newX || ysplit * (YSUM - 2) < newY || newX == 0 || newY == 0) {

            if (confirm('撞墻了,游戲失敗!是否重新開始?')) {

                location.reload(true);

            }

        }

    }

  

    //如果沒有吃到禮物,那么進行普通移動

    if (flag == 0) {

        sinak.unshift(newX + ',' + newY);

        sinak.splice(sinak.length - 1, 1);

    }

  

    //畫蛇

    for (var r = 0; r < sinak.length; r++) {

        context.fillRect(sinak[r].split(',')[0], sinak[r].split(',')[1], xsplit, ysplit);

    }

    context.closePath();

}

控制蛇的方向:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

//鍵盤事件

document.onkeydown = function (event) {

    var e = event || window.event || arguments.callee.caller.arguments[0];

    var move = 0; //移動方向

    if (e && e.keyCode == 37) { //左

        move = (MoveTo == 1 ? 1 : 3);

    } else if (e && e.keyCode == 38) { //上

        move = (MoveTo == 2 ? 2 : 0);

    } else if (e && e.keyCode == 39) { //右

        move = (MoveTo == 3 ? 3 : 1);

    } else if (e && e.keyCode == 40) { //下

        move = (MoveTo == 0 ? 0 : 2);

    } else if (e && e.keyCode == 32) {//暫停游戲

        clearInterval(timer);

    }

    MoveTo = move; //修改當前移動方向

};

這里做了防誤操作,當蛇正在朝向某方向移動時,直接輸入反方向是無效的。如:蛇正向右走,這時直接按←鍵是無效的,仍然往右走。

tag標簽:JS+Canvas 貪吃蛇
本文最后更新于 2022-10-26 19:07,某些文章具有時效性,若有錯誤或已失效,請在網站留言或聯系站長:17tui@17tui.com
·END·
站長網微信號:w17tui,關注站長、創業、關注互聯網人 - 互聯網創業者營銷服務中心

免責聲明:本站部分文章和圖片均來自用戶投稿和網絡收集,旨在傳播知識,文章和圖片版權歸原作者及原出處所有,僅供學習與參考,請勿用于商業用途,如果損害了您的權利,請聯系我們及時修正或刪除。謝謝!

17站長網微信二維碼

始終以前瞻性的眼光聚焦站長、創業、互聯網等領域,為您提供最新最全的互聯網資訊,幫助站長轉型升級,為互聯網創業者提供更加優質的創業信息和品牌營銷服務,與站長一起進步!讓互聯網創業者不再孤獨!

掃一掃,關注站長網微信

大家都在看

    熱門排行

      最近更新

        返回頂部
        亚洲国产精品人久久,亚洲va国产日韩欧美精品色婷婷,久久久久88色偷偷,免费人成黄页在线观看国际
        不卡免费追剧大全电视剧网站| 亚洲人成伊人成综合网小说| 亚洲图片你懂的| 久久色中文字幕| 国产欧美日韩精品一区| 国产精品色在线| 亚洲综合一区二区三区| 日韩视频在线你懂得| 久久视频一区二区| 91麻豆精品91久久久久同性| 日韩免费一区二区| 91丝袜呻吟高潮美腿白嫩在线观看| 国产在线一区二区| 日韩电影在线观看网站| 激情综合色综合久久综合| 99久久99久久精品免费观看| 欧美精品免费视频| 1000精品久久久久久久久| 蜜臀久久99精品久久久久宅男| 日韩va欧美va亚洲va久久| 一区二区三区蜜桃| 丰满少妇久久久久久久| 精品久久国产97色综合| 亚洲成人精品在线观看| 亚洲国产精品久久人人爱蜜臀| 激情亚洲综合在线| 精品久久久久99| 国产自产v一区二区三区c| 欧美一区二区三区免费观看视频| 亚洲私人黄色宅男| 国模娜娜一区二区三区| 精品国产91洋老外米糕| 国产精品久久久久久久久搜平片| 久久97超碰色| 国产亚洲综合色| 激情综合色综合久久| 99国产一区二区三精品乱码| 国产精品色一区二区三区| 欧美性色综合网| wwwwxxxxx欧美| 国产午夜精品一区二区| 国产视频一区不卡| 暴力调教一区二区三区| 亚洲另类一区二区| 日韩欧美综合在线| 色综合中文综合网| 亚洲一卡二卡三卡四卡五卡| 欧美一级爆毛片| 日本麻豆一区二区三区视频| 亚洲国产精品成人综合色在线婷婷| 日本伦理一区二区| 成人高清视频在线观看| 久色婷婷小香蕉久久| 亚洲成人先锋电影| 日韩一区二区电影| 久久成人免费日本黄色| 亚洲老妇xxxxxx| 欧美日韩在线播放三区四区| 日本不卡1234视频| 亚洲一区在线视频观看| 亚洲免费在线看| 亚洲日本青草视频在线怡红院| 国产成人精品免费看| 国产精品伦理在线| 国产精品欧美久久久久一区二区| 成人app网站| 日本高清免费不卡视频| 经典三级在线一区| 国产精品自拍av| 99re视频精品| 色综合视频在线观看| 成人毛片老司机大片| 99v久久综合狠狠综合久久| 欧美色综合久久| 欧美一区二区三区四区在线观看| 风间由美一区二区三区在线观看 | 国产精品免费丝袜| 综合亚洲深深色噜噜狠狠网站| 亚洲一区中文日韩| 一区二区欧美视频| 国产精品久久久久久久久免费樱桃| 亚洲欧美激情小说另类| 久久99精品国产.久久久久久| 国产毛片精品视频| 欧美高清你懂得| 91在线视频观看| 亚洲精品成人精品456| 亚洲国产另类av| 奇米影视一区二区三区| 国产一区二区三区综合| 麻豆视频观看网址久久| 国产精品高潮久久久久无| 亚洲国产精品一区二区久久| 国产精品一区二区在线播放| 欧美日韩一区二区在线观看| 久久久久久久久久久久久夜| 日韩影视精彩在线| 国产精品福利在线播放| 亚洲精品国产高清久久伦理二区| 国产亚洲一区二区三区| 国产精品久久久久影院| 中文字幕精品一区二区精品绿巨人 | 成人午夜av电影| 日韩欧美久久一区| 欧美顶级少妇做爰| 亚洲福利视频导航| 成人免费视频视频在线观看免费| 国产精品白丝jk黑袜喷水| 九九视频精品免费| 久久精品人人做人人综合 | 国产在线播放一区| 中文字幕av资源一区| 成人黄页在线观看| 丝袜a∨在线一区二区三区不卡| 日韩天堂在线观看| 免费日本视频一区| 正在播放一区二区| 波波电影院一区二区三区| 日韩美女啊v在线免费观看| 国产一区二区看久久| 久久久久久一二三区| 成人在线视频首页| 国产精品久久久久四虎| 97aⅴ精品视频一二三区| 看片网站欧美日韩| 香港成人在线视频| 亚洲一区二区三区四区在线观看| 国产欧美一区二区精品忘忧草| 成人网页在线观看| 大陆成人av片| 99久免费精品视频在线观看| 成人激情小说乱人伦| 精品伊人久久久久7777人| 久久99国产精品尤物| 国内成人精品2018免费看| 韩国精品一区二区| 国产精品18久久久久久久久| 国产一区二区三区av电影 | 日韩电影在线观看网站| 久久午夜羞羞影院免费观看| 久久伊99综合婷婷久久伊| 久久久午夜精品| 亚洲国产成人在线| 一区二区三区资源| 精品在线你懂的| 国产在线精品免费| 免费精品视频在线| 95精品视频在线| 久久综合视频网| 久久久久久97三级| 亚洲精品在线免费观看视频| 欧美日韩精品一区二区三区四区 | 日韩午夜在线影院| 中文字幕一区三区| 麻豆国产91在线播放| 欧美剧在线免费观看网站 | 韩国av一区二区| 日本乱码高清不卡字幕| 国产精品久久久久永久免费观看 | 91色porny| 中国色在线观看另类| 国产欧美综合在线观看第十页| 欧美人与z0zoxxxx视频| 欧美精品123区| 亚洲国产成人精品视频| 日本vs亚洲vs韩国一区三区二区| 亚洲国产综合91精品麻豆| 岛国精品在线观看| 精品视频在线视频| 久久综合成人精品亚洲另类欧美| 亚洲精品一区二区三区99| 日本不卡高清视频| 26uuu国产在线精品一区二区| 久久精品国产精品青草| 精品久久人人做人人爱| 国产精品影视在线| 亚洲天堂免费看| 欧美日韩国产在线观看| 日韩av电影天堂| 久久精品一区蜜桃臀影院| 亚洲午夜精品在线| 欧美精品一区二区三区高清aⅴ| 亚洲免费观看在线视频| 91.com在线观看| 精品在线一区二区三区| 精品乱人伦一区二区三区| 五月激情丁香一区二区三区| 国产三级一区二区| 久久国产乱子精品免费女| 中文字幕一区二区在线观看| 成人开心网精品视频| 久久精品国产999大香线蕉| 亚洲视频一区在线| 久久久久久**毛片大全| 欧美一区二区啪啪| 欧美日韩中文字幕一区| 91国产丝袜在线播放| aaa欧美日韩| 色婷婷综合五月| 色综合天天视频在线观看|