遊戲人的心得錦集
下面收集職業、業餘遊戲開發者的心路歷程,國內唯一以心得出一本書的遊戲人大概就只有半路了,下面這份名單會不定期更新。
最後一次更新2015-10-21
猴子靈藥的中肯入行忠告
前進遊戲界:給大學生的行前準備建議
"前進天空樹"的製作人
給想全職做遊戲的你
雖然不是出自遊戲開發者之手,但是非常適合有興趣的學生
給大學生的忠告:把興趣當工作,不會帶給你快樂
NDark在元智大學的演講稿
遊戲製程心得二三事
Chris Crawford所寫的
頂級遊戲設計大師談如何成為一名遊戲設計師
興趣跟工作兩者之間本來就有著截然不同的性質,但是對社會新鮮人而言,常常覺得做自己喜歡做的工作才是理想目標,不希望將青春花在不喜愛的事物上,不希望為了賺錢而賺錢,希望往自己的興趣發展也能闖出一片天。
這沒什麼不好,親自去試過才會知道自己是怎樣的人,才會知道自己究竟能不能忍受逐夢的辛苦,究竟是不是真的不在乎薪水,這原本是畢業之前就該搞懂的事,不過長輩大多在你求學期間只會跟你說「先把書讀好」、「考到一所好學校再說」之類的,也許連這些出社會的大人們也不清楚自己的目標,如果沒搞清楚自己的方向,跑再遠都是白搭。
想要找適合自己的道路就必須先好好的認識自己,先尋找自己的起點才不會迷失方向。
我自訂的設計模式
2016/08/10
這篇提到的做法已經被我捨棄了,物件之間有依賴關係時,使用 std::shared_ptr 處理就已經很理想了。
在開發ToyBox途中,我設計了一個簡單的設計模式,用來解決我擔心的某種資源洩漏狀況。
很多情況下,兩個物件可能在資源上有依賴關係,需要互相保持聯絡,注意對方手上的資源是否還存在,當其中一方被銷毀或者打算切斷關係時,有必要通知對方一聲,讓對方可以處理一下(不要說一直到打了電話才知道這個人已經切斷關係),這可以避免許多記憶體問題,算是一種制式化的觀察者模式,只觀察對方是否打算斷絕聯絡,彼此互相觀察。
實作上就只是互相記住對方的指標,然後準備好一個callback function,上面紀錄當對方斷線時該如何應對,當對方斷線時就會由對方呼叫這個callback function。
實作寫在 ToyBox/include/toy/Link.hpp,大概要用一段時間才知道這作法的優缺點,有可能到頭來我只發現這作法是多此一舉也說不定,如果你對這個模式有什麼更好的建議,歡迎留言或來信告知。
#include <stdio.h>
#include "toy/Link.hpp"
//當 obj_B 主動絕交時會呼叫這個 obj_A 預先準備的行為
void obj_A_reaction()
{
printf("goodbye obj_B\n");
}
//這範例是 obj_A 先斷交的,所以只有執行這個
void obj_B_reaction()
{
printf("goodbye obj_A\n");
}
int main()
{
toy::Link obj_A;
toy::Link obj_B;
obj_A.SetReaction(&obj_A_reaction);
obj_B.SetReaction(&obj_B_reaction);
obj_A.Connect(obj_B); //兩者連結上了
obj_A.Disconnect(); //由obj_A主動斷交,此時只會呼叫obj_B_reaction()
return 0;
}
成員函式的callback function
C語言的callback function做法只能用函式指標去儲存全域函式,在C++中要用同一招會顯的很不自然,因為全域函式無法封裝到類別當中,而member function則無法直接傳遞函式指標,因為沒連帶物件指標一起傳是沒用的。
於是boost用樣板技巧創造出可以呼叫成員函式的「仿函式」,它將成員函式跟物件的指標封裝在一起,呼叫的人並不需要知道這boost::function的內容物是哪裡來的,裝的是全域函式還是成員函式也不用知道,甚至連這函式實際上到底需要多少個參數也不知道,非常全面的取代了 C語言的 callback function,你只要知道它可以取代函式指標,尤其想實現成員函式的callback function只剩這條路可選。
不過需要注意「仿函式」是用樣板實現的,而樣板魔法只能實作在標頭檔上面,這也不算什麼缺點,跟它帶來的好處相比實在太划算了。
仿函式歷經長時間的演化,已經成為了非常強大的好用工具,在C++11裡面已經成為標準庫成員了。
我的專案裡有個山寨版的仿函式實作,大多功能都有實現了,內容會比boost的原作好懂許多
,還滿有趣的,尤其bind的實作手法相當精彩,運用了繼承、樣板偏特化、多載,感謝boost高手們的貢獻,如果看不懂實作的話無所謂,畢竟那些樣板技巧很少用到。
#include <stdio.h>
#include <functional.hpp>
void MyFunction(int a)
{
printf("%d\n",a);
}
int main()
{
using namespace std::placeholders; // for std::placeholders::_1
std::function<void(int)> func=std::bind(&MyFunction,_1);
func(5);
return 0;
}
lua與C++之間的互動:如何在lua裡面建立C++的物件
首先lua並不支援你將Class傳到script這邊,lua只支援將一個C風格的全域函式指標傳過去,因此一切行動都是從全域函式開始的。
基本概念就是將C++的一組全域函式傳到lua這邊,然後用lua的table將它們包裝的像個物件一樣,table會內含一個物件指標,這就是大致上的實作方向了。
首先在C++這裡寫個全域函式負責動態配置物件,將它的函式指標傳到lua之後會扮演建構子的角色,產生的物件指標會用lua的userdata來儲存。
另外再寫幾個全域函式來負責操作物件指標,它們的函式指標傳到lua之後會扮演成員函式的角色。
將上面這些函式裝到lua的table上面就可以直覺的使用C++的物件了。
解構子則不需要以上做法,在儲存物件指標的userdata上面就可以指定解構行為了。這裡需要注意一點,lua的解構時間點跟C++不同,因為lua的垃圾收集機制不是當變數無人使用時就會去清理,所以不要以為區域物件在離開該區域時就會當場解構,而且由於指標的size太小,lua根本不知道指標背後咬了多大一塊記憶體,可能會累積超多物件才解構,你最好自己親自呼叫"__gc"來解構,或者
用collectgarbage("collect")
強制要求立刻
清理。要傳給lua使用的全域函式有固定的格式(lua_CFunction),而且從lua取得參數以及送回傳值給lua都需要呼叫lua介面來執行,你可以看到網路上有很多教學是自己寫個Wrapper類別來當中間層,然後為類別量身打造一系列全域函式,這樣寫起來會很累,而且不能封裝的全域函式會破壞OO架構,程式碼不會好看到哪去。
幸虧C++還有樣版這樣的特別武器,可將上述手續給包裝起來,真的輕鬆超多的,我的luapp專案就是在做這件事,luapp已經將這份工作包裝的很舒服了。
當然檯面上還有其他更成熟的專案提供更全面的功能,不過以我的需求來說,自製的luapp已經堪用了。
CMake指令
CMake的組態檔總是命名為"CMakeLists.txt"
CMake的語法是由一堆函式構成
不管做什麼都是在呼叫函式
以下列出比較常用的
project(專案名稱)
你的專案檔生出來就會用這個名字
cmake_minimum_required(VERSION 2.8)
確認該環境的CMake版本符合你的要求,CMake會強迫要求你在主專案加上這行,子專案就沒關係
add_subdirectory(子資料夾)
進入指定資料夾然後執行裡頭的組態檔"CMakeLists.txt",這設計讓你很容易增加子專案
include_directories("路徑")
告訴CMake該去哪裡尋找標頭檔
link_directories("路徑")
告訴CMake該去哪裡尋找函式庫
add_executable("執行檔名字" main.cpp main2.cpp main3.cpp)
決定要編譯哪些程式碼,然後產生程式
set(EXECUTABLE_OUTPUT_PATH "路徑")
決定編譯出來的執行檔要放哪裡
add_library(函式庫名稱 STATIC main.cpp main2.cpp main3.cpp)
決定要編譯哪些程式碼,然後產生函式庫,STATIC表示你要編譯成靜態函式庫,動態要寫SHARED
set(LIBRARY_OUTPUT_PATH "路徑")
決定編譯出來的函式庫要放哪裡
target_link_libraries(函式庫/執行檔名稱 需連結的函式庫名稱)
決定要連結的函式庫,執行檔跟函式庫都用這個設定
message("想傳達的訊息")
CMake允許你在生成專案檔的過程印出一些訊息
訂閱:
文章 (Atom)