一直都觉得javascript可以玩得很cool。所以终于尝试了使用js来写了一个小游戏,界面上其实也没什么特色~~普普通通吧,paperen将这个游戏取名为(untouchable)不可触及,游戏规则其实很简单,不要让那个按钮与那些飞来飞去的小球发生碰撞,看你能熬到多少秒。

20110521142514

 untouchable游戏地址  http://paperen.com/demo/collision/

关于游戏说明在这个地址都会有的啦,很简单自己玩下就了解了。而这个游戏的源代码全部都在页面上了,自己查看源代码就有了,所以可以说javascript与css都是开源的~~

关于这个游戏的js代码,paperen实在不能解析太多,什么都在代码中了,有兴趣的人一看就明白了,在这里就说一下paperen在写js过程中一些思路的东西吧。

1.整个游戏明显是有两种对象存在的,弹来弹去的小球(单选框radio)与那个带有郁闷表情的控制块(按钮button |-_-|)所以我分别写了两个类ball与block。而各自都有自己一些方法与参数,现在想想貌似可以将它们之间的一些公共特性抽出来作为一个类的,而ball与block可以去继承这个父类~~

2.关于小球的反弹效果,可以看一下ball中的Run与changeDirection方法。

paperen将北,东北,东,东南,南,南西,西,西北用了1,2,3,4,5,6,7,8表示。

changeDirection的第一个参数是代表x轴上的方向,第二个参数是y轴的方向,(-1,0)代表将向x轴的0方向运动,(1,0)将向x轴的无穷方向运动,(0,-1)代表将向y轴的0方向运动,(0,1)代表将向y轴的无穷方向运动。

之后就是一开始定义的速度根绝方向对小球的left与top进行调整了,setPosition方法。可能这里paperen搞得比较繁琐……

3.关于控制块的跟踪鼠标行为其实是绑定了一个事件

if ( IE ) {
document.onmousemove = control_block;
} else {
EventUtil.addListener( window, "mousemove", control_block );
}

当触发mouseover的时候就会执行control_block,具体如何获得鼠标的x与y具体看 control_block吧,  记得要减去游戏区域的x,y与控制块的宽度/2,高度/2(因为要让鼠标处于控制块的中心位置)

4.使用魔法效果(隐身),其实一开始是创建了两个控制块。

//向区域加入控制块
tmp = new block();
block_instance.push( tmp.create(1).initPosition() );
tmp = new block();
block_instance.push( tmp.create(2).iMagic().initPosition() );

注意第二个控制块使用create后又调用了iMagic的方法,来声明这是魔法块。给控制块绑定click事件(在create的时候)useMagic,那么点击的时候就会触发useMagic了,请留意一下useMagic,paperen是使用了三个参数1,0,-1分别代表启动魔法效果,0代表魔法效果执行中,-1代表魔法效果使用完毕。一开始定义魔法效果为4秒,所以要在倒数两秒时给玩家一些提示,提示魔法效果将会结束,于是就是调用 useMagic(0)这个函数了 。

//提示取消魔法效果
if ( magicTimer >= 2000 ) {
//取消魔法效果
useMagic(-1);
} else {
for( i=0; i if ( block_instance[i].magic ) {
if ( magicTimer % 200 == 0 ) {
document.getElementById( block_instance[i].id ).style.display = "block";
block_instance[i].setFace( block_faces[0] );
} else {
document.getElementById( block_instance[i].id ).style.display = "none";
block_instance[i].setFace( block_faces[3] );
}
} else {
document.getElementById( block_instance[i].id ).style.display = ( magicTimer % 200 == 0 ) ? "none" : "block";
}
}
magicTimer += 100;
setTimeout("useMagic(0)", 100);
}

一进来就判断魔法计数器是否超过2秒了,如果是直接就代表魔法使用完毕了,每200毫秒改变一下控制块的样式,并让统计器加100再定时执行自身。

5.检查碰撞check_collision,就是定时执行这个函数,思路其实也很简单,就是循环检查小球的当前位置是否落在控制块的面积区域内,有则定义为发生碰撞。

//判断是否碰撞
function check_collision() {
if ( block_instance.length <= 0 || gameOver || block_magic_state ) return false;
block = block_instance[0];
for( i=0; i tmp = ball_instance[i];
if ( tmp.x + tmp.width > block.x && tmp.x < block.x + block.width && tmp.y + tmp.height > block.y && tmp.y < block.y + block.height ) {
//碰撞了
block.setFace( block_faces[1] );
Over();
return false;
}
}
}

6.所有的东西动离不开定时执行,setTimeout与setInterval,请弄明白这两个函数的区别才能让你更好地使用它们,前者只会到达定时时执行一次指定的动作之后就没有了,后者则会到达定时就执行一次动作后再重新计时。

7.最后记录分数当然使用了XML Http这个对象来将分数异步传递给一个php页面进行记录,又再次使用了轻量级的数据库sqlite。

8.paperen对IE下的一卡一卡的现象还是不能了解清楚(有高手在的话能不能给paperen点提示),肯定与自己的代码有关,可能会比较耗资源,要改善的东西还是很多而且还有更多玩法(让控制块一定时间变大……让小球一定时间变大……让小球一定时间跟踪控制块……有些很Bt的想法,哈哈),当然可能存在不少BUG……希望大家提出~~

9.希望大家喜欢这个游戏,老实说paperen最高记录只能顶到67.4秒,上个图为证,不要说paperen作弊(发誓不是ps的!发誓不是改了某个参数的!)……希望你们也不要作弊……

20110521150745

好吧,最后在此顺便也提一提前段时间的google banner那个动画效果,新浪微博说竟然有人说是css做的,而且博猪还是拥有较多粉丝的,所以可能有不少人被误导了,不知道有多少人去看过源码,凡是有web开发经验的人第一时间都不会觉得是使用css做的,因为css除了使用explosion可以起到一些脚本作用外,它主要是用来渲染与布局页面的,根本不存在这种动态改变DOM(文档结构与元素)的能力。下面是paperen扒了那天的动画再放上来分享的地址,google是有将js进行压缩的,故paperen也使用jsbeautifier这个在线工具进行还原了(更适合人类看代码了)

http://paperen.com/demo/google-banner/

不妨看看源代码

l = function () {
var a = d[f],
c = document.getElementById("hplogo");
if (c && a[0]) {
var b = document.createElement("div");
b.id = "hplogo" + f;
b.style.left = a[0] + "px";
b.style.top = a[1] + "px";
b.style.width = a[2] + "px";
b.style.height = a[3] + "px";
b.style.background = "url(graham11-hp-sprite.png) no-repeat " + -g + "px " + -h + "px";
b.onmousedown = k;
a[3] > i && (i = a[3]);
a[4] ? (g = 0, h += i, i = 0) : g += a[2];
c.appendChild(b);
++f;
f < e && (j = window.setTimeout(l, 83))
}
},
m = function () {
google.doodle.a = !1;
i = h = g = f = 0;
j != -1 && (window.clearTimeout(j), j = -1);
for (var a = 0; a < e; ++a) {
var c = document.getElementById("hplogo" + a);
c && c.parentNode && c.parentNode.removeChild(c)
}
j = window.setTimeout(l, 83)
};

最关键的就是这个l(google对变量也进行了简化压缩),或者你可以将它当为是播放的执行(play),就像是flash播放到某一帧,当然还有一个关键就是d这个很长长的数据~~paperen在此就不放出来了,例如:[69, 0, 164, 139, 1],69代表了要将创建的div元素的x为相对hplogo元素的69px位置,0代表将div元素的y为相对hplogo的0px位置,164代表div的宽度,139代表高度,背景图片为  graham11-hp-sprite.png并且将图片定位到-g,-h的位置(CSS Split技巧)。而注意以下两行代码,很精炼

a[3] > i && (i = a[3]);
a[4] ? (g = 0, h += i, i = 0) : g += a[2];

就是对背景定位进行的控制,如果数组第三个位置大于i即记录此时的高度,如果数组第四个位置存在值且大于0,背景图片x坐标回零,高度加上现在的i,否则x坐标加上当前宽度。

在整个过程都使用了js不断往hplogo元素里面插入子元素,直到到达d数组的最大长度。

请结合firebug或者opera的dragon fly等页面调试工具进行分析,关于那张图片 http://paperen.com/demo/google-banner/graham11-hp-sprite.png 可能你会更明白一点。

paperen认为主要功夫是放在这张图片上的,代码花的时间可能不到半个小时~~怎都好,希望你能喜欢javascript,因为它真的可以玩得很cool~~