请选择 进入手机版 | 继续访问电脑版

JS学习笔记——原生js贪吃蛇

[复制链接]
冰宇 发表于 2020-12-31 18:57:39 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
目前处于学习阶段,学习的总结,如果有错误的地方,还请指出指教!
把界面分成30*30个小方格,蛇头、身子和食物分别占据一个小方格。
界说全局变量

  1. // 全局变量var sw = 20,    // 一个方块的宽度    sh = 20,    // 一个方块的高度    tr = 30,    // 行数    td = 30;    // 列数var snake = null,   // 蛇的实例    food = null,    // 事物实例    game = null;    // 游戏实例
复制代码
创建小方格的构造函数

css文件设置了小方格样式,分别有蛇头、身子和食物,通过传入差别的class属性值来实现。
参数:
x:x轴坐标(通篇原点为左上角起始点)
y:y轴坐标
classname:class属性值
  1. function Square(x, y, classname){    this.x = x * sw;    this.y = y * sh;    this.class = classname;    this.viewContent = document.createElement('div');   // 创建方块对应的dom元素    this.viewContent.className = this.class;    this.parent = document.getElementById('snakeWrap'); // 获取方块的父级}
复制代码
添加到页面方法(创造一个小方格):

这里this是Square
  1. Square.prototype.create = function(){    this.viewContent.style.position = 'absolute';                // 开启绝对定位    this.viewContent.style.width = sw + 'px';                        // 设置宽度    this.viewContent.style.height = sh + 'px';                        // 设置高度    this.viewContent.style.left = this.x + 'px';                // 设置偏移量    this.viewContent.style.top = this.y + 'px';                        // 设置偏移量    this.parent.appendChild(this.viewContent);                        // 把要创建的节点添加到父元素中};
复制代码
从页面中移除方法:

  1. Square.prototype.remove = function(){    this.parent.removeChild(this.viewContent);};
复制代码
创建蛇的构造函数

初始设置有一个蛇头两个圆形身体,占三个小方格,在之后的移动中,我们把它看成一个整体,用链表举行实现。
  1. function Snake(){    this.head = null;   // 存蛇头的信息    this.tail = null;   // 存蛇尾的信息    this.pos = [];      // 存储蛇身上的每一个方块的位置    this.dirctionNum = {    // 存储蛇走的方向,用一个对象来表现        left : {            x : -1,            y : 0,            rotate : 180        },        right : {            x : 1,            y : 0,            rotate : 0        },        up : {            x : 0,            y : -1,            rotate : -90        },        down : {            x : 0,            y : 1,            rotate : 90        }     }}
复制代码
初始化蛇方法:

  1. Snake.prototype.init = function(){    // 创建蛇头    var snakeHead = new Square(2,0,'snakeHead');    snakeHead.create();    this.head = snakeHead;      // 存储蛇头的信息    this.pos.push([2,0]);       // 把蛇头的位置存起来    // 创建蛇身体1    var snakeBody1 = new Square(1, 0, 'snakeBody');    snakeBody1.create();    this.pos.push([1,0]);    // 创建蛇身体2    var snakeBody2 = new Square(0, 0, 'snakeBody');    snakeBody2.create();    this.tail = snakeBody2;    this.pos.push([0,0]);    // 形成链表关系    snakeHead.last = null;    snakeHead.next = snakeBody1;    snakeBody1.last = snakeHead;    snakeBody1.next = snakeBody2;    snakeBody2.last = snakeBody1;    snakeBody2.next = null;    // 蛇头要走的方向    this.direction = this.dirctionNum.right;    // 默认让蛇往右走}
复制代码
蛇头即将下一个位置各情况判断方法

  1. Snake.prototype.getNextPos = function(){    // 蛇头要走的下一个点的坐标    var nextPos = [        this.head.x / sw + this.direction.x,        this.head.y / sh + this.direction.y    ]    // 下个点是自己,代表撞到自己,游戏竣事    var selfCollied = false;    // 是否撞到自己标识    this.pos.forEach(function(value){        if (value[0] == nextPos[0] && value[1] == nextPos[1]){            selfCollied = true;        }    });    if (selfCollied){        this.strategies.die.call(this);        return;    }    // 下一个点是围墙,游戏竣事    if (nextPos[0] < 0 || nextPos[1] < 0 || nextPos[0] > td - 1 || nextPos[1] > tr - 1){        this.strategies.die.call(this);        return;    }    // 下一个是食物,吃    if (food && food.pos[0] == nextPos[0] && food.pos[1] == nextPos[1]){        this.strategies.eat.call(this);        return;    }    // 下一个点不特殊,走    this.strategies.move.call(this);};
复制代码
碰撞后处理处罚方法:

若直接调用
  1. this.strategies.move();
复制代码
此时,下面代码中this指向的是Snake.prototype,若想this指向Snake则需要用call方法调用(上面代码便是如此)。
  1. this.strategies.move.call(this);
复制代码
  1. Snake.prototype.strategies = {    // 参数决定删不删除蛇尾    // 当传参后就表现吃,不删蛇尾    move : function(format){        // 创建新身体(在旧蛇头的位置)        var newBody = new Square(this.head.x / sw, this.head.y / sh, &#39;snakeBody&#39;);        // 更新链表的关系        newBody.next = this.head.next;        newBody.next.last = newBody;        newBody.last = null;        this.head.remove();     // 把旧蛇头从原来的位置删除        newBody.create();        // 创建一个新蛇头(蛇头下一个要走的点即nextPos)        var newHead = new Square(this.head.x / sw + this.direction.x, this.head.y / sh + this.direction.y, &#39;snakeHead&#39;)        // 更新链表关系        newHead.next = newBody;        newHead.last = null;        newBody.last = newHead;        newHead.viewContent.style.transform = &#39;rotate(&#39;+this.direction.rotate+&#39;deg)&#39;;                newHead.create();        // 更新坐标        this.pos.splice(0,0,[this.head.x / sw + this.direction.x, this.head.y / sh + this.direction.y])        this.head = newHead;        // format值为false,表现需要删除        if (!format){            this.tail.remove();            this.tail = this.tail.last;            this.pos.pop();        }    },    eat : function(){        this.strategies.move.call(this,true);                // 吃到食物,使蛇身长一个单元,故传入true参数,不需要把蛇尾删除        createFood();        game.score++;                                                                // 得分    },    die : function(){        game.over();    }}
复制代码
创建食物

  1. function createFood(){    // 食物小方块随机坐标    var x = null;    var y = null;    var include = true;     // 循环跳出条件,true表现食物的坐标在蛇身上(需要继承循环)    while (include){        x = Math.round(Math.random() * (td - 1));        y = Math.round(Math.random() * (tr - 1));        snake.pos.forEach(function(value){            if (x != value[0] && y != value[1]){                                include = false;            }        })    }    // 生成食物    food = new Square(x, y, &#39;food&#39;);    food.pos = [x, y];      // 存储一下食物坐标    // 永远是第一次创建的食物,改变left,top值,不需要移除再创建    var foodDom = document.querySelector(&#39;.food&#39;)    if (foodDom){        foodDom.style.left = x * sw + &#39;px&#39;;        foodDom.style.top = y * sh + &#39;px&#39;;    } else{        food.create();    }}
复制代码
创建游戏逻辑构造函数

  1. function Game(){    this.timer = null;    this.score = 0;}
复制代码
初始化方法

  1. Game.prototype.init = function(){    snake.init();    createFood();    document.onkeydown = function(event){        event = event || window.event;        // 按键按下        if (event.key == &#39;ArrowLeft&#39; && snake.direction != snake.dirctionNum.right){            snake.direction = snake.dirctionNum.left;        } else if (event.key == &#39;ArrowUp&#39; && snake.direction != snake.dirctionNum.down){            snake.direction = snake.dirctionNum.up;        } else if (event.key == &#39;ArrowRight&#39; && snake.direction != snake.dirctionNum.left){            snake.direction = snake.dirctionNum.right;        } else if (event.key == &#39;ArrowDown&#39; && snake.direction != snake.dirctionNum.up){            snake.direction = snake.dirctionNum.down;        }    };    this.start();};
复制代码
游戏开始方法

通过定时器每隔一段时间获取下一个蛇头位置,来让蛇自动前进
  1. Game.prototype.start = function(){    this.timer = setInterval(function(){        snake.getNextPos();    },200);};
复制代码
游戏暂停方法

把定时器清除
  1. Game.prototype.pause = function(){    clearInterval(this.timer);}
复制代码
游戏死亡方法

清除定时器,而且设置成最开始状态
  1. Game.prototype.over = function(){    clearInterval(this.timer);    alert(&#39;你的得分为:&#39;+this.score);    // 游戏回到最初始状态    var snakeWrap = document.getElementById(&#39;snakeWrap&#39;);    snakeWrap.innerHTML = &#39;&#39;;    snake = new Snake();    game = new Game();    var startBtnWrap = document.querySelector(&#39;.startBtn&#39;);    startBtnWrap.style.display = &#39;block&#39;;};
复制代码
开启游戏

  1. game = new Game();var startBtn = document.querySelector(&#39;.startBtn button&#39;);startBtn.onclick = function(){    startBtn.parentNode.style.display = &#39;none&#39;;    game.init();};
复制代码
暂停游戏

  1. var snakeWrap = document.getElementById(&#39;snakeWrap&#39;);var pauseBtn = document.querySelector(&#39;.pauseBtn button&#39;);snakeWrap.onclick = function(){    game.pause();    pauseBtn.parentNode.style.display = &#39;block&#39;;}
复制代码
点击继承

  1. pauseBtn.onclick = function(){    game.start();    pauseBtn.parentNode.style.display = &#39;none&#39;;};
复制代码
代码在下篇文章中。
纪录学习过程,请指点!

来源:https://blog.csdn.net/smile981005/article/details/111816019
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


专注素材教程免费分享
全国免费热线电话

18768367769

周一至周日9:00-23:00

反馈建议

27428564@qq.com 在线QQ咨询

扫描二维码关注我们

Powered by Discuz! X3.4© 2001-2013 Comsenz Inc.( 蜀ICP备2021001884号-1 )