孔雀开发小屋

专注并致力于手机客户端开发
<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

统计

  • 随笔 - 103
  • 文章 - 0
  • 评论 - 251
  • 引用 - 0

常用链接

留言簿(38)

随笔分类

随笔档案

关注的博客

朋友的博客

搜索

  •  

最新评论

阅读排行榜

评论排行榜

代码随想

     摘要: 工程项目中不是讲究新鲜的语言技巧、语法规范。不要华丽的新技术。要的就是正常而稳定,稳定压倒一切。  阅读全文

posted @ 2010-03-31 00:00 孔雀 阅读(1912) | 评论 (4)编辑 收藏
DirectInput入门

我想在博客里记录一些学习DirectX的笔记。这是第一篇。
一直以来对于DirectX的一套没有花时间去学习,3D图形api也是学习了OpenGL,相当长的一段时间里,总是认为自己不会去接触这些。到公司写了快一年的游戏逻辑了,才明白逻辑固然很重要,但是写逻辑写一年和写两年的区别不大。做游戏,做网游不就那几个大块么,图形,网络,数据库,io并发。写逻辑是要写的,但终究需要在某一领域有所专长,才是正道。

言归正传吧。

DirectInput是一个不依赖硬件的虚拟输入系统,是建立于硬件抽象层(HAL)之上的接口。

微软的DirectX一套均采用COM开发,所以无论DDraw还是DirectInput的构建、设置、使用,代码都相差无多。基本步骤都是建立xxx接口对象,建立xxx设备,设置xxx相关属性(参数),使用之。

我们要在应用程序中使用DirectInput,分以下三步走。
1)初始化
2)获取设备状态
3)根据设备状态,进行你的自定义处理。

我这里给出一个简单的例子。该例子就是在标准的windows应用程序中使用DirectInput所需的步骤。
首先需要包含必要的宏定义和头文件

1 #define INITGUID
2 #include <objbase.h>
3 #include <dinput.h>

相关的全部变量:
LPDIRECTINPUT       g_dinput = NULL;
LPDIRECTINPUTDEVICE g_Keyboard 
= NULL;


建立初始化函数:

 1 BOOL InitDirectInput(HINSTANCE hInstance)
 2 {
 3     // 创建DirectInput对象
 4     if (DI_OK != DirectInputCreate(hInst, DIRECTINPUT_VERSION, &g_dinput, NULL))
 5         return FALSE;
 6 
 7     // 创建键盘设备
 8     if (DI_OK != g_dinput->CreateDevice(GUID_SysKeyboard, &g_Keyboard, NULL))
 9         return FALSE;
10 
11     // 设置协作等级
12     if (DI_OK != g_Keyboard->SetCooperativeLevel(g_hWnd, DISCL_NONEXCLUSIVE|DISCL_BACKGROUND))
13         return FALSE;
14 
15     // 设置数据格式
16     if (DI_OK != g_Keyboard->SetDataFormat(&c_dfDIKeyboard))
17         return FALSE;
18 
19     // 获取设备
20     if (DI_OK != g_Keyboard->Acquire())
21         return FALSE;
22 
23     return TRUE;
24 }

在哪里使用呢?我们在windows消息循环里面,处理完消息之后:
 1     unsigned char keyboard_state[256];
 2     // Main message loop:
 3     while (GetMessage(&msg, NULL, 00)) 
 4     {
 5         if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
 6         {
 7             TranslateMessage(&msg);
 8             DispatchMessage(&msg);
 9         }
10 
11         g_Keyboard->GetDeviceState(256, (LPVOID)keyboard_state);
12         if (keyboard_state[DIK_UP])
13         {
14             ::MessageBox(NULL, "up""msg", MB_OK);
15         }
16     }

基本就是这些了。

我这里主要是作为学习笔记留在blog上,说的不清楚或者不专业或者其他原因让你没有看明白的,请看
《windows游戏编程大师技巧》一书。






posted @ 2010-03-30 23:55 孔雀 阅读(2395) | 评论 (7)编辑 收藏
boost库的Singleton的实现

在工作中遇到不少情况使用singleton模式,下面采用的是最简单的一种形式:

 1 class Foo
 2 {
 3 public:
 4     static Foo& getSingleton()
 5     {
 6         static Foo foo;
 7         return foo;
 8     }
 9 
10 private:
11     Foo();
12 };
这种实现,在单线程情况下,简单而有效。

对于线程安全的singleton的实现,网上有不少讨论。这两天看到boost库中的一种实现,没有使用锁机制,而是充分利用了C++的语言特性较好的解决了多线程情况下使用singleton的问题。
boost的singleton的实现基于以下假设:良好的设计在进入main函数之前应该是单线程的。
我们可以使用全局变量的方式来设计singleton,并且保证在使用该singleton之前其已经被正确的初始化,如何做到?且看代码:
 1 template <typename T>
 2 struct Singleton
 3 {
 4     struct object_creator
 5     {
 6         object_creator(){ Singleton<T>::instance(); }
 7         inline void do_nothing()const {}
 8     };
 9 
10     static object_creator create_object;
11 
12 public:
13     typedef T object_type;
14     static object_type& instance()
15     {
16         static object_type obj;
17         create_object.do_nothing();
18         return obj;
19     }
20     
21 };
漂亮而巧妙的实现。
但是上面的实现还是有一点小的缺憾,那就是只能调用类的默认构造函数,不能调用带参数的构造函数。

附:
非常抱歉,上面这个代码是有点问题的。感谢各位童鞋及时回复并指出问题所在。现在补上缺失的初始化部分。
1 template <typename T>
2 typename Singleton<T>::object_creator
3 Singleton<T>::create_object;


posted @ 2010-02-28 22:48 孔雀 阅读(7045) | 评论 (21)编辑 收藏
Placement new的用法及用途

     摘要: C++中placement new的标准使用方法及用途
  阅读全文

posted @ 2010-02-20 14:20 孔雀 阅读(11449) | 评论 (4)编辑 收藏
一些随想

17号就从家做飞机返京,过春节就在家呆了一个礼拜,又要匆忙的回来工作了。

18号中午送走女友,一个人回到房里,上网一直到晚上,吃饭回来也是继续上网。想今年搞点小成本的投资,google了半天,论坛也看了半天,未果。

晚上一个人出来吃饭,走在小区里和街上,听到振聋发聩的烟花爆竹的声音,有点反感大城市里这种的烟花爆竹的声音,经过层层高层小区建筑的回音继而扩大,那声音失去了原本的清亮与干脆。

新的一年,又要工作一年了。告诉自己好好干吧。

1. 做好现在的本职工作,并希望有一些突破。
2. 自己业余时间想做的一款游戏,也希望在今年年底之前给完成了。
3. 希望在网络编程方面和微机系统方面的认识与理解有所提高。
4. 学点中医。






posted @ 2010-02-19 18:27 孔雀 阅读(285) | 评论 (1)编辑 收藏
C++库--使用TinyXML库遍历XML文件

最近在写一个小工具时,需要用C++解析XML文件。使用了TinyXML这个精巧的C++库,使用起来确实比较方便,下面给出如何遍历一个xml文件的方法,很好用哦,根据自己的需要可以修改该函数,虽然简单,但是实用。

 1 void
 2 parseElement( TiXmlNode* pElem )
 3 {
 4     if ( NULL == pElem )
 5     {
 6             return;
 7     }
 8 
 9     TiXmlNode*    pElement = pElem->FirstChild();
10 
11     for ( ; pElement; pElement = pElement->NextSibling() )
12     {
13         int nType    = pElement->Type();
14 
15         switch ( nType )
16         {
17             case TiXmlNode::ELEMENT:
18                 parseElement( pElement );
19                 if ( 0 == stricmp( pElement->Value(), “Property” ) )
20                 {
21                     std::string strValue = pElement->ToElement()->Attribute( “Value” );
22                     size_t pos = strValue.find( “set” );
23                     if ( string::npos != pos )
24                     {
25                         std::cout << strValue << std::endl;
26                     }
27                 }
28                 break;
29             case TiXmlNode::TEXT:
30                 std::cout << pElement << std::endl;
31                 break;
32             default:
33                 break;
34         }
35     }
36 }
37

posted @ 2010-01-16 20:14 孔雀 阅读(7890) | 评论 (3)编辑 收藏
我们需要什么样的游戏

     摘要: 说说09年的游戏界的两匹黑马,一个是《植物大战僵尸》,一个是《偷菜》。

游戏太多了,现在仅网游成功的就有上百款。单机更是不胜其数。我一直在考虑,我们到底需要什么样的游戏。

作为一个程序员,很自然的会从技术角度去先评估一下这些游戏,对比成功的与失败的有什么不同。我思考良久,得到的结论是:技术非常重要,技术又很次要。  阅读全文

posted @ 2010-01-15 00:06 孔雀 阅读(2378) | 评论 (9)编辑 收藏
网络通信模型之select模型

为什么会出现select模型?

先看一下下面的这句代码:
int iResult = recv(s, buffer,1024);
这是用来接收数据的,在默认的阻塞模式下的套接字里,recv会阻塞在那里,直到套接字连接上有数据可读,把数据读到buffer里后recv函数才会返 回,不然就会一直阻塞在那里。在单线程的程序里出现这种情况会导致主线程(单线程程序里只有一个默认的主线程)被阻塞,这样整个程序被锁死在这里,如果永 远没数据发送过来,那么程序就会被永远锁死。这个问题可以用多线程解决,但是在有多个套接字连接的情况下,这不是一个好的选择,扩展性很差。
再看代码:
int iResult = ioctlsocket(s, FIOBIO, (unsigned long *)&ul);
iResult = recv(s, buffer,1024);

这一次recv的调用不管套接字连接上有没有数据可以接收都会马上返回。原因就在于我们用ioctlsocket把套接字设置为非阻塞模式了。不过 你跟踪 一下就会发现,在没有数据的情况下,recv确实是马上返回了,但是也返回了一个错误:WSAEWOULDBLOCK,意思就是请求的操作没有成功完成。 看到这里很多人可能会说,那么就重复调用recv并检查返回值,直到成功为止,但是这样做效率很成问题,开销太大。

select模型的出现就是为了解决上述问题。

select模型的关键是使用一种有序的方式,对多个套接字进行统一管理与调度

看核心代码:(这里只给出服务端的)

while ( 1 )
{
// 初始化fdset
FD_ZERO( &fdsRead );

// 将server套接字添加到可读集合中
FD_SET( sockServer, &fdsRead );

// 调用select
select( 0, &fdsRead, NULL, NULL, &tv );

// 判断server套接字的状态,如果套接字还在可读集合中,
// 说明有数据可以读入,则建立套接字可以成功
if ( FD_ISSET( sockServer, &fdsRead ) )
{
sockAccept = accept( sockServer, (sockaddr*)&addr, &nLen );
// 有数据可读,进行相关处理
}

当然了,这里演示的只是最基础的select的用法。网络通信中的I/O复用的相关问题还很多,还需要慢慢学习与深入。


posted @ 2010-01-13 22:55 孔雀 阅读(2908) | 评论 (0)编辑 收藏
程序员的五种非技术错误

下面这篇文章摘自链接:http://coolshell.cn/?p=1145

我认为这篇文章写得非常好!值得收藏。

对于程序开发者来说,有两种技术需要我们掌握,一个是技术上的能力,另一个是非技术上的能力。不幸的是,许多程序员过多地关注了技术上的能力,而忽 略了非技术上的能力的培养,因此,我们的程序员们经常会有一些很不好的习惯,这里我们例举了程序员们最常犯的5个非技术的错误,与大家共勉。

1.- 缺乏团队纪律

“Discipline is the bridge between goals and accomplishment.” Jim Rohn.

纪律是一个最有价值的技能,不仅仅只是在软件开发领域,同样在其它领域也是一样的。但对于现实来说,我们很难找到即有才华又有纪律的人。这正如足球 队一样,非洲的球员们才华相当的出众,可惜他们总是独自为阵,团队纪律性不足,所以可以有好的成绩,但却无法赢得最后的胜利;而德国队的队员个人技能平 平,但其有很强大的团队纪律性,所以,总是能打入最后的决赛并获得冠军。有人说过,个人英雄并不可怕,而有强大纪律性的团队才让人可怕。这正是日本这个民 族的可怕之处。况且,软件开发从来都不是一个人可以完成的事情,所以团队工作中的纪律性会是非常重要的。

Steve Pavlina 强调了自律中5个因素:“承担, 毅力, 努力, 勤奋, 和坚持” 这里,我们强烈推荐你读一读Steve的 关于自律的文章

下面是我们觉得程序应该有的比较良好的习惯。

  • 每天都有自己的to do list
  • 在一个时间内只做一个事
  • 把事情做对了
  • 事情没有完全完成时不要轻易结束
  • 慢点总比道歉好,道歉总比不做好

2.- 过度自负

我们的经验告诉我们,过度的自负的人一般是意识不到自己的自负,下面是一些过度自负的特征,希望你可以从中检测一下自己是否过度自负了。

  • 觉得自己是最牛的程序员
  • 总是打断谈话
  • 你要求Code Reivew不是要检查代码,而是向大家炫耀你的代码

在网上有太多的文章关于程序员的自负的问题,这里有两篇,你可以看看:一篇是Mike Bernat的 Egoless programming(无自负编程) 还有一个是stackoverflow.com 上的一个贴子

3.- 沟通不畅

“如果我要说十分钟,我需要一周做准备;如果说15分钟,我需要3天做准备;半个小时,我需要两天;如果说一个小时,我现在就准备好了。” Woodrow Wilson

人类的沟通是我们最主要的活动。成为一个好的沟通者是一件很难的事情,我们不断地和别人交换关于设计,编码,文章的意见,并且我们每天都在试图说服别人我们自己的设计和想法会更好,更有道理……

然后,好的沟通者是那些当他们正在解释一些事情的时候,他们的解释是下面这个样子的:

  • 专注。不跑题,没有废话。
  • 清晰. 很容易听懂。
  • 简明. 加一点就觉得多,少一点都觉得不够。

要有一个好的沟通技巧,我们的建议如下:

  • 如果你觉得你沟通方面不够好的话,请事先准备你要表达的东西,努力做到专注,清晰和简明。
  • 在交谈中,先听,后想,最后再说。
  • 永远从对方的角度思考问题。

4.- 忘了用户

“如果我们不关心我们的用户……那么别人会”

你的存在,你工作的意思只有一个原因——你的用户。我们在很多时间都会忘了这个事情。经常,我们在工作当中,技术会取代用户而占据了主要的位置,我 们可以花费数月的时间来创建一个程序框架,但一个程序框架不会给用户代来任何的价值,我们不是说程序框架不重要,而是说,对于用户的需求来说,这是其次重 要的东西。如果离开了用户的需求,我们所有的技术,算法或是精妙的设计将会变得什么也不是。

5.- 不懂工作的轻重缓急

程序员总是喜欢去研究一些新的或自己感兴趣的东西,但对于软件工程来说,我们更需要知道所有事情的轻重缓急,要学会如何了解事情的优先级,这样才会 让我们的工作事半功倍,而我们的工作也会更有效。比如,当用户的站点出现问题的时候,有些时候,我们的程序员过试地关注于问题的重现和原因,而忘记了用户 的站点正在流血,无法进行生产。所以,一般来说,最重要的事情首先是恢复用户站点,然后才是去重现和调查问题。在我们的日常工作中,我们要处理很多事情, 只有了解到了所有事情的轻重缓急,处理最重要最紧急的事情,我们才能够更好的安排自己的工作,才能够更好的完成我们的事情。不要以为这是一件很简单的事 情,这需要我们不断地和别人沟通来了解事情的轻重缓急,事实证明,如果我们不懂工作中的轻重缓急,本来只有一件紧急的事情,如果处理不当,最后可能会演变 成多件紧急事情,其它本来不紧急的事,后来也会变得很紧急,最终程序员们顾此失彼,苦不堪言。希望大家切记。

posted @ 2010-01-12 21:39 孔雀 阅读(2612) | 评论 (1)编辑 收藏
植物大战僵尸资源提取

植物大战僵尸是09年非常风靡的一款游戏。虽然是2D画面,但是其游戏性、画面的轻松可爱、恰到好处的音效使人爱不释手。

最近想做一款类似的游戏,想先暂用其图像资源与音乐资源来,而专注于游戏程序编写本身。发现其所有的资源都打包在main.pak包中。经过一番努力,终于从中提取到所有的png图像1800多张,ogg格式音乐文件300余首。现在将整个过程简要说明。

1)该main.pak经过了加密。其实只是通过0XF7进行了一个简单的xor运算。通过对源文件进行xor运算可以得到未加密的资源文件。我们这里叫做mainbak.pak。
2)写一个程序将mainbak.pak读取,然后在文件(二进制)中查找png和ogg文件格式的特征码(魔数)。循环读取,就可以获取所有的资源了。

附:
png文件格式开头:0x89 0x50 0x4E 0x47
png文件格式结尾:0x49 0x45 0x4E 0x44 后面还有四位CRC,不过选取这四位标示结尾就可以了。算文件长度的时候记得加上四位CRC就可以了。

ogg魔数:0x4F 0x67 0x67 0x53 0x00 0x02 0x00 0x00 0x00 0x00

enjoy it !

posted @ 2010-01-10 01:16 孔雀 阅读(6142) | 评论 (8)编辑 收藏
仅列出标题
共11页: First 3 4 5 6 7 8 9 10 11