摘要: 工程項目中不是講究新鮮的語言技巧、語法規范。不要華麗的新技術。要的就是正常而穩定,穩定壓倒一切。 閱讀全文
我想在博客里記錄一些學習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, 0, 0))
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游戲編程大師技巧》一書。
在工作中遇到不少情況使用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;
摘要: C++中placement new的標準使用方法及用途
閱讀全文
17號就從家做飛機返京,過春節就在家呆了一個禮拜,又要匆忙的回來工作了。
18號中午送走女友,一個人回到房里,上網一直到晚上,吃飯回來也是繼續上網。想今年搞點小成本的投資,google了半天,論壇也看了半天,未果。
晚上一個人出來吃飯,走在小區里和街上,聽到振聾發聵的煙花爆竹的聲音,有點反感大城市里這種的煙花爆竹的聲音,經過層層高層小區建筑的回音繼而擴大,那聲音失去了原本的清亮與干脆。
新的一年,又要工作一年了。告訴自己好好干吧。
1. 做好現在的本職工作,并希望有一些突破。
2. 自己業余時間想做的一款游戲,也希望在今年年底之前給完成了。
3. 希望在網絡編程方面和微機系統方面的認識與理解有所提高。
4. 學點中醫。
最近在寫一個小工具時,需要用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
摘要: 說說09年的游戲界的兩匹黑馬,一個是《植物大戰僵尸》,一個是《偷菜》。
游戲太多了,現在僅網游成功的就有上百款。單機更是不勝其數。我一直在考慮,我們到底需要什么樣的游戲。
作為一個程序員,很自然的會從技術角度去先評估一下這些游戲,對比成功的與失敗的有什么不同。我思考良久,得到的結論是:技術非常重要,技術又很次要。 閱讀全文
為什么會出現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復用的相關問題還很多,還需要慢慢學習與深入。
下面這篇文章摘自鏈接: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.- 不懂工作的輕重緩急
程序員總是喜歡去研究一些新的或自己感興趣的東西,但對于軟件工程來說,我們更需要知道所有事情的輕重緩急,要學會如何了解事情的優先級,這樣才會
讓我們的工作事半功倍,而我們的工作也會更有效。比如,當用戶的站點出現問題的時候,有些時候,我們的程序員過試地關注于問題的重現和原因,而忘記了用戶
的站點正在流血,無法進行生產。所以,一般來說,最重要的事情首先是恢復用戶站點,然后才是去重現和調查問題。在我們的日常工作中,我們要處理很多事情,
只有了解到了所有事情的輕重緩急,處理最重要最緊急的事情,我們才能夠更好的安排自己的工作,才能夠更好的完成我們的事情。不要以為這是一件很簡單的事
情,這需要我們不斷地和別人溝通來了解事情的輕重緩急,事實證明,如果我們不懂工作中的輕重緩急,本來只有一件緊急的事情,如果處理不當,最后可能會演變
成多件緊急事情,其它本來不緊急的事,后來也會變得很緊急,最終程序員們顧此失彼,苦不堪言。希望大家切記。
植物大戰僵尸是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 !