H5C3J 学习笔记 part9 Javascript inherits spriteSheet
这几天一直在一个小东西上改来改去,今天终于成了一点形,得马上记录一下,不然就堆积得太多了。
首先是编写好一个Bird类,或者说,Vehicle,又或者说,Atomic类,总之是一个具备了2D向量行为的类型,下面我很自然的顺着原来的思路,想要编写一个该类的子类,然后第一次发现JavaScript是木有继承概念的……啊,我孤陋寡闻了。
我翻看了一些所谓的完美继承方案,大部分都看得很累,这些人写文章并非为了解决你的继承问题,而是炫耀他从过程中获得的点点优越感(我也是,但是没那么严重)。
然后我找到了这里,我认为这个老外用很少的代码,实现了基本完整的继承机制,原文在此
代码如下:
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
Function.method('inherits', function (parent) {
this.prototype = new parent();
var d = {},
p = this.prototype;
this.prototype.constructor = parent;
this.method('uber', function uber(name) {
if (!(name in d)) {
d[name] = 0;
}
var f, r, t = d[name], v = parent.prototype;
if (t) {
while (t) {
v = v.constructor.prototype;
t -= 1;
}
f = v[name];
} else {
f = p[name];
if (f == this[name]) {
f = v[name];
}
}
d[name] += 1;
r = f.apply(this, Array.prototype.slice.apply(arguments, [1]));
d[name] -= 1;
return r;
});
return this;
});
Function.method('swiss', function (parent) {
for (var i = 1; i < arguments.length; i += 1) {
var name = arguments[i];
this.prototype[name] = parent.prototype[name];
}
return this;
});
`</pre>
要定义类型时,先声明一个空白的构造函数,然后声明一个init函数,在里面定义要使用的类变量。
<pre>` var Bird = function ()
{
}
Bird.method("init",function(px,py,vx,vy){
this.edgeBehavior = Bird.BOUNCE;
this.mass = 1.0;
this.maxSpeed = 30;
});
`</pre>
想定义子类时,显式的调用<span>inherits函数,即可实现继承,例如:</span>
<pre>` var Tank = function()
{
}
Tank.inherits(Bird);
Tank.method("init",function(px,py,vx,vy){
//Some code for Tank Class,override parent function init
});
`</pre>
第二个值得注意的地方是,this关键字的引用歧义陷阱,如下代码开始的时候让我完全没有注意到错误的来源:
<pre>` this.reachGoal = false;
setTimeout(function(){this.reachGoal = true},1000);
`</pre>
JavaScript没有类概念,它的所谓类,就是一个函数而已,所以当我使用匿名函数做定时器调用时,这里的this,指代的已经不是我想操作的this,而是指代那个匿名函数了。解决的办法是(我暂且这样解决的)起个别名变量。
<pre>` this.reachGoal = false;
var main = this;
setTimeout(function(){main.reachGoal = true},1000);
下面遇到的就是,如何展现一个爆炸动画,当然可以用粒子系统达成,但个人认为效率低,效果没有那么好,所以还是利用一个老技术,SpriteSheet来达成,可以很容易的找到一些资源,比如下面这种。
[![](https://archive.writeitdown.site/explosion2.png)](https://archive.writeitdown.site/explosion2.png)
Collie引擎中对SpriteSheet有很好的支持,当我把这玩意当个新鲜事儿和小白分享时,小白说他早就知道这个东西了,其解决的最大问题,就是可以减少发起http请求的次数,我当时满脑子惊异,在我看来,这东西是为了解决:“如何能象Flash一样利用单个文件描述一个连续动画”的问题,然后我猛然发现,我以Flash为中心的思路是多么狭隘,我考虑这问题时,完全忽略了这项技术可能先于Flash诞生的事实,而且Flash中很可能借鉴了这样的手段,只是它封闭起来,我没看见而已。
我从日本人对美国的态度上,学习到的是,知道人家比你强,就马上认输,俯首学习。
关于转向行为的部分代码,在看的书里目前都有,所以不再赘述。
下面是这几天的一个小小的结果展示。
[![](https://archive.writeitdown.site/%2525E5%2525B1%25258F%2525E5%2525B9%252595%2525E5%2525BF%2525AB%2525E7%252585%2525A7%2525202013-10-14%252520%2525E4%2525B8%25258B%2525E5%25258D%25258811.12.14.png)](https://archive.writeitdown.site/%2525E5%2525B1%25258F%2525E5%2525B9%252595%2525E5%2525BF%2525AB%2525E7%252585%2525A7%2525202013-10-14%252520%2525E4%2525B8%25258B%2525E5%25258D%25258811.12.14.png)
[demo](http://hector.ziki.me/tank/tank/Tank.html)
很郁闷的是,发现它在Safari下又不能正常工作了……,检查一下发现,用于实现帧动画的requestAnimationFrame函数在Mac版本的Safari下不能正常运行,在iOS6的Safari下也不能正常运行,在iOS7的Safari上可以运行,所以,我只好再改成利用Timer触发的版本了。
这个水真不是一般的深啊,我发现原来用AS实现的部分,例如层次关系坐标换算,用AS实现时很容易,做js开发果然要痛苦一些。