为了账号安全,请及时绑定邮箱和手机立即绑定

HTML5小游戏---爱心鱼(上)

难度中级
时长 2小时34分
学习人数
综合评分9.50
139人评价 查看评价
9.6 内容实用
9.5 简洁易懂
9.4 逻辑清晰
  • 6,在born方法中随机给fruitType赋值: 我们该如何区别果实的类型呢?我们需要给果实类增加一个属性: //果实类型 this.fruitType=[]; 这个变量是个character类型,我们在初始化的时候,给它一个空的字符串:this.fruitType[i]=""; 当它出生的时候呢,我们再具体给它一个类型。用两个字符串,一个是orange,一个是blue,用颜色 这两个字符串来区别它的属性fruitType: fruitObj.prototype.born=function(i){ var aneId=Math.floor(Math.random()*ane.num); this.x[i]=ane.x[aneId]; this.y[i]=canHeight-ane.len[aneId]; this.l[i]=0; this.alive[i]=true; this.fruitType[i]= //orange,blue } 我们做一个随机: fruitObj.prototype.born=function(i){ var aneId=Math.floor(Math.random()*ane.num); this.x[i]=ane.x[aneId]; this.y[i]=canHeight-ane.len[aneId]; this.l[i]=0; this.alive[i]=true; var ran=Math.random(); if(ran<0.3){ this.fruitType[i]="blue"; //orange,blue }else{ this.fruitType[i]="orange"; } }
    查看全部
  • 5,chrome浏览器特性使得果实变大 好的,另一个细节是果实分黄色的果实和蓝色的果实。两种不同的果实,这两种果实的 区别呢,就是它的图片资源不一样,同时在功能上是这样子的,假设大鱼吃到了一个黄色的 果实,假设它得10分,那么蓝色的果实呢,可以使它当前吃到的黄色果实的数量加倍,ok,关于 这个功能这方面我们先不管,到后面我们去计算的它的score的时候再说,现在我们需要把黄色 果实和蓝色果实让它能够有所区别,刚才为什么会出现一个特别大的果实呢?这是chrome浏览器的 特性,当你不再当前标签下面的时候,它就会有时间间隔啊,它会有一个不执行的状态,当我切过来 的时候,这个标签页下的东西实际上是不执行的,所以会导致那个deltaTime会特别的大,那这个问题 大家可以不用管它,
    查看全部
  • 4,修改speed,让它的范围更大,使得果实快慢差距变大 好,我们到浏览器中看一下:可以看到有果实出来了,一开始的时候还是会产生一大片 然后后面就看起来比较自然了,那我们再修改一下数值吧。让它的speed状态随机的范围 更大一点: fruitObj.prototype.init=function(){ for(var i=0;i<this.num;i++){ this.alive[i]=false; this.x[i]=0; this.y[i]=0; this.l[i]=0; this.spd[i]=Math.random()*0.017+0.003;//[0.003,0.02) } this.orange.src="./src/fruit.png"; this.blue.src="./src/blue.png"; } 好,再看一下,好的,现在快慢差距会非常的大
    查看全部
  • 3.修改init方法,将fruitMonitor放在gameloop中。 好,ok,那我们初始化的时候,这里把所有的状态设置为false:this.alive[i]=false; fruitObj.prototype.init=function(){ for(var i=0;i<this.num;i++){ this.alive[i]=false; this.x[i]=0; this.y[i]=0; this.l[i]=0; this.spd[i]=Math.random()*0.01+0.005;//[0.005,0.015) /* 这个意思就是说:在初始化的时候,让所有的果实都出生,出生的过程呢,就是 找到一个位置让它出生, this.born(i);*/ } this.orange.src="./src/fruit.png"; this.blue.src="./src/blue.png"; } 同时我们需要把这个函数fruitMonitor放在主循环里面,每一帧都要进行判断: function gameloop(){ window.requestAnimFrame(gameloop); var now=Date.now(); deltaTime=now-lastTime; lastTime=now; drawBackground(); ane.draw(); fruitMonitor(); fruit.draw(); }
    查看全部
  • 2.修改born方法,增加发出果实方法:sendFruit。 但是在这里还有一个细节,在整个30个果实池里面,哪一个是处于 闲置状态,哪一个是活着的,需要去判断一下,这里还是做一个循环: 如果当前果实的状态是false,就要让这个果实出生,这里需要传一个参数进来,这个i值对应的 果实出生,它要随机一个海葵的位置,而后它的尺寸归零,同时它的alive状态要设置为true。 fruitObj.prototype.born=function(i){ var aneId=Math.floor(Math.random()*ane.num); this.x[i]=ane.x[aneId]; this.y[i]=canHeight-ane.len[aneId]; this.l[i]=0; this.alive[i]=true; } 当它出生之后呢,本次循环结束。每次sendFruit()只要send一个fruit。然后下一次再进入循环。 function sendFruit(){ for(var i=0;i<fruit.num;i++){ if(!fruit.alive[i]){ fruit.born(i); return; } } }
    查看全部
  • 那我们再来看一下游戏机制: 1,给果实添加监视功能:fruitMonitor方法。 我们所有的果实并不是一切全部出生,漂上去,然后就完了,而是持续不断的产生果实, 保持屏幕上有一定数量的果实,所以给它加一个规则:这个规则是这样的: 保持屏幕上有一定数量的果实,比如15个,所以我们一开始初始化的时候,不应该让所有的果实 都出生,而是要有一个机制去判断,我们来给果实添加一个监视功能吧。 我们要判断一下当前屏幕上有多少个果实是活着的,如果它的状态是true,我们要做一个数据统计。 num++如果数量少于15个,发出一个果实,让果实出生,并且当前的功能执行完毕,怎么让它发出一个 果实呢,就是让它执行一下born方法。 function fruitMonitor(){ var num=0; for(var i=0;i<fruit.num;i++){ if(fruit.alive[i]) num++; } if(num<15){ //send fruit sendFruit(); return; } }
    查看全部
  • 5,给果实动作增加alive限制: 飘出去了我们要做一个判断,飘出去之后,这个果实的使命就已经完成了。它的任务就完成了,所以它 要回到一个待命状态,ok,我们再来做一个检测:如果它的y坐标小于10,它的alive状态 就要变成false,那么只有它的alive状态为true的时候,才做上面这些事情(就是生长,往上漂,并且绘制) 所以我们要在for循环的最顶端加一个条件,如果它的alive状态是true,那么就做这所有的事情(生长,往上漂 并且绘制果实,绘制果实是在gameloop函数中会循环绘制,再有每次绘制果实的参数都是在一定范围内随机的), 包括alive的检测: fruitObj.prototype.draw=function(){ for(var i=0;i<this.num;i++){ if(this.alive[i]){ if(this.l[i]<=14){ //果实生长时果实长度的变化情况 this.l[i] += this.spd[i]*deltaTime; }else{ //果实往上漂的速度的变化情况 this.y[i] -= this.spd[i]*7*deltaTime; } ctx2.drawImage(this.orange,this.x[i]-this.l[i]*0.5, this.y[i]-this.l[i]*0.5,this.l[i],this.l[i]); if(this.y[i]<10){ this.alive[i]=false; } } } } 刷新浏览器,好的,没有出现bug。
    查看全部
  • 4,增加果实速度属性改变果实生长、往上漂动作的速度: 我们给它个性化一下,每一个果实都有它独特的速度,给果实类添加一个属性spd,speed速度。 //果实的速度 this.spd=[]; 这个速度既是果实成长的速度,也是果实往上漂的速度,在init方法里,给果实的速度 初始化一下,给它一个任意值:(其实这里的值并不是任意的,是在前面调整好的值的基础上,将spd做成随机 生成的,但还是在原来测试值的附近波动,其作用就是既能保证每一个果实生长和往上漂的速度不一样,又能 保持原来果实生长和往上漂的速度在一个范围内,不会太快,也不会太慢,总而言之,就是让果实从生长到 往上漂既能不失真又能不拘泥,不死板) init方法: fruitObj.prototype.init=function(){ for(var i=0;i<this.num;i++){ this.alive[i]=true; this.x[i]=0; this.y[i]=0; this.l[i]=0; this.spd[i]=Math.random()*0.01+0.005;//[0.005,0.015) this.born(i); } this.orange.src="./src/fruit.png"; this.blue.src="./src/blue.png"; } draw方法: fruitObj.prototype.draw=function(){ for(var i=0;i<this.num;i++){ if(this.l[i]<=14){ //果实生长时果实长度的变化情况 this.l[i] += this.spd[i]*deltaTime; }else{ //果实往上漂的速度的变化情况 this.y[i] -= this.spd[i]*7*deltaTime; } ctx2.drawImage(this.orange,this.x[i]-this.l[i]*0.5, this.y[i]-this.l[i]*0.5,this.l[i],this.l[i]); } } 刷新浏览器,看一下,现在果实都有各自不同的速度,都飘出去了。
    查看全部
  • 3,实现果实往上漂,但是动作都一致,看起来很傻: 往上漂这个原理的本质就是果实的y坐标在逐渐的减小,所以当果实图片的长度大于14的时候 做如下改变: fruitObj.prototype.draw=function(){ for(var i=0;i<this.num;i++){ if(this.l[i]<=14){ this.l[i] += 0.01*deltaTime; }else{ this.y[i] -= 0.01*deltaTime; } ctx2.drawImage(this.orange,this.x[i]-this.l[i]*0.5, this.y[i]-this.l[i]*0.5,this.l[i],this.l[i]); } } 好,我们刷新一下,好,果实在往上漂了对不对,这个速度太小了。作如下改变: fruitObj.prototype.draw=function(){ for(var i=0;i<this.num;i++){ if(this.l[i]<=14){ this.l[i] += 0.01*deltaTime; }else{ this.y[i] -= 0.1*deltaTime; } ctx2.drawImage(this.orange,this.x[i]-this.l[i]*0.5, this.y[i]-this.l[i]*0.5,this.l[i],this.l[i]); } } 恩,这个速度太大了,又做如下改变:0.07 fruitObj.prototype.draw=function(){ for(var i=0;i<this.num;i++){ if(this.l[i]<=14){ this.l[i] += 0.01*deltaTime; }else{ this.y[i] -= 0.07*deltaTime; } ctx2.drawImage(this.orange,this.x[i]-this.l[i]*0.5, this.y[i]-this.l[i]*0.5,this.l[i],this.l[i]); } } 刷新,好,差不多,一直上去了,其实这样子很难看的,果实向上漂的动作都是一致的,看起来很傻。
    查看全部
  • 2,通过增约束条件,果实生长不再疯长: 果实现在越来越大。我们需要判断一下: 在draw方法的for循环中做如下改变: fruitObj.prototype.draw=function(){ for(var i=0;i<this.num;i++){ if(this.l[i]<=10){ this.l[i] += 0.01*deltaTime; } ctx2.drawImage(this.orange,this.x[i]-this.l[i]*0.5, this.y[i]-this.l[i]*0.5,this.l[i],this.l[i]); } } 我们再到浏览器中看一下:现在是果实长到一定程度就不长了。再调整一下这个值: 让果实的长度大于14就不再长大了。 fruitObj.prototype.draw=function(){ for(var i=0;i<this.num;i++){ if(this.l[i]<=14){ this.l[i] += 0.01*deltaTime; } ctx2.drawImage(this.orange,this.x[i]-this.l[i]*0.5, this.y[i]-this.l[i]*0.5,this.l[i],this.l[i]); } } 好,大家可以看到果实是慢慢变大,现在已经长成熟了,这个时候它需要往上漂,
    查看全部
  • 接下来继续细化果实的状态: 1,果实变的太大,太恐怖: 首先果实出生的时候,是由小慢慢长大的,这个过程我们需要来控制一下,这个原理很简单,是一开始绘图的时候, 绘一个很小的图片,然后慢慢的让这个尺寸加大,我们需要给果实类加一个属性: //果实图片的长度 this.l=[]; l初始化的时候是0, 那么果实在出生的时候长度l也是0;因为即便不是初始化,果实在每次刚出生的时候,这个l也要重置一下, 这个l会随着时间逐渐的增长,在draw方法的for循环中,给l加一个常数0.01:this.l[i] += 0.01; 这里需要调整一下成长的速度,这里也是我们第一次用到这个值deltaTime,deltaTime是什么呢? 我们前面讲过:就是每两帧之间的时间间隔。它是用来保证游戏里面动作的流畅,连贯,当你用到一个 随时间变化的变量的时候,一定要使用deltaTime使这个过程变得平滑, 在draw方法的for循环中做如下改变: fruitObj.prototype.draw=function(){ for(var i=0;i<this.num;i++){ this.l[i] += 0.01*deltaTime; ctx2.drawImage(this.orange,this.x[i]-this.l[i]*0.5, this.y[i]-this.l[i]*0.5,this.l[i],this.l[i]); } } 其中drawImage方法的第4个参数和第5个参数是规定绘制这个图片的尺寸。 在浏览器中刷新一下,可以看到果实在慢慢长大,不过挺恐怖的,它现在越来越大。我们需要判断一下:
    查看全部
  • 7,果实类定义:都是属性的定义: var fruitObj=function(){ this.alive=[];//bool //果实坐标 this.x=[]; this.y=[]; //果实的图片资源 this.orange=new Image(); this.blue=new Image(); }
    查看全部
  • 6,果实类的初始化方法: /* 另外还要初始化一下。初始化的时候还要给池子里面的每一个果实,要告诉它,它是什么状态。 我们首先初始化的时候,给它是否活着的属性一种任务状态,即初始化为真。 */ fruitObj.prototype.init=function(){ for(var i=0;i<this.num;i++){ this.alive[i]=true; this.x[i]=0; this.y[i]=0; /* 这个意思就是说:在初始化的时候,让所有的果实都出生,出生的过程呢,就是 找到一个位置让它出生, */ this.born(i); } this.orange.src="./src/fruit.png"; this.blue.src="./src/blue.png"; }
    查看全部
  • 5,果实的draw方法: /* 哦,另外我们还要画果实。我们这边就要画每一个果实了。它有两个状态,首先是 长在海葵上面,因为果实的数量要比海葵的数量要小,所以我们不用很担心,即便会 有重复,我们先不去管它,ok。我们先做一个循环,在这个循环里面,画果实。 怎么画果实?果实首先要找到一个定位,找到一个海葵,然后grow,长了之后呢 就开始漂了,网上漂fly up。我们首先find an ane,这个时候我们如何找呢? 当前的这个果实要生长在哪里呢?我们直接写一个born函数。 把draw放在gameloop的循环里面。然后到浏览器中看一下情况如何。看, 所有的果实已经在位置上了。只是这个位置有点点偏差。你看这个果实的 位置和这个海葵的位置是不对的,这是为什么呢?因为drawImage这个API呢 它绘制的时候,是从图片的0,0点(即图片的左上角)开始的, 所以这个地方,x值的坐标需要减去这个图片的宽度的一半,同样的,y值的坐标也要减去图片高度的一半。 ctx2.drawImage(this.orange,this.x[i]-this.orange.width*0.5,this.y[i]-this.orange.height*0.5); 来到浏览器中看一下,这样就很好了,每个果实都长在海葵上面,也就是说 大家现在看到的不是30个。这是为什么?因为有重叠,我们没有给它做一个 排除。问题在这个地方,我们是找的随机值,这个随机的时候是会出现重复的: var aneId=Math.floor(Math.random()*ane.num); 怎么样排除重复呢?那就是给海葵做一个记录,判断一下它当前有没有被 占用,如果没有被占用,这个果实就可以生成在这个海葵上,如果这个海葵 上面已经有了一个果实,就找下一个海葵。 */ fruitObj.prototype.draw=function(){ for(var i=0;i<this.num;i++){ /* 我们首先不管果实大小,先把它画上去,再说,我们当前的任务呢是让果实出生, */ ctx2.drawImage(this.orange,this.x[i]-this.orange.width*0.5,this.y[i]-this.orange.height*0.5); } }
    查看全部
  • 4.1 果实的born方法: fruitObj.prototype.born=function(i){ var aneId=Math.floor(Math.random()*ane.num); this.x[i]=ane.x[aneId]; this.y[i]=canHeight-ane.len[aneId]; }
    查看全部

举报

0/150
提交
取消
课程须知
1、对html、css基础知识已经掌握。 2、对JavaScript的基础知识掌握,如数组、类、对象。
老师告诉你能学到什么?
1、html5 canvas制作游戏理念 2、html5 canvas 绘图API 3、游戏中的碰撞检测 4、认识几个数学函数 5、物体池概念 6、序列帧动画的控制

微信扫码,参与3人拼团

意见反馈 帮助中心 APP下载
官方微信
友情提示:

您好,此课程属于迁移课程,您已购买该课程,无需重复购买,感谢您对慕课网的支持!