就是缘于此,能够玩飞机、俄国方块、贪吃蛇等

在火车上,为了消磨时间,我起来了写JS小游戏的陈设。就先从贪吃蛇那种最简易的初阶写起吧。

正文是苏福的原创作品,转发请注明出处:苏福CNblog:http://www.cnblogs.com/susufufu/p/5875523.html

那位用JAVASCRIPT写出顶级玛丽的牛人,值得学习。我这里用li标记来模拟红白机中镜头的像素点的想法,就是出自此。

该程序是自家的个人创作,写的不得了,未经自己同意,请不要用来其他用途!

贪吃蛇的游玩相信80后的心上人小时候都玩过,记得自己童年还攒了二十多块钱买了个游戏机(一个礼拜2块的零花钱!),可以玩飞机、俄联邦方块、贪吃蛇等,刚开首玩的真舒服,无奈太费电池,玩不起,放一段时间居然显示器充裕了!哎!
点击查看演示:

苏福的创作:贪吃蛇

始发游戏

贪吃蛇没什么游戏规则,就是转转转、吃吃吃!我就定义了一个类Snake,想用面向对象来写,不明了写的像不像!请前辈多多指点

//====Snake类
            var Snake = function () {
                this.score = 0;
                this.speed = 10;
                this.levle = 0;
                this.snakeHead = this.createBlock('snake-head',block);
                this.snake = [this.snakeHead]; //将蛇头作为蛇体的第一个元素
                this.food = this.createBlock('food',block);
            };

贪吃蛇的游戏规则:

  • 吃掉一个食物,蛇长自动+1;
  • 蛇头撞到边缘或蛇身则游戏甘休;
  • 用方向键控制移动方向,必要有抛锚游戏效果;

本条娱乐的筹划难题有那多少个:

  1. 蛇的活动方向随方向键的改观
  2. 蛇身种种部分的移动
  3. 蛇身移动进程中不止的判断是还是不是撞墙、是否吃到食品。

蛇的移动方向的转移自我定义了一个静态属性Snake.headDirection = {x:1,y:0};,用来保存当前意况,x、y的取值范围为1、0、-1,x和y不会同时为零,x为零时意味着如今垂直运动,可以往左(y:1)或往右(y:-1),y为零时代表水平位移,可以往上(x:1)或往下(x:-1)。为此我把方向键的风云回调函数设计成类似状态机的函数:

document.onkeydown = function (event){
                var e = event||window.event;
                var key = e.keyCode;
                switch (key){
                    case 38:
                        if(Snake.headDirection.x === 0){return;} //判断是否是垂直移动
                        Snake.headDirection.y = 1;
                        Snake.headDirection.x = 0;
                        break;
                    case 40:
                        if(Snake.headDirection.x === 0){return;}
                        Snake.headDirection.y = -1;
                        Snake.headDirection.x = 0;
                        break;
                    case 37:
                        if(Snake.headDirection.y === 0){return;} //判断是否是水平移动
                        Snake.headDirection.x = 1;
                        Snake.headDirection.y = 0;
                        break;
                    case 39:
                        if(Snake.headDirection.y === 0){return;}
                        Snake.headDirection.x = -1;
                        Snake.headDirection.y = 0;
                        break;
                }
            };

上面是创办蛇头或蛇身的共有函数,因为蛇头、蛇身都是由同样的四方构成,那里自己事先在HTML文件里就创建了一个四方“,通过css把它藏在标题栏的下面,然后以后蒙受要制造蛇头、蛇身的时候就克隆一个并在给定随机地方后添加到游戏窗口,省的每趟都运行创制元素的代码:具体看代码注释

Snake.prototype.createBlock = function (id,block) {
                var bk = block.cloneNode(false),x = getRandom(600),y = getRandom(400);
                bk.id = id;
                setElemXY(bk,x,y); //该方法用来设置元素的lef、top
                gameWindow.appendChild(bk);
                return bk;
            };

接下去是蛇的位移、吃食物、撞墙:当蛇头的岗位等于食品的职分时,启动吃食品函数;当蛇头的下次活动的坐标在游戏窗口之外时,就判断撞墙,游戏停止;

//移动蛇身,并判断是否吃到食物,或吃到自己,或撞墙
            Snake.prototype.moving  = function () {
                //吃到食物
                var head = getElemXY(this.snakeHead), food = getElemXY(this.food);
                if(head.x === food.x && head.y === food.y){
                    this.eat(this.food);
                    this.food = this.createBlock('food',block);
                }
                //移动、撞墙
                var x = Snake.headDirection.x, y = Snake.headDirection.y;
                //x等于0说明当前垂直移动,如果y等于1,说明在向左移动,所以head.y即元素的left-10px;y等于零时同理
                if(x === 0){ 
                    y === 1 ? head.y-=10 : head.y+=10;
                    if(head.y<0||head.y>400){this.gameOver();return;}
                }
                if(y === 0){
                    x === 1 ? head.x-=10 : head.x+=10;
                    if(head.x<0||head.x>600){this.gameOver();return;}
                }

                var len = this.snake.length;
                for(var i = len-1 ; i>0 ; i--){
                    var nowXY = getElemXY(this.snake[i]);
                    if(head.x === nowXY.x && head.y === nowXY.y){this.gameOver();return;} //吃到自己
                    var preXY = getElemXY(this.snake[i-1]);
                    setElemXY(this.snake[i],preXY.x,preXY.y); //将每个蛇节都移到它的前一个的位置
                }
                setElemXY(this.snakeHead,head.x,head.y); //舌头移动到新位置

                timeId = setTimeout(function () {
                    this.moving();
                //这里用bind绑定this,不然无法调用this.moving(),不支持bind的话只能外层加个匿名函数来传参了
                }.bind(this),1000/this.speed);  
            };

上面是吃食品函数,那几个函数相比较简单,首要看后边几行代码,将食品的职分改为蛇身的末段一个节点的职位,并把它添加进蛇的数组,便于全部移动

//吃食物,并更新游戏成绩
            Snake.prototype.eat = function (food) {
                this.levle++;
                this.speed+=0.4;
                this.score+=5*this.speed;
                levelInfo.innerHTML = '等级: '+this.levle;
                speedInfo.innerHTML = '速度: '+this.speed.toFixed(2);
                scoreInfo.innerHTML = '成绩: '+this.score;
                maxScore = Math.max(maxScore,this.score);
                maxScoreInfo.innerHTML = '最高成绩: '+maxScore;
                var oldLast = getElemXY(this.snake[this.snake.length-1]);
                setElemXY(food,oldLast.x,oldLast.y);
                this.snake.push(food);
            };

大概就是以上这个代码了,此外还有几个不难的公物函数,就隐瞒了,自己查看源码。

重大游戏元素:

  • 蛇;
  • 食物;
  • 舞台;

那里我要说的一点体验:给函数、变量命名的时候肯定要语义化,一看就能大约知道那一个函数、变量是怎么的,那样才不会自乱了阵脚,更别提和别人合营了!(不要用拼音,你不以为low的话也行,我是不懂就查翻译,多多少少也能增进点乌克兰语水平吧,呵呵,我斯拉维尼亚语水平也是很菜,惭愧!)

根本思路及算法:

  • 布局的戏台,很醒目是一个固定大小的二维数组;
  • 蛇通过持续吃食品可以变动自身长度,所以应该是一个尺寸可变的二维数组;
  • 食品、蛇可以出现在全部舞台的随机地点,可以透过改动其坐标值来改变地方;

接下去看有的代码:

snake.unshift([nextX,nextY])
if(aLi[nextX][nextY].className==_options.classFood){
    _createFood();
}else{
    aLi[snake[nSnakeLen][0]][snake[nSnakeLen][1]].className='';
    snake.pop();
}

 

这一部分是百分之百游戏最基本的代码,snake数组在每趟活动的时候,它的首先个节点都会攻占那些像素点,所以这一个数组就是unshift([蛇头像素点坐标])。假设那一个点是食品那么,继续生成食品,蛇身则早就由此unshift自动+1;尽管那几个点不是食物,那么删除蛇尾的像素点,从而保证蛇身长度不变,已毕了蛇的移动效果。

其余一些相比较关键的,通过方向键改变蛇身移动方向。考虑到蛇本身是含有一多级坐标值的二维数组,只需给它的值在横向或纵向上+1或-1,即可左右移动一个像素的职位。

//移动方向、预载移动方向
    var direction = preDirection = [0,1];
    var nextX = snake[0][0]+direction[0];
    var nextY = snake[0][1]+direction[1];

 

 

重点函数方法,我都在源代码里写上了诠释。即使游戏用了组件封装的写法,但是实在都是原生写法,所以依旧有改革之处。有BUG欢迎提议来。

点此查看游戏演示DEMO