FLEX中CSS编译成SWF的经验总结
为了在FLEX中实现动态样式切换,一般的做法是将CSS编译成SWF之后,再使用
StyleManager.loadStyleDeclarations("css.swf");
这样的方式来实现样式的切换工作.
我们可以在右键CSS文件,然后选择"编译CSS为SWF文件"来实现我们想要的效果.但是有一点注意,如果你的CSS中定义了类似
skinClass:ClassReference("cn.LunaStudio.skins.ImageButtonSkin");
这样的自定义的皮肤指向,编译出来的SWF中会找不到这些自定义的类,所以会在加载CSS.SWF之后使用的过程中报找不到类的错误.
这个时候,你需要把CSS文件放到SRC的根目录下,然后你就会发现编译出来的类便正常地包含了自定义的类了,然后一切正常了
Flex中的方法绑定的一个比较实际的小例子
我们知道[Bindable]标签是可以直接针对事件的绑定.就象下边这样子
[Bindable("myChangeEvent")]
public var myProp:*;
当该对象发送myChangeEvent的时候,myProp的绑定便生效了,这时,与myProp建立的绑定关联,也就跟着更新了.
对于方法绑定,其效果是一样的,也就是说,我同样也可以把上边的代码变成
[Bindable("myChangeEvent")]
public function myFunc(myProp:*):*{...}
根据这一点特性,我们可以做一些比较实际点的应用.比如I18N的立即切换内容的解决方案
如下边的例子
______________________________
右键查看源文件
______________________________
参考:
http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf64c3d-7ff3.html
http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf69084-7cc5.html
定义发布用的NetStream需要使用实例域变量,局部变量者无效
1 2 3 4 5 6 | import flash.net.NetStream; var nc:NetConnection; var video:Video; nc = new NetConnection(); nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); nc.connect("rtmp://localhost/livestreams"); |
1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | function netStatusHandler(event:NetStatusEvent):void { trace(event.info.code); switch (event.info.code) { case "NetConnection.Connect.Success": publishLiveStream(); break; case "NetStream.Publish.Start": var ns2:NetStream=new NetStream(nc); ns2.play("testStream") video1.attachNetStream(ns2); break; } } //try comment this line;尝试注释这一行,把NS变成局部变量 var ns:NetStream; function publishLiveStream():void { //if u comment the above line,uncomment this line;把NS变成局部变量,你会发现发布视频失效了 // var ns = new NetStream(nc); ns = new NetStream(nc); ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); ns.attachCamera(Camera.getCamera()); ns.publish("testStream", "live"); } |
U3D-island demo(sfs-version)
最近开始折腾起U3D了.把官方提供的ISLAND的DEMO从原来的SFS1移植到SFS2X上,运行良好


访问地址
http://218.240.54.69:8080/island/index.html
输入IP的时候将127.0.0.1换成218.240.54.69
使用poeditor建立或更新po文件
在上一篇帖子中描述了通过xgettext制作PO文件的一些方法,其实我们也可以用poeditor来很方便地生成PO文件
具体操作如下边的图所示
文件->新建消息文档



文件保存在工程的目录下(和src文件夹同级别)
文件->首选项

点击如图的按钮,更新翻译字段

最后就取得了所有AS文件中需要翻译的字段了

当AS文件中有新的翻译字段时,只需打开PO文件,再点一下更新源就可以了.
当然,如果你还是想使用命令行去操作,在这里的更新PO文件的时候,就要用到msgmerge命令.详情可参考此链接说明
转帖注明出处:
http://lunastudio.cn
在FlashBuilder中使用getText
首先,是要装备一些必要的软件和代码
安装getText
http://gnuwin32.sourceforge.net/packages/gettext.htm
推荐安装"安装版",在安装完后,记得把getText的bin目录添加到path中去
安装PoEditor
http://www.poedit.net/download.php
下载As3GetText
http://code.google.com/p/actionscript3gettext/
然后在程序中需要翻译的文字前用一个特殊的方法名做为提取翻译字句的依据,一般来说,是用
__("helloworld");
用一个或两个"_"用做方法用.
然后在打开cmd
输入如下的指令
xgettext myclass.as --force-po --from-code=utf-8 -p po_dir -L ObjectiveC
这里需要注意的是,一般来说,因为我们给了__方法,只需要通过参数--keyword=__来指名,xgettext就能自动解析出来我们的翻译字典,但不知道是什么原因,没有成功,所幸ObjectiveC的默认识别方法就是__,所以这里只要把-L,即把默认语言改成ObjectiveC就可以正常解出PO文件了.
另外,当我们要去检索复数文件,比如说src目录下的所有as文件的话,需要配合find一起使用
find src -name "*.as" -print >tmplist
xgettext --files-from=tmplist --force-po --from-code=utf-8 -p po_dir -L ObjectiveC
这样就能生成PO文件了.
然后再用POeditor打开PO文件,为这些字符,配上对应的翻译即可
然后刚才提到的__("helloworld")方法的功能就是通过as3gettext里边的API,来读取.po文件所生成的.mo文件语言包,然后再转换成翻译后的语言,这个可以去看一下as3gettext里的sample
最后再说一下一个getText的Eclipse插件
http://www.gted.org/
在FB菜单中,HELP->INSTALL NEW SOFTWARE
然后添加站点
http://gted.sourceforge.net/update
然后安装好后,在WINDOWS->PREFERNENCE里就能找到geted.在path to gettext这指向一开始安装的gettext的bin目录
然后在项目上的属性菜单里找到geted settings里找到相关对应的设置
最后再项目右键菜单里找到geted->update po files,即可生成最一的PO文件了
转帖注明出处:
http://lunastudio.cn
Box2d笔记–Hello b2World
box2d中的物理世界,即b2World类就是一个包含了各种物体(body,物理体,或者叫刚体),固定附着物(fixture,形状与物理体的绑定物)以及各种约束体(比如关节),并使其在当中完成各种交互的这样一个集合体.
这个世界可能存在重力,所以,在创建这个世界的时候我们需要传一个描述重力的二维向量(v2对象),当然这取决于你的视角设定,也许你是做的横版游戏,这样的确需要一个重力.如果是顶视图,那可能就不需要重力了.
1 2 | var gravity:V2=new V2(0,10); var world:b2World=new b2World(gravity); |
然后世界定期需要刷新
1 2 3 4 5 6 7 | //刷新时间粒度 var stepTime:Number=1/30; //速度计算层级 var velocityIterations:int=8; //位置计算层级 var positionIterations:int=8; world.Step(stepTime,velocityIterations,positionIterations); |
在这个Step方法中进行了碰撞的检测,速度的更新等操作.
正如一开始描述的那样,world是一个管理刚体的集合.那么,刚体的产生,销毁以及碰撞判断都由world来处理.所以我们很容易找到b2World.CreateBody,b2World.DestoryBody这样的方法
刚体共有三种类型,分别是staticBody,dynamicBody以及kinematicBody
其含意分别是指,静态刚体(即不受力影响的物体,比如边界墙),动态刚体(完全模拟真实物理情况的物体),运动刚体(这是2.1版新增的一个类型,和静态刚体相比,就是它可以移动.它也同样不会被环境力所影响)
现在我尝试在world中创建两个刚体
1 2 | var mybodyA:b2Body=world.CreateBody(new b2BodyDef()); var mybodyB:b2Body=world.CreateBody(new b2BodyDef()); |
但实际上,仅仅只是这样创建两个刚体是没有意义的.因为它还没有具体的形状.所以它们即存在于这个世界中,但又无法参与到具体的碰撞运算中.
这个时候我们需要再定义一下形状
形状有两类,一种是b2PolygonShape(多边形),一种是b2CircleShape(圆形)
多边形最多有8个边,并且多边形必须是凸边形.当然,你也可以使用组合来形成更为伪凹边形或者更复杂的形状.
这里我们分别把上边的两个刚体一个定义成一个普通的矩形方形,另一个定义成圆形.
1 2 3 4 5 6 | var shapeA:b2PolygonShape=new b2PolygonShape(); var boxWidth:Number=100; var boxHeight:Number=100; shapeA.SetAsBox(boxWidth,boxHeight); var radius:Number=100; var shapeB:b2CircleShape=new b2CircleShape(radius); |
接下来就是将刚体和形状通过附着对象(b2Fixture)绑定起来.
1 2 3 | var fixtureDef:b2FixtureDef=new b2FixtureDef(); fixtureDef.shape=shapeA; new b2Fixture(myBodyA,fixtureDef); |
也可以使用更简洁的写法
1 2 | var density:Number=1; myBodyA.CreateFixtureShape(shapeA,density); |
此时场景中便有了一个方形的刚体了.现在我们把方形刚体当做"地板",放在下方
*注意,一般来说,定义刚体初始的位置时,要尽量在刚开始使
1 2 3 4 5 6 | 用b2BodyDef对象建立刚体的时候就定义好,而不是已经创建好后再去更新位置,因为会有一瞬间,所有刚体都会堆积在同一个位置诞生,那样不利于正确的碰撞运算.所以我们这里要修改一下我们开始创建刚体的代码. <code> var bodyDefA:b2BodyDef=new b2BodyDef(); bodyDefA.postion.v2=new V2(0,400); bodyDefA.type=b2Body.b2_staticBody; var mybodyA:b2Body=world.CreateBody(bodyDefA); |
这样就在下方创建了一个静态刚体用着"地板"了.
1 2 3 4 5 6 | 现在我们要再把开始那个球给完善了. 先修改一下创建时的代码 <code>var bodyDefB:b2BodyDef=new b2BodyDef(); bodyDefB.postion.v2=new V2(10,0); bodyDefB.type=b2Body.b2_dynamicBody; var mybodyB:b2Body=world.CreateBody(bodyDefB); |
再建立形状关联
1 | myBodyB.CreateFixtureShape(shapeB,1); |
这样两个可以进行物理模拟的有形状的刚体就形成,但是它们现在还并不是可视的.
一般来说.我们在游戏开发中都会将自己的贴图(Sprite)附着在刚体上.当刚体发生位移或者旋转时,我们只需要同步一下即可.
刚体有一个userData属性是专门用来存放刚体对应的自定义对象的.我们可以将我们的贴图放在这里.比如我们的库中有两个导出名分别叫Ball和Box的影片剪辑,那么我们可以象下边这样将影片剪辑的实例存放在userData中.
1 2 | mybodyA.SetUserData(new Box()); mybodyB.SetUserData(new Ball()); |
当然,你也可以在刚体定义对象中就申明
1 2 | var bodyDefB:b2BodyDef=new b2BodyDef(); bodyDefB.userData=new Ball(); |
然后再在EnterFrame事件中执行world.Step方法.
addEventListener(Event.EnterFrame,update);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | function update(e:Event) { world.Step(1/30,8,8); for(var body:b2Body = world.GetBodyList(); body; body = body.GetNext()) { var userData:*=body.GetUserData(); if(userData is Sprite) { userData.x = body.GetPosition().x; userData.y = body.GetPosition().y; userData.rotation = body.GetAngle() * (180/Math.PI); } } } |
有时候我们在做测试的时候可能没有准备什么box,什么ball的影片剪辑,这时,我们可以先使用debugdraw来绘制形状,查看一个演算的效果.
使用的方式为
1 2 | var debug:b2DebugDraw = new b2DebugDraw(world); addChild(debug); |
然后在update中刷新绘图即可
1 | debug.Draw(); |
转载请注明出处:
http://lunastudio.cn
Redis命令总结
Redis提供了丰富的命令(command)对数据库和各种数据类型进行操作,这些command可以在Linux终端使用。在编程时,比如使用Redis 的Java语言包,这些命令都有对应的方法,比如上面例子中使用的sadd方法,就是对集合操作中的SADD命令。下面将Redis提供的命令做一总结。
连接操作相关的命令
quit:关闭连接(connection)
auth:简单密码认证
对value操作的命令
exists(key):确认一个key是否存在
del(key):删除一个key
type(key):返回值的类型
keys(pattern):返回满足给定pattern的所有key
randomkey:随机返回key空间的一个key
rename(oldname, newname):将key由oldname重命名为newname,若newname存在则删除newname表示的key
dbsize:返回当前数据库中key的数目
expire:设定一个key的活动时间(s)
ttl:获得一个key的活动时间
select(index):按索引查询
move(key, dbindex):将当前数据库中的key转移到有dbindex索引的数据库
flushdb:删除当前选择数据库中的所有key
flushall:删除所有数据库中的所有key
对String操作的命令
set(key, value):给数据库中名称为key的string赋予值value
get(key):返回数据库中名称为key的string的value
getset(key, value):给名称为key的string赋予上一次的value
mget(key1, key2,…, key N):返回库中多个string(它们的名称为key1,key2…)的value
setnx(key, value):如果不存在名称为key的string,则向库中添加string,名称为key,值为value
setex(key, time, value):向库中添加string(名称为key,值为value)同时,设定过期时间time
mset(key1, value1, key2, value2,…key N, value N):同时给多个string赋值,名称为key i的string赋值value i
msetnx(key1, value1, key2, value2,…key N, value N):如果所有名称为key i的string都不存在,则向库中添加string,名称key i赋值为value i
incr(key):名称为key的string增1操作
incrby(key, integer):名称为key的string增加integer
decr(key):名称为key的string减1操作
decrby(key, integer):名称为key的string减少integer
append(key, value):名称为key的string的值附加value
substr(key, start, end):返回名称为key的string的value的子串
对List操作的命令
rpush(key, value):在名称为key的list尾添加一个值为value的元素
lpush(key, value):在名称为key的list头添加一个值为value的 元素
llen(key):返回名称为key的list的长度
lrange(key, start, end):返回名称为key的list中start至end之间的元素(下标从0开始,下同)
ltrim(key, start, end):截取名称为key的list,保留start至end之间的元素
lindex(key, index):返回名称为key的list中index位置的元素
lset(key, index, value):给名称为key的list中index位置的元素赋值为value
lrem(key, count, value):删除count个名称为key的list中值为value的元素。count为0,删除所有值为value的元素,count>0从头至尾删除count个值为value的元素,count<0从尾到头删除|count|个值为value的元素。
lpop(key):返回并删除名称为key的list中的首元素
rpop(key):返回并删除名称为key的list中的尾元素
blpop(key1, key2,… key N, timeout):lpop命令的block版本。即当timeout为0时,若遇到名称为key i的list不存在或该list为空,则命令结束。如果timeout>0,则遇到上述情况时,等待timeout秒,如果问题没有解决,则对key i+1开始的list执行pop操作。
brpop(key1, key2,… key N, timeout):rpop的block版本。参考上一命令。
rpoplpush(srckey, dstkey):返回并删除名称为srckey的list的尾元素,并将该元素添加到名称为dstkey的list的头部
对Set操作的命令
sadd(key, member):向名称为key的set中添加元素member
srem(key, member) :删除名称为key的set中的元素member
spop(key) :随机返回并删除名称为key的set中一个元素
smove(srckey, dstkey, member) :将member元素从名称为srckey的集合移到名称为dstkey的集合
scard(key) :返回名称为key的set的基数
sismember(key, member) :测试member是否是名称为key的set的元素
sinter(key1, key2,…key N) :求交集
sinterstore(dstkey, key1, key2,…key N) :求交集并将交集保存到dstkey的集合
sunion(key1, key2,…key N) :求并集
sunionstore(dstkey, key1, key2,…key N) :求并集并将并集保存到dstkey的集合
sdiff(key1, key2,…key N) :求差集
sdiffstore(dstkey, key1, key2,…key N) :求差集并将差集保存到dstkey的集合
smembers(key) :返回名称为key的set的所有元素
srandmember(key) :随机返回名称为key的set的一个元素
对zset(sorted set)操作的命令
zadd(key, score, member):向名称为key的zset中添加元素member,score用于排序。如果该元素已经存在,则根据score更新该元素的顺序。
zrem(key, member) :删除名称为key的zset中的元素member
zincrby(key, increment, member) :如果在名称为key的zset中已经存在元素member,则该元素的score增加increment;否则向集合中添加该元素,其score的值为increment
zrank(key, member) :返回名称为key的zset(元素已按score从小到大排序)中member元素的rank(即index,从0开始),若没有member元素,返回“nil”
zrevrank(key, member) :返回名称为key的zset(元素已按score从大到小排序)中member元素的rank(即index,从0开始),若没有member元素,返回“nil”
zrange(key, start, end):返回名称为key的zset(元素已按score从小到大排序)中的index从start到end的所有元素
zrevrange(key, start, end):返回名称为key的zset(元素已按score从大到小排序)中的index从start到end的所有元素
zrangebyscore(key, min, max):返回名称为key的zset中score >= min且score <= max的所有元素
zcard(key):返回名称为key的zset的基数
zscore(key, element):返回名称为key的zset中元素element的score
zremrangebyrank(key, min, max):删除名称为key的zset中rank >= min且rank <= max的所有元素
zremrangebyscore(key, min, max) :删除名称为key的zset中score >= min且score <= max的所有元素
zunionstore / zinterstore(dstkeyN, key1,…,keyN, WEIGHTS w1,…wN, AGGREGATE SUM|MIN|MAX):对N个zset求并集和交集,并将最后的集合保存在dstkeyN中。对于集合中每一个元素的score,在进行AGGREGATE运算前,都要乘以对于的WEIGHT参数。如果没有提供WEIGHT,默认为1。默认的AGGREGATE是SUM,即结果集合中元素的score是所有集合对应元素进行SUM运算的值,而MIN和MAX是指,结果集合中元素的score是所有集合对应元素中最小值和最大值。
对Hash操作的命令
hset(key, field, value):向名称为key的hash中添加元素field<—>value
hget(key, field):返回名称为key的hash中field对应的value
hmget(key, field1, …,field N):返回名称为key的hash中field i对应的value
hmset(key, field1, value1,…,field N, value N):向名称为key的hash中添加元素field i<—>value i
hincrby(key, field, integer):将名称为key的hash中field的value增加integer
hexists(key, field):名称为key的hash中是否存在键为field的域
hdel(key, field):删除名称为key的hash中键为field的域
hlen(key):返回名称为key的hash中元素个数
hkeys(key):返回名称为key的hash中所有键
hvals(key):返回名称为key的hash中所有键对应的value
hgetall(key):返回名称为key的hash中所有的键(field)及其对应的value
持久化
save:将数据同步保存到磁盘
bgsave:将数据异步保存到磁盘
lastsave:返回上次成功将数据保存到磁盘的Unix时戳
shundown:将数据同步保存到磁盘,然后关闭服务
远程服务控制
info:提供服务器的信息和统计
monitor:实时转储收到的请求
slaveof:改变复制策略设置
config:在运行时配置Redis服务器
JSON串中的中文字符编码显示问题
服务端传回来的JSON串中包含中文,默认为是UNICODE格式.类似如下内容
\\u00e5\\u00bf\\u00ab\\u00e7\\u0082\\u00b9\\u00e5\\u0090\\u00a7,\\u00e7\\u00ad\\u0089\\u00e5\\u0088\\u00b0\\u00e8\\u008a\\u00b1\\u00e5\\u0084\\u00bf\\u00e9\\u0083\\u00bd\\u00e8\\u00b0\\u00a2\\u00e4\\u00ba\\u0086
值得注意的是,这里并不是直接可以使用的UNICODE串,因为前边不是一个\而是\\,这样的结果就是\\u00e5并不是一个BYTE而是一个长度为6的字符串(\\被转义识别成一个字符了).似乎没有什么直接的办法去转义了.于是只有自己动手写一个间接的转换方法.
首先是计算出直接的那个字节的值.我们使用下边的这个方法去运算