本文对《仿掌上游戏机》中的WzwScreen类做了API文档介绍,如果你对这个项目的整体结构和整体思路不是很了解,建议你先阅读 《仿掌上游戏机》简介 这篇文章。
一、屏幕类 WzwScreen.js
屏幕有多大、屏幕颜色、文字大小这些都由WzwScreen
类控制着。它提供了一个构造函数,构建一个屏幕实列需要2个参数new WzwScreen(dom, option)
。dom
允许是一个 选择器、jquery对象、原生dom。而option
则提供了一些参数配置。请看下面。
1、用于构建屏幕的option参数
下面列出了option
的参数含义及默认值,这些所有值都提供了一个默认值,所以你希望构建自己的屏幕实列时可以直接不传option
。
width: 190, // [可选] 游戏屏幕宽度
height: 250, // [可选] 游戏屏幕高度
atomRowCount: 21, // [可选] 点阵行数
atomColCount: 11, // [可选] 点阵列数
atomBorder: 1.5, // [可选] 点阵边框大小
atomInset: 2, // [可选] 点阵内空白大小
atomSpace: 3, // [可选] 点阵间距
splitPosition: 0.7, // [可选] 左右分隔位置,取值范围:0~1
splitSize: 1, // [可选] 分割线大小
fontSize: 13, // [可选] 文字大小
fontHeight: 15, // [可选] 文字行高
background: "#9facaa", // [可选] 背景色
color1: "#000000", // [可选] 浓颜色
color2: "#8f9997", // [可选] 浅颜色
接下来将分别介绍WzwScreen
类提供的静态函数以及实列函数。
2.1、构造函数
// 构建一个屏幕实列。
var myScreen = new WzwScreen("#myScreen");
// 使用自己的配置构建
var myScreen = new WzwScreen("#myScreen", {
background: "gray",
color1: "#ffffff",
color2: "black"
});
2.2 实列方法列表
-
myScreen.makeNewArr(valueAdapter): 产生一个与构建屏幕时相同点阵个数的二维数组。若不提供
valueAdapter
则二维数组内全为0,否则根据valueAdapter
函数返回值填充二维数组,此函数会提供两个参数(rowIndex/*第一层数组下标*/, colIndex/*第二层数组下标*/)
。 -
myScreen.playAnim(anim, callback): 播放指定动画,
anim
来自WzwScreen.ANIM
内的某个动画,你也可以自己实现动画,后文将介绍。callback
每个动画组执行完成触发此函数,提供了两个参数(animName/*动画名称*/, animIndex/*执行完成的动画组下标*/)
。
什么是动画组?答:每个动画都是由多个
组
构成的,何为一组
,当动画从开始到铺满整个屏幕,叫做一组
。然后从整个屏幕又被完全清空,又是一组
。内置的所有动画都是两组的动画,分别包含了第一组填充,和第二组清空。
-
myScreen.updateAtomArr(atoms): 更新点阵。要求传入一个二维数组,二维数组里为1的部分会被渲染成
color1
指定的颜色。 -
myScreen.updateStatusAtoms(atoms):更新右侧4×4的点阵区域。
-
myScreen.regLogic(callback): 注册一个函数,此函数会永远不停的被调用,在这个被注册的函数里,你有机会更新游戏逻辑。
-
myScreen.setLevel(level): 设置当前显示的关卡值。
-
myScreen.setScore(score): 设置当前显示的成绩值。
-
myScreen.setPause(pause): 设置当前是否显示暂停标志。
-
myScreen.setBest(best): 设置当前显示的最佳成绩值。
2.3 静态属性列表
- WzwScreen.ANIM: 内置动画列表。此对象内容纳了多个预置的动画效果。如下:
WzwScreen.ANIM = {
CIRCLE, // 螺旋线的方式充满屏幕,然后以螺旋线的方式清空屏幕。
B2T, // 从底部到顶部挨着充满屏幕,然后从顶部到底部清空屏幕。
T2B, // 从顶部到底部挨着充满屏幕,然后从底部到顶部清空屏幕。
COP, // 从屏幕上下两端同时充满屏幕,然后从屏幕中间到两端清空屏幕。
};
- WzwScreen.LETTER: 内置英文字母列表。
WzwScreen.LETTER = {
A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z
};
2.4、静态方法列表
-
WzwScreen.assign(target, obj1, obj2, ...):浅拷贝。将所有对象合并到 target,然后返回 target。
-
WzwScreen.each(arrOrInt, callback): 遍历方法。第一个参数支持
数组
和整数
。第二个参数为回调,循环过程中会给这个回调函数三个参数(value, index, arrOrInt)
。 -
WzwScreen.each2(arr, callback): 遍历方法。第一个参数要求一个二维数组。第二个参数为回调,循环过程中会给这个回调函数四个参数
value, rowIndex(第一层下标), colIndex(第二层下标), arr
。 -
WzwScreen.scroll(from, to, callback, dur): 递变方法。from、to为两个整数,此方法将数字由from不停递变到to,递变时间dur(默认500ms),递变过程会不停调用callback回调,callback是一个对象,此对象须提供多个方法以便接受各种递变状态。例如:
// 将数字从0递变到140,整个过程800毫秒,期间根据递变状态会调用对应回调。
WzwScreen.scroll(0, 140, {
goo: function (current) {/*此方法会被不停的调用,current表示当前递变到的值。此方法返回字符串 kill 则直接停止本次递变,直接停止本次递变不会触发end回调、但是会触发kill回调。*/},
end: function () {/*递变到目标数值时回调。*/},
kill: function () {/*递变在过程中得到了一个kill停止命令时,本方法会执行。*/}
}, 800);
-
WzwScreen.mergeArr(src, tar, rowIndex, colIndex, valueAdapter): 数组融合方法,通常是用于二维数组融合。将
src
数组 按照rowIndex
、colIndex
指定的位置融合到tar
数组里面,然后返回tar
数组。若提供了valueAdapter
函数,则根据此函数规则进行融合。若没有提供valueAdapter
函数,则无条件将src
里的所有的值覆盖tar
里对应位置的值。valueAdapter
是一个适配器函数,融合过程会给这个函数提供四个参数(tarRowIndex/*tar数组第一层下标*/, tarColIndex/*tar数组第二层下标*/, rowIndex/*src数组第一层下标*/, colIndex/*src数组第二层下标*/)
,此函数返回值将作为结果融入到tar
数组里面。 -
WzwScreen.mergeArr2(src, tar, rowIndex, colIndex, valueAdapter): 数组融合方法,此方法和
WzwScreen.mergeArr
用法一模一样,唯一的区别就是:此方法不会修改原tar
数组,而是返回一个新的结果数组。 -
WzwScreen.random(start, end): 产生随机数。产生一个左闭右开[start, end)区间内的随机整数。
-
WzwScreen.storeGet(key): 获取本地存储的值。
-
WzwScreen.storeSet(key, value): 设置本地存储值。
-
WzwScreen.storeRemove(key): 移除本地存储的值。
二、动画及实现自定义动画
通过实列方法myScreen.playAnim(anim, callback)
可以很方便的播放一个动画,动画可以是来自WzwScreen.ANIM
里的内置动画,也可以是自己实现的动画。要完成自己实现动画效果,我们就必须明白动画的组成结构。
1、动画组
一个完整的动画,是由n(n>0)组动画组串联运行构成的,内置的所有动画都是包含了2组的动画,大部分都是第一组用于把点阵按规律铺满整个屏幕,第二组用于把点阵按规律从整个屏幕消除。执行观察下面的动画执行:
这个动画是内置的 WzwScreen.ANIM.COP
动画,可以很明显的看到,动画开始首先从屏幕顶部和底部开始慢慢的遮盖,直至整个屏幕被填充满,这边完成了一组,然后随即开始执行下一组动画,从屏幕中间向上下两边将遮盖散开,直至完全散开。
2、动画帧
我们有了动画组,而每个动画组在播放时要如何进行界面渲染?其实是由很多个‘帧’构成,每一帧本质就是一个 和屏幕点阵数量大小相同的二维数组,这个二维数组里 1 的值就会被渲染成黑色点阵,0 的值就不会被渲染,通过一个组内的多个帧连续切换,直到所有帧执行完成,则预示着这个组被执行完成了。
3、动画时间
动画通常都有一个执行过程,而对于这里,我们将时间作用于每一个动画组。你只能为每一个动画组执行多长时间设置一个值,这也是必须要求每一个动画组必须指定执行时间。
4、实现自定义动画
既然明白了动画的组成结构,就能很容易实现动画了。一个动画是多个‘组’构成的,所以我们自己定义的动画,只需要返回一个由多个组构成的动画就好了。比如说下面这个示例代码:
var myAnim = function () {
var group1 = [ // 第一组。
[[1,1...],[0,0...],...], // 第一帧。
[[1,0...],[1,1...],...], // 第二帧。
// 每一帧本质就是一个 和屏幕点阵数量大小相同的二维数组
...
];
var group2 = [...]; // 第二组。
// 动画由多个组构成。
var animArr = [
group1,
group2
];
// 每个动画组执行多长时间(毫秒),这个数组大小和 animArr 必须保持一致。
// 以确定每个组的执行时间。
var animTime = [
500,
500
];
return {
animName: 'myAnim', // 必须指定动画名称。
animArr: animArr, // 所有动画组。
animTime: animTime // 设定各个动画组的执行时间。
}
}
现在,当你完成了自己的动画的各个帧如何渲染的逻辑并组成了一个个完整的组后,你就可以尝试播放你的动画了:
myScreen.playAnim(myAnim, function (animName/*动画名称*/, index/*执行完成的组名称*/) {
// 每个动画组执行完成后,这里会执行,并传入一些参数使你知道哪个组完成了。
})
有时候我们的动画效果需要结合当前屏幕实列内的一些数据来进行计算,我们就需要有办法在这个构建动画的方法里去获取屏幕实列对象。其实很简单,通过 this
就可以拿到当前屏幕实列对象。一旦你完成了你的动画构建方法,你把这个动画放在哪个屏幕实列里运行,则你在这个方法里使用的this
就表示对于的屏幕实列。就像这样:
var myAnim = function () {
var group1 = [ // 第一组。
this.makeNewArr(), // 第一帧,直接产生一个与当前屏幕实列相同大小的空二维数组。
...
];
var group2 = ...;
var animArr = [ group1, ...];
var animTime = [ 500, ... ];
return {
animName: 'myAnim',
animArr: animArr,
animTime: animTime
}
}