这两天等老师的项目等到脖子都长了,于是乘还没开始那个项目就自己学习了JS的动画效果,然后写了个类似打气球的游戏和一个贪吃蛇的游戏。。。打气球的游戏代码比较简单,现在先打出来。。。如下。。。
  先来张效果图
  就是不断有红色的div方块从浏览器上方落下,然后鼠标点击红色方块就可以消灭它。。。然后记录下分数以及你没有打到的方块个数。。。听起来很简单,其实做起来。。。也很简单。。
  其实js的动画无非就是利用setTimeout方法不断地利用时间间断执行一个动作,时间连贯起来就是动画。。首先要清楚怎么做:
  1.要不断地setTimeout来执行一个可以产生红色方块的函数;
  2.要不断地aetTimeout来执行一个可以让红色方块落下的函数,其实就是不断地改变红色方块的top属性;
  首先看1,在window.onload的时候就执行一次div_init()方法,这个方法就是产生红色“气球”的函数,如下
//div的初始化
function div_init(){
//var left=Math.random()*(document.documentElement.clientWidth||document.body.clientWidth);
if(lose_count>1)//这里判断没打中的个数,lose_count是一个全局变量,开始为0
{alert("您已经输了!重新开始?")}
else
{
//left是红色方块第一次出现距离浏览器最左边的位置
//Math.random()*800限制出现的位置最左只能到800px处
var left=Math.random()*800;
var top=10;//这个是一开始出现的高度,即距离浏览器上方的高度
//接下来动态创建div,并为相应的属性赋值,div这个class如下
//.div{ background-color:#C00; width:30px; height:30px;
//display:inline-block;}
var div=document.createElement('div');
div.className
='div';
div.style.position
='relative';
div.style.top
=top+"px";
div.style.left
=left+"px";
//接下来定义鼠标点击方块的事件,就是把此方块去掉,然后分数增加
div.onclick=function(){
document.body.removeChild(div);
total
+=10;
document.getElementById(
'p').innerHTML="您当前分数为 "+total+"";
}
//最后body添加这个div
document.body.appendChild(div);
//添加div之后,接下来就要令其下落,add_top(object)
//这个方法就是令object不断地下落
add_top(div);
//然后调用setTimeout每一秒钟创建一个红色的div
setTimeout("div_init()",1000);
}
}
  
  请记住div这个类的display:inline-block;如果不是行内块的话,那么每次新建一个div它都会占据一行的位置,那么下一个div出现的位置就要被迫下降一行了。。。这样就不对了。
  接下来是令新建的div不断地下落,也就是那个add_top(div)方法,接下来就是:
//div高度的自动增长
function add_top(div){
//首先得到这个div的top属性的值,并将其转换成数值型
var top=div.style.top;
var top_int=parseInt(top);
//然后top_int加上20,每次执行都会加上20,所以div就会每次都下落
top_int+=20;
div.style.top
=top_int+"px";
//setTimeout("",3000);//setTimeout传参数给函数只能传递字符串,无法传递对象进去
//当下落到某一高度时,比如500的时候,就将其kill掉
if(top_int<500)
{
setTimeout(add_top,
300,div);//这里有变形。。。
}
//这里,超过高度就消失,此时lose_count就加一
else
{
if(div!=null)
{
document.body.removeChild(div);}
lose_count
+=1;
document.getElementById(
'lose').innerHTML="您已经丢失了 "+lose_count+""
}
}
  这个方法还是比较简单的,主要注意
if(top_int<500)
{
setTimeout(add_top,
300,div);//这里有变形。。。
}
  这里将window.setTimeout方法进行重载了,可以传入多个参数,这个地方是重点,因为setTimeout本身是不支持直接函数传参。。。
   例如这样setTime(f(a),1000)如果想要将a参数传进去,不是不行,然而传进去的a最多只能是字符串,而当我想将div整一个对象传进去的时候,是不行,这一点在我实现的过程中卡了我很久,就因为这样,一开始一直都落下一次之后就无法继续下落了。。。然后就去翻书,因为记得以前是在书上看到过的这个改写发。。。
   现将setTimeout改写如下。。。
//先将自带的setTimeout方法保存起来放在一个变量中
var old_sTo = window.setTimeout;
//接下来重载此函数,默认情况下是两个参数
  window.setTimeout = function(fn, mDelay) {
  
//当第一个参数为函数指针的时候
if(typeof fn == 'function'){
  
var argu = Array.prototype.slice.call(arguments,2);
  
var f = (function(){ fn.apply(null, argu); });
  
return old_sTo(f, mDelay);
  }
  
return old_sTo(fRef,mDelay);
  }

  当第一个参数为函数指针的时候,先将传进去setTimeout的参数集合arguments取出来,然后利用call调用数组原型方法slice,并同时将2这个参数传给slice方法,表示将从第三个参数开始利用slice截取获取,slice接受参数只有一个时,将截取从参数开始到最后的数组,这里就从2下标开始,就是第三个参数,因为我们不知道调用方法的时候会传入多少个参数,默认是2个参数,所以如果有多的话就这样子选出来,给数组变量arug。如果看到这里还是卡住了,没办法,那就只能补一补call和arguments方面的知识了。。。
  取出来多余参数之后,这些参数就是将要传入给fn函数的参数,然后新建一个函数指针var f = (function(){ fn.apply(null, argu); });这句可能又比较费解了。。。
  apply和call一样原理,不过就是后面的参数是数组类型的,这时候刚好将之前得到的arug参数数组传入。。将参数传给fn函数,然后封装成一个function传递给f这个新函数指针。。。
  最后再调用old_sTo,也就是原来的setTimeout方法,这个时候f已经将所需要的参数arug传进去了。
  如果一开始传进去的不是方法指针,而是执行的语句,那就按原来那样子去执行。。。
  到这里结束了,这样当setTimeout接收2个参数的时候,就按原来的方法执行,当传入多余2个参数的时候,多的参数就作为fn的参数。。。
  setTimeout(add_top,300,div);所以最后这里,传多一个div的参数,是一个对象,这个对象参数就会传递给add_top函数指针,然后执行。。。
  所有代码就这三个亮点,解决了,就over了,关于如何优化并美化的问题,这些是后期的事了。。。
  完了。