Gluster 分布式文件系统概述请查看我之前转载的文章 http://blog.csdn.net/zonelan/article/details/8468383
操作系统:Ubuntuserver 12.04.1 LTS 64bit
分布式文件系统:Gluster
测试服务器:4台ip:192.168.1.1-192.168.1.4
1、安装软件包:
apt-get install glusterfs-server glusterfs-common glusterfs-client glusterfs-dbg glusterfs-examples
2、建立分区或磁盘挂在目录
mkdir-p /export/brick1 (在所有存储节点建立)
3、挂在分区或磁盘到目录
mount/dev/sda1/export/brick1(所有节点执行挂载,分区或磁盘容量要尽量一致(对于replica模式的卷尤为重要,这种模式下会以容量小的分区或磁盘为准))
4、修改/etc/hosts文件,加入各节点机器名与IP对应关系,内容如下:
test01 192.168.1.1
test02 192.168.1.2
test03 192.168.1.3
test04 192.168.1.4
在其他节点做相同操作
5、ssh密钥登录(192.168.1.1上操作)
ssh-kengen
ssh-copy-id-i .ssh/id_rsa.pub root@192.168.1.2
ssh-copy-id-i .ssh/id_rsa.pub root@192.168.1.3
ssh-copy-id-i .ssh/id_rsa.pub root@192.168.1.4
其他节点做相同操作,除自身ip
6、建立peer关系(192.168.1.1上操作)
gluster
gluster>peer probe 192.168.1.2 192.168.1.3 192.168.1.4(此操作在一台服务器上操作即可,状态将同步到其他服务器)
gluster>peer probe (ip)(后续增加节点时使用)
gluster>peer detach (ip) (后续删除节点时使用)
gluster>peer status对等体状态
Numberof Peers: 3
Hostname:192.168.1.2
Uuid:67d37243-4332-4324-b497-92cf3d4fa2c1
State:Peer in Cluster (Connected)
Hostname:192.168.1.3
Uuid:0e8f17ba-c061-4537-ac3a-f625600c6663
State:Peer in Cluster (Connected)
Hostname:192.168.1.4
Uuid:66149333-6235-4bcc-82ae-b2fd011794db
State:Peer in Cluster (Connected)
7、建立卷(192.168.1.1上操作)
gluster
gluster>volume create gv0 replica 2 192.168.1.1:/export/brick1192.168.1.2:/expo
读取队列任务的优先级要比写入队列任务的优先级要低,这点非常重要。不然,一旦向队列中添加一个元素之后,高优先级的任务将会马上占有CPU并处理该元素。设备驱动任务将不能够做其它更多的操作直到高优先级任务因为再次等待队列而阻塞。因此,如果一个应用任务拥有比写入队列任务更高的优先级,它的控制流就如同在设备驱动任务以事件为参数调用了应用任务函数。如果应用任务花费的时间长于轮询周期,则会有事件丢失的可能。
下面的例子可以让我们开发出用于简单应用的事件队列结构。一台VCR有一些控制按钮,如时间设置频道设置等等。它也有三个一般的按钮A B C 。在屏幕上会根据上下文给出这三个按钮的具体操作用处。例如,在按下时间设置按钮后:菜单会把A B C 解释为:
A = 小时
B = 分钟
C = 设置结束时间
在按下频道按钮后,菜单显示:
A = 下一个
B = 搜索
C = 存储
每个按键如何执行它的工作并不重要。我们关心的是在指定上下文中如何对每个按键的意义进行解析。很多产品在屏幕底部放置没有标识的按钮,然后在屏幕下方相应于按钮的位置显示标识说明。从这一点来看,按钮位于显示屏幕上面的标识说明,可以通过软件来更改。许多自动柜员机(ATM)就是采用的这种技术。
VCR拥有两个带箭头显示的按钮用于增加或减小选定的值。录像带驱动器中使用限位开关来对录像带插入还是移除状态进行检测,当没有录像带插入时候,需要对用户的某些选择操作进行阻止。我们称该开关为录像带检测器。当用户插入或者移除录像带时候,我们可以把它当成一个用户事件。
这里有两种类型的事件:按键事件和录像带检测事件。按键可以按如下方式定义:
typedef enum
{
KEY_CHANNEL,
KEY_SET_TIMER,
KEY_A,
KEY_B,
KEY_C,
KEY_UP_ARROW,
KEY_DOWN_ARROW
}KeyValue;
typedef enum
{
KEY_PRESS,
KEY_RELEASE,
}KeyAction;
typedef struct
{
KeyValue value;
KeyAction action;
}KeyEvent;
录像带检测器事件描述如下:
typedef enum
{
TAPE_INSERTED,
TAPE_REMOVED
}TapeAction;
typedef struct
{
TapeAction action;
}TapeEvent;
一个只有一个条目的结构体可以当成一个单一元素,但是为了保持一致性,我们还是将其放入一个结构体中。
如果在30秒的时间内用户没有任何操作,则会产生一个超时事件。VCR显示屏将会恢复到一个显示系统时间的默认状态。这个事件不需要任何附加的数据。
为了将这些事件中的任何一个放入到队列中,需要创建一个可以区分的包含两个结构体的联合体类型。区分标志是在联合体之外的一个数据域,通过它可以区分联合体中的结构体哪一个是有效的。具体如下所示:
typedef enum
{
KEY_EVENT,
TAPE_EVENT,
TIMEOUT_EVENT
}EventTag;
本篇是该系列文章第二篇,其他文章请看下面帖子中的目录
http://blog.csdn.net/lufy_legend/article/details/8441677
话说突然想起来黄忠黄老将军被我仍在漆黑的战场上已经有一段时日了,没吃没喝的,不知道怎么样了。
等我来到战场上一看,才发现这个担心是多余的,老将军依然精神抖擞的在原地活蹦乱跳,嘴里不停的喊着,“别想困住老夫,老夫已经死过一回了”。
看着老将军如此拼命的想要往前走两步,我决定让老将军走动起来。
不过首先,得先让战场明亮起来,准备一张背景图片,然后使用LBitmap对象显示到游戏中,并将原来的黑色矩形注释掉。
//背景层 backLayer = new LSprite(); //backLayer.graphics.drawRect(1,"#000",[0,0,LGlobal.width,LGlobal.height],true,"#000"); baseLayer.addChild(backLayer); var background = new LBitmap(new LBitmapData(imglist["back"])); backLayer.addChild(background);效果如下
黄老将军看了看久违的熟悉的战场,又看了看战场上的“董”字旗子,吼道:“差点没气晕过去,董卓跟老夫有哪门子关系啊!?”
其实我也没办法,没有找到合适的图片了,下面就是让人物动起来了,黄忠在旁边继续吼到:“早就已经动起来了,只是不能动地方而已,都快累死了。”。话说这老家伙火怎么这么大...
懒得理他,继续写代码,下面将前面的代码休整一下,一个动作一个动作来。我只写核心部分,完整代码一会儿给出下载。
1,走动游戏中,键盘的各个键的状态是按下还是弹起,是需要准确判断的,所以准备一个keyCtrl数组,来保存键盘键的状态。
在按下的时候,使用
keyCtrl[e.keyCode] = true;在弹起的时候,使用
keyCtrl[e.keyCode] = false;这样,每个键的状态,就可以通过keyCtrl数组来获取。
接着,在Character类的onframe函数中调用move函数,在move函数中根据人物当前的状态,计算移动的步长,来进行移动。
Character.prototype.move = function (){ var self = this, mx = self.mx, my = self.my; if(self.action == ACTION.MOVE || self.action == ACTION.JUMP || self.action == ACTION.JUMP_ATTACK){ mx *= MOVE_STEP; my *= MOVE_STEP; }else if(self.action == ACTION.RUN){ mx *= MOVE_STEP*2; my *= MOVE_STEP*2; }else if(self.action == ACTION.HIT){ mx = MOVE_STEP*2*(self.direction == DIRECTION.RIGHT ? 1 : -1); my = 0; }else{ mx = my = 0; } if(mx == 0 && my == 0)return; self.x += mx; self.y += my; if(self.y < 250){ self.y = 250; }else if(self.y > 448){ self.y = 448; } };上面的self.mx,self.my在Player类中进行计算
Player.prototype.move = function (){ var self = this, mx = 0, my = 0; if(keyCtrl[KEY.LEFT]){ mx = -1; }else if(keyCtrl[KEY.RIGHT]){ mx = 1; }else if(keyCtrl[KEY.UP]){ my = -1; }else if(keyCtrl[KEY.DOWN]){ my = 1; } self.mx = mx; self.my = my; self.callParent("move",arguments); };callParent函数是lufylegend引擎中调取父类函数的方法,两个参数,第一个参数是父类的方法名,第二个参数是固定参数arguments,因为Player继承自Character,所以就是调用Character对象的move函数。
然后在键盘键按下的侦听函数onkeydown中根据按键来改变人物的状态,就能实现了人物的行走了。
2,跑动跑动就是连续按两下左或者右,这就需要判断上一次和这一次两次的按键,考虑到后面的绝招等,这里建立一个储存按键的数组keyList
var keyList = [{keyCode:0,time:0},{keyCode:0,time:0},{keyCode:0,time:0}];
每次按键,都将当前的信息压入该数组,然后将不需要的按键信息(两次以前)移除。
var keyThis = {keyCode:e.keyCode,time:(new Date()).getTime()}; var keyLast01 = keyList[0]; var keyLast02 = keyList[1]; keyList.unshift(keyThis); keyList.pop();
然后,根据按键序列中的信息,进行判断,是否进行跑动
switch(e.keyCode){ case KEY.LEFT: if(keyLast01.keyCode == KEY.LEFT && keyThis.time - keyLast01.time < 200){ hero.setAction(ACTION.RUN,DIRECTION.LEFT); }else{ hero.setAction(ACTION.MOVE,DIRECTION.LEFT); } break; case KEY.RIGHT: if(keyLast01.keyCode == KEY.RIGHT && keyThis.time - keyLast01.time < 200){ hero.setAction(ACTION.RUN,DIRECTION.RIGHT); }else{ hero.setAction(ACTION.MOVE,DIRECTION.RIGHT); } break;
3,跳跃
了便于控制,我将跳跃图片修改了一下
因为人物动作是通过LAnimation对象来显示的,所以只要在跳跃的过程中,改变LAnimation对象的y坐标,就能实现跳跃了
我在Player类中对onframe函数进行了重写
Player.prototype.onframe = function (){ var self = this; self.callParent("onframe",arguments); if(self.action == ACTION.JUMP){ self.onjump(); }else if(self.action == ACTION.JUMP_ATTACK){ self.onjump_attack(); } };上面代码,当人物跳跃或者跳跃攻击的时候,会调用相应的onjump函数和onjump_attack函数,在这两个函数内根据图片的播放序号,来修改LAnimation对象的y坐标
Player.prototype.onjump = function (){ var self = this; self.setLocation(); var index = self.anime.colIndex; self.yArr = [0,-10,-20,-30,-40,-40,-30,-20,-10,0]; self.anime.y += self.yArr[index]; }; Player.prototype.onjump_attack = function (){ var self = this; self.setLocation(); var index = self.anime.colIndex; if(index >= self.yArr.length)return; self.anime.y += self.yArr[index]; };这样,跳跃就完美实现了。
4,攻击
攻击的时候,在攻击动作结束之前,不可能进行走动或者跳跃等其他动作的,所以在攻击键按下的时候,需要将按键上锁,让按键无效
setTimeout("keylock = true;",50); hero.setAction(ACTION.ATTACK,hero.direction);为什么要使用setTimeout函数?,因为还有绝招的发动,绝招的发动需要攻击键和跳跃键同时按下,但是人不可能同时按下两个键的,要有一个很小的间隔,我这里将这个间隔的最大值设定为50毫秒,所以在这50毫秒以内,是可以再按下跳跃键的。5,连续攻击
当连续几次普通攻击的时候,是会出现一次特殊的攻击的,我设定每三次攻击,进行一次特殊攻击
case KEY.ATTACK: if(keyLast01.keyCode == KEY.ATTACK && keyLast02.keyCode == KEY.ATTACK && keyThis.time - keyLast02.time < 1000){ keyList = [{keyCode:0,time:0},{keyCode:0,time:0},{keyCode:0,time:0}]; keylock = true; hero.setAction(ACTION.BIG_ATTACK,hero.direction); }当然,需要判断一下这几次连续攻击的时间,这里设定在1秒钟内进行三次攻击,则判定为连续攻击。
6,跳跃攻击这个也简单,只要在人物处于跳跃状态的时候进行攻击,则判定为跳跃攻击。
case KEY.ATTACK: if(keyLast01.keyCode == KEY.ATTACK && keyLast02.keyCode == KEY.ATTACK && keyThis.time - keyLast02.time < 1000){ keyList = [{keyCode:0,time:0},{keyCode:0,time:0},{keyCode:0,time:0}]; keylock = true; hero.setAction(ACTION.BIG_ATTACK,hero.direction); }else if(hero.action == ACTION.JUMP){ hero.setAction(ACTION.JUMP_ATTACK,hero.direction); }else{ setTimeout("keylock = true;",50); hero.setAction(ACTION.ATTACK,hero.direction); }7,技能攻击
玩过街机三国志的朋友们都知道,下=>上=>攻击,就会发动一下特殊的武将技,这个也简单,在攻击键按下的时候判断一下前两次按键就可以了。
if(keyLast01.keyCode == KEY.UP && keyLast02.keyCode == KEY.DOWN && keyThis.time - keyLast02.time < 300){ keylock = true; hero.setAction(ACTION.SKILL,hero.direction); }8,大绝招当满屏幕的敌人围住自己的时候,怎么办?放大招呗。
在攻击键按下的时候,判断一下跳跃键是不是同时被按下了。
if(keyLast01.keyCode == KEY.JUMP && keyThis.time - keyLast01.time < 50){ keylock = true; hero.setAction(ACTION.BIG_SKILL,hero.direction); }当然,在跳跃键按下的时候,也需要判断一下攻击键是不是被按下了。
if(keyLast01.keyCode == KEY.ATTACK && keyThis.time - keyLast01.time < 50){ keylock = true; hero.setAction(ACTION.BIG_SKILL,hero.direction); }绝招发动的时候,其他按键是无效的,所以键按键上锁keylock=true;
比较特殊的是,绝招图片的动作比较多,全都合到一