盗賊の極意

Feed Rss

今天跟家里打电话,聊到马博士,现在想想,他是我们一批人里最踏实的一个了吧。

心态好真的很重要。

想起当年在寝室里看到他查阅色色的网站时,他也没有扭捏掩盖,也没有很中二的假装炫耀,坦然中还略有一点羞涩,真是……好萌啊

漫画啊小说啊什么的拿起来能看进去,这一点我也很佩服。我的话,八成是先搜搜看这书评价如何,然后对比看看有没有其他更好的选择,然后胡思乱想一阵,然后时间就没了。结果马博士成了博览群书的马博士,小把戏还是当年的小把戏

多么励志的马博士!以后我也要本着“多动手少动脑”(正面意义)的踏实作风走下去!

不胡思乱想,以踏实的方式追妹纸!

从java转到C++,不得不自己处理各种头文件包含问题。以前完全没有过这方面的经验,摸石头过河中

事情的背景是这样的:我有一套游戏代码,现在想给它做一个编辑器,希望尽可能重用以前的代码,不要一样的功能复制到两个项目里,以防止一个功能这边修改了那边没修改。

嗯,因为我的设计能力有限,导致要修改很多出才能重用原有代码。这已经不能叫完全的“重用”了吧……嘛,不真正重用这么一次,我永远也不会知道哪里应该设计的更灵活的,算是个好教训吧,好教训。

所谓复用,其实也只是新建一个项目,把原来游戏的源文件都导入进来,然后改一改。

在写编辑器的时候,我发现我需要修改引擎文件engine.h,我不希望这个修改应用于游戏本身,所以我从编辑器项目中移除了游戏的engine.h和engine.cpp文件,然后在编辑器项目目录下新建了两个同名文件导入了项目,在这两个新文件里做我的修改。

一开始我挺紧张的,感觉这么做很不靠谱,这肯定不是正确的复用之道(显然不是)。但是事实上它正确运转了,我也就没再多想。直到刚才,我发现我在engine里新写的函数IDE的自动补全里不给显示,硬写上去就是编译出错。到这里,我第一个想到的就是engine头文件导入错了。事实证明也确实如此。

我想,文件导入的头文件应该是和这个文件在同一个真实目录中的同名文件吧。比如engine.h文件在我的编辑器目录和原来的游戏目录里都有。我先导入了一个原来游戏目录里的头文件比如XXXWidget.h,因为这个头文件里include了engine.h,这个engine.h就是和这个XXXWidget.h在同一目录下的engine.h。哪怕我项目里有一个同名同姓的engine.h,include也是只看相对目录,不看项目配置。

那怎么办呢。

这个问题是我在编辑器目录里写新文件时遇到的,所以我在这个新文件的一排include命令的最后又手动include了一下engine.h(原本是靠前面include的原来游戏项目中的头文件间接include engine.h文件的),无效。我又把include engine.h的命令挪到了间接引入engine.h文件的头文件引用前面,行了。

经典的霰弹枪编程方法= =,再加上以前马博士指出的我的源代码注释陷阱,变量命名方式,看来我还是集各种恶劣的编程习惯于一身了

这时我才突然想起来,engine.h里面有

#ifndef__ENGINE_H__

#define__ENGINE_H__

这两句。所以只有最先被导入的engine才有效。嗯,懂了。可是再一想,那是不是我的项目里有的engine用的是原来的,有的用的是新的啊?这样,会不会有问题?还是一个类只有第一次导入的才有效?我行说ifndef命令啊define命令什么的都是只作用在一个源文件上的,在另一个源文件里就从新算了?嗯,好像接触到了一个比较深的C++问题了呢。一直被java照顾着,完全没考虑过这方面的事情,以后努力补上吧。这次我要优先做完编辑器,遇到的问题先搁置不理它!

#ifndef __ENGINE_H__

我实际执行了一下(做了一些调整),有个很诡异的bug:

如果我加入1个以上的CheckListboxItem的话,最后一个的文字不会显示,而且最后那个文字条无法被选中(如果文字为空的普通Item,虽然看不到字,但是点那里是可以选中Item的),但checkbox却正常显示、正常运转了。

但我再追加一个普通的EntryItem的话,前面的也能正常显示了!

CEGUI太大太复杂,想把它整个包含进来下断点排查对我来说基本上不可能。

在浪费了很多时间以后,我决定阻止自己再在这个bug上浪费时间了。反正知道了可以用空的EntryItem不完美地解决这个问题,之后就以这个不完美的解决方法为基础写我的关卡编辑器吧。

这种事情常常发生(比如这起)——我花了大力气去解决一个疑难杂症,来获得微不足道的提升。其实,如果今后我都没机会用CEGUI了的话,会解决这个bug对我来说也没什么意义。如果今后我还有机会继续研究它的话,到时候再去研究这个bug就好了。以我门都没入的水平想去排查杂乱如迷宫的cegui内部结构,还不如拿那个时间先把编辑器的小样做出来再改进呢。

原文:CEGUI官方wiki

翻译:基拉铃妖

===================================================================

2012.10.15日更新

被这教程坑啦!!!

后来人注意:在“在CEGUI中正确地注册这个窗口”那段代码里,addFalagardWindowMappings的第二个参数应该填你在CheckListboxItem.cpp里初始化的WidgetTypeName的值,在这个例子里就是“CEGUI/CheckListboxItem”,而不是它的基类“CEGUI/ItemEntry”!!填ItemEntry虽然也能运转,但你在CheckListboxItem里重写的基类函数都不会生效.

我昨天就是死活覆盖不了基类函数,后来下断点发现它连我重写的构造函数都没有进入,当时就寒心了啊我去!!!

还我时间!还我被消耗的对CEGUI的热情!!


-----------------------------------------------

不过多亏这个教程我才知道怎么自定义控件,而且它全文也就这一处错误,总的来说还是收益远大于危害的。

……唉。想不违背公允就得好坏都看,这样一来连发泄一下的机会都没有了……

===================================================================

有时候你需要一个列表来包含一些可选中的item。CEGUI 0.5引入的ItemListbox可以接受所有继承自ItemEntry的item。我将向你介绍如何创建一个CheckListboxItem来放入你的list中。

开始!

我假设你使用的是标准imageset,以及标准scheme(现在支持TaharezLook和WindowsLook)。

我们首先来写一个looknfeel entry。这是本教程中最重要的内容,它将占整个教程70%左右的比重。首先,这个entry有几个声明(states):

1.Enabled:当item是enabled时,它是什么样子。

2.Disabled:当item是disabled时,它是什么样子。

3.SelectedEnabled:当item被选中且是enabled时,它是什么样子。

4.SelectedDisabled:当item被选中且是disabled时,它是什么样子。

写下所需文件

打开一个合适的looknfeel文件(WindowsLook.looknfeel或者TaharezLook.looknfeel),然后在文件底部填上以下内容(说是在最下面但是也要在Falagard tag内!)

我们的开始

我们首先需要定义一个WidgetLook,这个文件里包含所有的动作(action)。它有一个属性,name。它代表拟定一个这个widget的名字。现在我们来添加声明(states)。这些声明(states)使item可以响应指定的事件(Events)。比如,当item被设为disabled,则声明(state)Disabled将被使用。

我们通过StateImagery定义一个声明(state)。它需要属性name来指定它在哪个状态(state)内。先不用管Layer。Section总会被用到。这一部分负责市级改变外观。它需要一个属性section,这是要改变 什么 ,在这里指label。TextColour就是颜色(黑色),我们会在下面定义它。现在,如你所见,Enabled状态(state)只是把文本颜色设为黑色,仅此而已。Disabled也类似(记住这是一个item,items通常不会是disabled状态的)。

现在我们来看看另外两个状态。

这些状态很好地解释了它们自己,虽然里面又多了几个section。Section不仅定义要改变什么,它还定义什么应该被显示。在Enabled状态中我们不想让他看起来是被选中的,所以没有selection section。注意,你书写Section的顺序同时也是Z轴的顺序。在本例中我们把selection图放在前面,然后是文字。如果我们把顺序反过来,就看不到字了。(被selection图挡住了)

现在我们来添加颜色和属性的定义。

我们的第一个PropetryDefinition只是定义了一个用在StateImagery sections中的文本颜色。其他PropertyDefinitions也一样,除了SelectionBrush。它不是定义颜色,而是定义了一个图像。在这个例子里,它使用定义在imageset里的WindowsLook的背景图。然后,我们有了一个可以影响某些设置的Property(属性)。在这个例子里,我们通过添加Selectable属性并设为true来创建一个item。

写功能部分

我们现在需要增加增加绘制背景、文字和选取的部分。这看起来有点难,不过其实不是。我们从一个NamedArea开始吧。它是listbox item所必需的,因为listbox需要知道这个item有多大来确保把它很好地放进list。

我假设你知道Area、Dim之类的基本概念。FontDim是用来根据label改变item的尺寸的。我们刚刚加进去的部分定义了item的尺寸。这次我不再贴出全部代码,而只展示新增的部分。

OK!现在我们来添加一个世纪的Checkbox吧。这对我们的目标来说很重要,因为它是我们的item可以被点击选中。我们不用为Checkbox写全部的状态和其他东西,我们直接用Child!只要把下面这段内容放在我们的NamedArea下面、第一个StateImagery的上面即可。(它俩中间)

这里添加了一个WindowsLook/Checkbox到我们的item里面去了。其中的suffix是必需的,加它是为了使name不重复。剩下的内容就非常直白了——把checkbox加到item的左边,和左边界留出3个像素的距离,让它看起来更平整一些。

现在我们需要一个label,这部分很简单所以我不会花很多时间去解释,基本上看了就明白了。

TextComponent是一个文本容器。Dim是定位。注意LeftEdge,label离开左边界18个像素。这是因为checkbox占了前面15像素的空间。

现在重要的来了!selection image。

注意我们给属性“name”复制为“selection”,as used in the StateImagery.Area部分还是定位和自适应。Dim用来确保整个item都被填满了。

ImageProperty定义了要使用的图像爱你个。我们已经在WidgetLook的前面某处定义了SelectionBrush。它现在只是用图填充那个区域(Area)。ColourProperty给image上色,我们也已经在WidgetLook的前面某处定义过SelectionColour了。VertFormat和HorzFormat是拉伸的(stretched),如果他没有被拉伸,它将只会画image的一个像素点,那就几乎不可见了。拉伸它是为了确保整个区域都被覆盖了。

完成!我们已经写好了我们的looknfeel entry!!

Pfew am I glad thats done.(基拉:我怀疑这是个拼写错误。作者文中多出拼写错误,有的我识别出来了,有的我真是搞不定,比如这句= =b)

给item写代码

到了实际考验我们的新item的时候了。我们需要再做一点工作来增加这个教程的完成度。首先,我们需要创建CheckListboxItem类。然后,我们要添加window工厂(factory)到系统中。最后,我们要做一个Falagard映射(mapping)。我们先从CheckListboxItem类开始吧。

CheckListItem.h

如你所见,这个类继承自ItemEntry。这是必需的,因为这样才能让我们的新item像个正常的item一样运作。需要特别注意的是这个CEGUI_DECLARE_WINDOW_FACTORY(CheckListboxItem). 它告诉CEGUI我们正在声明这个窗口。

CheckListItem.cpp

这里的CEGUI_DEFINE_WINDOW_FACTORY(CheckListboxItem) 非常重要。它告诉CEGUI我们在哪里放置和这个窗口相关的代码。如你所见,这个类非常空,你,当然,可以加任何你喜欢的东西到这个类里面来——这里写的只是类的基础框架。

现在,还有一件重要的事要做。在CEGUI中正确地注册这个窗口。

(译注:实践证明,addFalagardWindowMappings的第二个参数应该填你在CheckListboxItem.cpp里初始化的WidgetTypeName的值,在这个例子里就是“CEGUI/CheckListboxItem”,而不是它的基类“CEGUI/ItemEntry”。具体区别见本文顶部2012.10.15日更新)

addFalagardWindowMappings的参数分别是:名称(Name),类型(Type),LooknFeel,窗口渲染器(WindowRenderer)。只要把这段代码放在你的main文件的某处,或者放在其他你确定可以在使用我们的新item之前会被执行到的地方。还要注意,为了使用CEGUI_WINDOW_FACTORY(),你需要在CEGUI命名空间内部。

实例

main.cpp

如你所见,在这个main函数里,注册窗口的函数在实际创建窗口之前被调用了。不要在意SDL初始化的部分——那只是我的个人测试环境而已。

恭喜!你已经创建了一个CheckListboxItem了。这是一个非常好的练习,因为你也学会了如何写一个复合Widget。

如果你有任何疑问、评论、反馈……任何事的话,欢迎发邮件告诉我。我的邮件地址是 levia at openfrag dot com.


--User:Levia 21:10, 5 April 2007 (GMT+1)

====== 译者后记 =======

@DHorse WordPress太凶残了,我在你那个网站上上好色的XML代码它都吞,好象是见了尖括号就管不住嘴似的。我算怕了它了,全部贴图搞定!哇哈哈哈哈!!

Re: SSH 中文亂碼問題

文章由 fishman8 » 2011-09-09, 23:31

prereqirement: ipkg, optware-devel


#-----for ARM CPU
cd /volume1/@tmp
wget http://sourceforge.net/projects/dsgpl/f ... 8f628x.tgz
tar xvfz gcc421_glibc25_88f628x.tgz
cd arm-none-linux-gnueabi/arm-none-linux-gnueabi/libc/usr/bin
cp locale /opt/bin
cp localedef /opt/bin
cd /volume1/@tmp
cp -R arm-none-linux-gnueabi/arm-none-linux-gnueabi/libc/usr/share/i18n /usr/share
#-----keep another copy safe in case DSM is reinstalled later
cp -R arm-none-linux-gnueabi/arm-none-linux-gnueabi/libc/usr/share/i18n /opt/share
mkdir /usr/lib/locale
localedef -c -f UTF-8 -i en_US en_US.utf8

然後用root 在 /etc/profile 檔案最後面加上
export LANG=en_US.UTF-8
就可以在 ssh 看到中文了。至少我 DS211j 是這樣成功的。

參考來源: http://pcloadletter.co.uk/2011/08/02/se ... ology-nas/

===================== 

以上转载自http://forum.synology.com/cht/viewtopic.php?f=6&t=3787

基拉补充:

ipkg安装是很早以前就完成了的,具体步骤我忘了= =

optware-devel的安装倒是可以说一下(其实就是照搬上面的参考来源= =)

ipkg update
ipkg install optware-devel

It will halt and complain that package wget-ssl clashes with wget. Continue with:

译:install optware-devel命令执行到一处会终止,原因是wget-ssl和wget冲突(真的!我也遇到了)。这时请按以下步骤解决:

cp /opt/bin/wget /opt/bin/wget-old
ipkg remove wget
cp /opt/bin/wget-old /opt/bin/wget
ipkg install libidn
ipkg install optware-devel

这次就能安好了。

(流水帐)

原因:

update失败是因为ipkg找不到它自己的wget(在/opt/bin/wget)。系统中有两个wget,另一个在/usr/syno/bin/wget。因为PATH变量中目录先后顺序的关系,系统会优先调用后者。

解决办法:

调整目录顺序

export PATH=/opt/bin:$PATH

(临时调整,重新登录失效)

然后ipkg update; ipkg install XXX 都可以正常运转了。

未解之谜:

为什么会变成这样?以前有段时间里都是没问题的呀?

参考文献:

http://forum.synology.com/enu/viewtopic.php?f=40&t=34693

我喜欢用ArrayList容器做参数,但总是为填充一个临时的ArrayList不够方便而苦恼。

比如说,以前,如果有一个ArrayList<String>做容器的函数 handleStrList(ArrayList<String> args) 的话,为了创建临时List喂给它,我会这样写:

handleStrListnew ArrayList<String>(){{
 add("string_1");
 add("string_2");
}})

上面的代码约等于:
class myTemp0001 extends ArrayList<String> {
   {
       add("string_1");
       add("string_2");
   }
}
handleStrListnew myTemp0001() )


写那么多个add很讨厌,也不优雅,但优雅的我不会- -

直到后来,我学到这招:

handleStrList(new ArrayList<String>( Arrays.asList("string_1","string_2") ) )

如果handleStrList函数不会增删改动它的参数的话,上面的 new ArrayList<String> 部分也可以省略:

handleStrList( Arrays.asList("string_1","string_2") )

优雅多了哈^_^

原理我懂,你一查你也知道,就不在这里卖弄了

这种小技巧对编程基本上没有什么帮助,不过偶尔想到了,觉得挺有趣的,就说一下吧。

果handleStrList函数不会增删改动它的参数的话,上面的

new ArrayList<String>(){{


handleStrList( new ArrayList<String>( Arrays.asList("string_1","string_2") ) )

  add("string_1")


;

  add("string_2");
}}


class myTemp0001 extends ArrayList<String> {
{

add

("string_1");

add("string_2");
}

经过了说明会+笔试C语言实际编程考试开发部员工面试高层管理者面试社长最终面试以后,终~于拿到了那家游戏公司的内定。整个选考过程耗时一个多月。

从去年10月开始就职活动以来,找工作断断续续持续了12个月。最开始去参加各大游戏公司的宣讲会是挺好玩(见到了活生生的任天堂老总岩田聪!),可到了后期就真是一场煎熬了。

就职需要主动出击,大量报名,面试时积极地推销自己,这对我来说都是困难。

就职以来,除了10几家“重在参与”型的梦幻级顶尖游戏公司以外,我真正投过的普通游戏开发公司其实只有两三家。同期就职成功的同学都是投了20多家以后才得以结束就职的,而那20多家,人家也早在4、5月份就投完了。相比之下,我这平均一个月投一家的速度,不知道的还以为是我不着急呢吧。

我都快急死了= =

从最开始只盯着超一流游戏公司,到受薪金诱惑想转投其他IT相关的高待遇行业,到最后理清思路认清现实瞄准小型游戏公司重新出发,我的就职之曲折连我自己都被惊到了。幸好最终还是在游戏行业中得以落脚,谢天谢地,可歌可泣。

我自称是个没主见的被动的人,面对不确定的未来总是提心吊胆焦虑不安,面对喜欢的人和事总是犹豫不决驻足不前。但即使这样不争气的我,也有让我为之自豪的一点:我有一个愿意与之相伴一生的领域——ACG。

如果是为了她,即使叫我去和陌生世界交流我也愿意;如果是和她一起,即使是不确定的未来我也乐得闭着眼睛走进去。我是没交过女朋友啦,不过凭我丰富的暗恋经验,我知道这和喜欢一个女孩的感觉是很像的。

说起来,这两天面试也被问到女朋友的话题了呢。总之是,好想找个女朋友啊

为了提高效率,我用java自带的线程池ThreadPoolExecutor把一个研究工具的处理过程做成了多线程,在研究室的四核cpu8G内存的电脑上跑效果拔群。只是,时不时的会出现cpu使用率为0的卡死现象,很难触发,无法重现,目测为多线程bug。(多线程新手一个,目测也没什么依据^_^b)

我觉得,如果是我的程序死循环了,cpu应该100%的,但是没有。

程序我设了超时后改变控制循环的bool型flag,应该是可以确保线程退出的,但是卡住了。

往线程池里填完任务以后,等待任务完成的代码是这样的:

ThreadPoolExecutor executor = new ThreadPoolExecutor(...)

...

executor.shutdown();

executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);

我觉得吧,应该是程序在await这里永远的等下去了。所以才会没有反应也不占cpu。

因为问题难以重现,我也想不出来应该在哪里设断点……Orz

所以,这个【未解决】恐怕要挂很久了。

要命的是,这个程序事关一个评测(比赛),时限4天。我初步计划花38小时无人值守让程序自己跑的。现在出了这个bug,我就只能时不时起来看看它,死了得关掉重开。不仅麻烦而且浪费宝贵的时间,真是……恨自己学艺不精啊!当年小勤同志告诉我,java学到后面是XXX,再后面是XXX,在后面是XXX,在后面是多线程。果然是很后面的技术,平时根本用不到,没经验。真正用起来了出了错难以调试,难学难提升。 不过,挺有趣的^_^

明天将(基本上)决定我是不是需要多浪费一年生命找工作,我得去琢磨我的面试草稿了。这个程序题很有挑战,但我没空,时间不合适,也没有很好的条件去解决这个问题(4核全100%运转的电脑,是很卡的,基本上什么也干不了……)。所以,以后吧。(嗯,拖延的借口越编越真实了)

executor.shutdown();

给我一个进入游戏业界的机会吧!拜托了!