歡迎光臨
每天分享高質量文章

利用Python進行游戲腳本編程,不愧是最強的腳本語言!

使用腳本語言可以更加快速地開發游戲邏輯,而不必擔心由於 C++ 程式員的粗心大意所造成的後果。使用已有的腳本語言可以節省開發新型自定義語言的時間和開銷,並且這些語言通常要比自己創造的語言更加的強大。

當然小編這裡有一份Python學習資料,加小編QQ群:696541369即可免費領取!

Python 對於游戲腳本語言來說是一種不錯的選擇,它很強大,容易嵌入使用,能夠無縫地使用 C/C++ 進行擴展,包含很多腳本語言所具有的高級特性,並且它可以用來實現自動化過程[TR1: automating production]。另外,關於 Python 的書籍、開發工具 和 庫 很豐富,使得我們很容易從其他開發者那裡受益。

下來就談一談我們在 Humongous 娛樂公司將 Python 集成進新游戲引擎的一些經驗。說明我們選擇 Python 的原因、獲得的收益、遇到的問題,以及我們是怎樣解決它們的。

為什麼要使用腳本語言

C++ 是一種強大的語言,並且是 C 語言的巨大改進,但它並不是完成所有任務的最佳選擇。C++ 非常強調運行時性能 [Stroustrup94],譬如,假如一個語言特性使得程式跑起來變慢,那麼這個特性便不會加入 C++ 語言中。C++ 程式員也因此背負了很多的限制和煩惱。

這裡列出一些限制,C++ 程式員經常遭遇這些事情但很少註意它們的存在:

  • 手工管理記憶體:C++ 程式員的大量時間都花在考慮呼叫 delete 的適當時機。
  • 鏈接過程:C++ 模塊(在編譯時或加載時)鏈接在一起,因此在運行時,無需進行的函式地址的解析。這提高了運行時的性能,但是卻使 編輯/測試 周期變長了。
  • 缺乏自省能力 [TR2: introspection]:C++ 有自己的方式知道一個類中包含哪些成員,但是這種方式需要編寫過多的加載和儲存物件的代碼,而在一些腳本語言中這隻需呼叫一個內建函式就可以完成。

C++ 是靜態的,而腳本語言是動態的。簡單地說,C++ 的程式運行地很快,但是腳本語言能讓你編碼更快。

所以,C++ 應該只用在你希望優化運行時性能的地方。現在計算機的運行速度都足夠快,對於大多數代碼來說性能都不是問題。如果你用 C++ 開發那些用腳本語言也能實現的程式,那麼你是在錯誤的事情上進行優化。

SCUMM 的問題

Humongous 公司已經使用 SCUMM (Script Creation Utility for Maniac Mansion) 創造了 50 多個游戲。SCUMM 是一個強大的 冒險游戲 開發語言,但是它有一些局限性。SCUMM 是十多年前寫的,它缺少一些現代語言的特性。

儘管 SCUMM 有持續的補丁和維護,它也沒有辦法像其它語言一樣健壯和有完備的功能了。

為什麼選擇 Python

我們有過創造一種新型的、現代的 私有語言的想法,但最終明智地放棄了這種想法。我們的職責是在做游戲,而不語言。

我們在每年花費大量開銷維護一套私有工具的情況下,確實希望使用一種已有的腳本語言而不是重新創造一種。使用已有語言更快地投入工作,花費更少的開銷,並且通常情況下要比我們創造的好,並且以後會發展地更好,即使我們不用它工作。

一旦我們決定要使用已有的腳本語言,就需要從中選擇一種。我們需要一種支持 面向物件編程,並且能嵌入到我們游戲中的語言,而且它不存在任何技術和許可授權上的問題。

我們考慮了 Lua [Lua01] 和 Python [Python02],這兩種語言已經被應用在某些游戲中了。

Lua 較小,更加容易嵌入到應用程式中,並且有一些很棒的語言結構。但是,那時我們發覺 Lua 的文件有些粗略,這大概是因為 Lua 是比 Python 更新的語言。

Python 比 Lua 有更多的擴展模塊,更多的參考書籍,並且 stackless Python [Tismer01] 很適合為物件 AI 創建微執行緒[TR3: micro-threads]。最後我們沒有選擇 Python 的 stackless 版本,但開始用 Python 寫自動生成腳本,這給了我們繼續使用 Python 的動力。當瞭解了 Python 後,我們喜歡上了它的語法,最後選擇了它。

在我們決定之後,這兩種語言都發生了改進:Lua 已經變成 stackless,而 Python 有了生成器,這個能提供一些相似的功能。現在任何一種都是安全的選擇。

誰在游戲中使用了 Python

Python 已經被使用在很多游戲中,包括:

  • ToonTown – http://www.toontown.com/
  • EveOnline – http://www.eve-online.com/
  • Blade of Darkness – http://www.codemastersusa.com/blade/

還有很多其它的游戲,只是我們很難確認,例如至少有一個 PS2 游戲使用了 Python。

同時 Python 也至少用在兩個游戲引擎中:

  • Game Blender – http://www.blender.nl/gameBlenderDoc/python.html
  • PyGame – http://www.pygame.org/

一個生成腳本示例

下麵是一段 Python 代碼示例,它是一個遞迴生成所有 VC++ 工作區的簡單生成腳本。它只有以下幾行:

原始碼打印?

加上更多的代碼,可以讓這個腳本 [Dawson02] 分析輸出結果,然後給團隊中的每個人發送一份結果報告郵件。不像某些其它腳本語言,上面代碼有很好的可讀性。使用 Python 來寫生成腳本和游戲腳本將會省卻很多學習的時間。

這個生成腳本示例也顯示了一些對 Python 新手很頭疼的問題。Python 的流程控制由縮進指明,而不使用 begin/end 宣告或大括號。

我用了很短的時間來適應這種規則,最後我發現這種規則很有效。我曾經不止一次討論過 C/C++ 中的大括號應該寫在哪裡,我想 Python 程式員有更高的工作效率,因為他們不用花費時間爭論 K&R; 及其它縮進風格[TR4: indenting style] 的事情。因為代碼塊由縮進定義,編寫時便不會出現任何不符合 Python 編譯器規則的縮進(因為那樣的話,程式就會出錯)。

要註意的是,當你混用 TAB 和空格進行縮進時,可能出現問題。大多數程式員使用寬度為 3 個或 4 個空格的 TAB 縮進,但是在 Python 編譯器內部卻使用 8 個空格的縮進,混合使用 TAB 和空格可能導致語法錯誤。如果你完全地使用空格或 TAB 進行縮進,並且使用一個能夠提示混用空格、TAB 縮進警告的 IDE,那麼便沒有什麼問題。

游戲腳本示例

下麵的示例是我們的第一個 Python/C++ 游戲中的一些 Python 代碼。這些代碼是 Python 正在執行的一個主迴圈,它呼叫了其它的模塊,這些模塊甚至可以用其它語言編寫:

原始碼打印?

因此,我們的游戲由 Python 啟動,併在需要時呼叫 C++ 程式。

它是如何工作的

Python 程式由模塊組成,當在一個源檔案中使用另一個源檔案中定義的函式時,需要匯入那個檔案。例如,gameai.py 有一個 UpdateAI 函式,那麼在其它 Python 源檔案中可以這樣呼叫它:

原始碼打印?

游戲程式員能夠想到的一個很棒的事情是,如果 UpdateAI() 跑起來很慢,那麼可以用 C++ 來重寫它。為了做到這點,在 gameai.py 中的函式和型別需要用 C++ 實現,並且在 Python 中註冊為原先的模塊名。之後,使用者能夠繼續匯入並使用 gameai 模塊,而不需要任何更改。

因此,Python 模塊能夠幫你簡單地用 Python 搭建你的整個游戲框架,而在適當的地方用 C++ 代碼實現。

粘合代碼 (Glue Code)

如果你自己手工編寫讓 C++ 代碼和 Python 協同工作的粘合代碼,那將是一件枯燥繁瑣的事情 [TR5: glue code]。一個能夠產生粘合代碼的系統框架是很重要的。

Swig, Boost, CXX 等 [Abrahams01] 能幫你產生代碼,更方便地將 Python 和 C++ 粘合起來。還有 Fubi[Bilas01],它是一個通用的框架,可以將 C++ 的函式和類映射到一種腳本語言中。

早期,大多數這些粘合代碼框架都依靠分析 C++ 頭檔案工作。因此,它們受到暴露的 C++ 頭檔案的限制,並且一些框架不支持從 C++ 類派生出 Python 類。後來,這些框架都有所改進,所以現在還是值得考慮的。

而我們決定做一個自己的方案,它可以根據類的 IDL 描述或匯出函式來生成粘合代碼。它的代碼叫做 Yaga,是一個遞迴命名法,表示 Yaga is A Game Architecture。

一個典型的 Yaga IDL 代碼如下:

它可以生成以下粘合代碼,還有其它一些代碼:

原始碼打印?

使用這個框架可以很簡單地匯出類和函式,從 C++ 類派生 Python 類,將 C++ 的陣列和 vector 映射為 Python 的序列型別,以及更多的事。

記憶體分配

Python 之中任何東西都是物件,物件被分配記憶體。因為所有的物件都有取用計數,所有你不用擔心釋放記憶體。但是,如果你是在編寫游戲,尤其是控制台游戲(譯註:指次時代及專用游戲機平臺游戲),你必需要明白這些記憶體從何處分配而來,以及分配過程會產生記憶體碎片的嚴重性。

為了控制這個性能問題,你需要隔離 Python,使其有自己的記憶體分配場。你需要重定向所有的記憶體分配操作到一個自定義的分配器上,它從一個固定大小的分配場中分配記憶體。只要你預留足夠大小的緩衝區,大於最大的 Python 歷史分配額度(原文:leave enough of a buffer above the maximum Python memory footprint),應該就能避免記憶體碎片問題。

另一個記憶體問題是沒有釋放的塊。這通常在 Python 中不是問題,因為每個物件都有取用計數,當變數離開作用域或者被顯式刪除,其取用計數就會減一,當計數為 0 時,物件就被釋放,物件生命結束。

試想這樣情況,一個被忘記的變數,它關聯了一串其它的物件,這時就會阻礙這些物件的釋放,所以你應該對清理物件保持警惕。然而,更糟糕的事情是迴圈取用問題,例如:物件 A 包含物件 B,但是物件 B 有一個回呼指標指向物件 A,那麼這兩個物件永遠都不會被刪除。Python 的開發者們意識到這個問題,在最近的 Python 版本中加入了一個垃圾收集器,它搜尋無法訪問到達的物件,並將其全部清除。

垃圾收集器對於游戲是很糟的,因為無法預知它們的運行時間,並且可能運行很長時間,使得畫面的幀率降低。因此,游戲程式中需要禁用垃圾收集器,這個做起來很簡單,隨後在每個游戲關卡後顯式地呼叫它。垃圾收集器同時也能告訴你 有多少無法訪問到達的物件仍然在分配中,這個可以幫助你跟蹤迴圈取用的情況,之後你可以手工地解決它們,這相當於 Python 的記憶體泄露檢查。

性能

如果你用 Python 做一些繁重的浮點計算工作,和 C++ 的性能相比會很讓人失望。Python 是一個慢語言,每個物件取用都意味著進行哈希表查詢,每個函式呼叫也一樣。這根本不能和 C++ 的性能相提並論,後者的變數位置和函式呼叫地址在編譯時就決定了。

但這並不意味著 Python 不適合做游戲編程,而是你需要在適當的地點用它。如果拿字串操作或 C++ STL 的 set 和 map 型別操作做對比,那麼 Python 代碼也許會做地更快。Python 的字串操作函式是用 C 寫的,並且 Python 的取用計數物件模型能夠避免一些 C++ string 類的字串複製過程。set 和 map 的大多數操作的複雜度是 O(log n),而對於 Python 的哈希表複雜度則是 O(1)。

你一定想,最好不要用 Python 寫 場景圖形遍歷 或 BSP 衝突檢測代碼。但是如果你用 C++ 寫它們,而後又匯出到 Python 中使用,那麼你就可以更快地編寫 AI 代碼。

請牢記 90/10 原則,這意味著對於 90% 的代碼,你不必過多操心它們的運行時性能,而代碼的明確表達力和編碼的效率才是關鍵。

控制台游戲

記憶體和性能問題在控制台游戲平臺上尤其重要。當不存在虛擬記憶體可以讓你漫不經心做記憶體分配的時候,保證在獨立的記憶體分配場中分配 Python 記憶體就顯得格外重要。同時,也要更明智地使用垃圾收集器 (as is using the garbage collector wisely)。

控制台平臺沒有鍵盤、滑鼠和多顯示器,所以在控制台平臺上運行 Python 除錯器用起來很不方便。遠程除錯是關鍵,它能讓你知道 Python 代碼的運行過程。很幸運,使用免費的 HapDebugger[Josephson02] 可以很容易建立遠程除錯環境。

Python 使用 C 編寫,並且已經被移植到多種編譯環境和平臺下,包括 PDA。因此,在某個控制台游戲平臺下 Python 可能已經有了很充分的發展。

Python 會花費掉一小部分和控制台游戲無關的記憶體,但是在新一代游戲平臺上可以不用擔心這個,它們最小都有 24M 記憶體。

法律問題

推向一種新的語言對於我們公司來說是個重大的決定,我覺得在進行之前,它定是受到了公司律師們的祝福。

律師懂得法律,但他們通常不太懂編程。大多數程式員在引入開原始碼前都不會咨詢公司的律師,當你確實問他們時,他們會認為你正在問一些奇怪且偏僻的事情。他們的立即反應是,認為那是有風險、沒有保證的計劃。

如果你和一個擅長知識產權的律師長談,他會一直向你灌輸“使用開源軟體會讓你焦頭爛額”的思想。有一些案例指明,在“免費發佈”的原始碼中包含專利或有版權的內容時,有嚴重的法律問題隱患。當你從商業軟體供應商那裡得到授權代碼時,他們會保護你免受法律責任,但對於開源軟體沒有人能給予授權許可 (with open source software there is no one to license it from)。

然而,開源社區對知識產權法律總是很警惕。例如 JPEG 已經從它們的開發庫中移除了 LZW 演算法代碼以避免專利問題 [IJG]。負責的程式員會關心授權許可問題,並且通常對 GPL 和 LPGL[FSF01] 以及他們的區別很熟悉。

將開原始碼引入商業產品存在很多風險。這些風險應嚴肅對待,但不應該阻止對開原始碼的使用。有很多開源的開發庫使用在游戲開發中,Python 實在沒什麼理由不被使用。

缺點

多語言開發增加了額外的複雜層次。同時除錯兩種語言的代碼很困難,而且必須花費時間維護系結兩種語言的粘合代碼。

類似 Python 的動態語言沒有編譯時型別檢查。這種情況初看讓人驚恐,但它的實際意味著,相比 C++ 你會遇到各式各樣不同的運行時錯誤,通常它們都很容易解決。

不同型別的換行符

UNIX (LF)、Mac OS (CR) 和 Windows (CR LF) 對待文本檔案中一行的結束有不同的約定,這實在很糟。

Windows 上的 C/C++ 庫(譯註:指 Windows API 和 VC 運行時庫)會做換行符轉換,所以 UNIX 檔案能夠在 Windows 上讀取,可以將 Windows 檔案像 UNIX 檔案一樣的操作。UNIX 和 Macintosh 文本檔案之間的共同點更少,只能依靠假定某個平臺上的檔案都只是這個平臺上曾經創建的,這個假設進行轉換。這個假設在當今的網絡環境下站不住腳,Python 也深受其害。直到現在,在 Windows 下寫的 Python 代碼可能無法在 Macintosh 下編譯,反之亦然。

這個問題的解決方法是,在運行 Python 代碼前,將 Python 源檔案通過一個檔案過濾器(可以用 Python 開發?)執行,另一種方法是以編譯後的位元組碼形式發佈 Python 代碼。但是,這兩種辦法都有缺點。最理想的是在計算機工業中標準化文本檔案格式,或者讓所有的檔案 IO 庫實現讀取任意型別文本檔案的能力。

這個問題在蘋果的 OS X 上更加有趣,換行符由運行程式的樣式而定,你可以運行 UNIX 或 Macintosh 兩種樣式程式。這會在一個系統下出現兩種不同的換行符,甚至不用重啟。

Python 的 Macintosh 版本最近修正了這個問題,在打開檔案時檢查換行符並對每個檔案進行調整。將所有的換行符都規定為 UNIX 型別是一種可行的方法,它在所有平臺下都能工作,但是還是要留心這個問題。

除錯器問題

很多 Python 程式員認為自動化測試和打印陳述句是他們唯一需要的除錯工具,而使用除錯器會影響編碼的產能。或許這對他們來說的確如此,但我已經習慣於進行原始碼級除錯,並且不會輕易放棄它。

PythonWin 是一個在 Windows 下的 Python 除錯器兼 IDE(奇特吧?)。它是免費的,有一些不錯的功能,但也有一些缺點,如:只能在 Windows 下運行,無法除錯有自身訊息迴圈的 Python 程式。

在 Humongous 娛樂公司,我們為 Macintosh 和 Windows 開發游戲,同時也涉及控制台游戲的開發。我們需要一種能工作在所有三個平臺上的除錯器,而最好的方案就是使用遠程除錯器。Python 的架構使得編寫它的除錯器很容易,再加上其它一些免費組件,我們開發出了自己的 Python 除錯器,我覺得它的效果比 PythonWin 好,並且具有遠程除錯功能。被除錯的客戶端需要運行一些額外代碼。除錯接口是 socket 上的 ASCII 文本,另外,我們還沒考慮將除錯器客戶端移植到更多其它平臺的問題。

因為我們希望集中精力開發游戲本身,而不是語言工具,所以決定再次借用開源的力量。我們在 Python 社區發佈了 HAP 除錯器 (Humongous Addition to Python),將其作為一個開源專案[Josephson02]。這是一個回饋社區的好機會,並且我們也從維護這個除錯工具的事務中解放出來。

我們還沒有解決的問題是除錯器的性能問題。大多數編譯式語言實現除錯斷點的方法是,將常規指令替換為導致 CPU 異常的指令,如 x86 處理器的 int 3 中斷。這讓程式可以全速執行,直到觸發中斷點。Python 不支持從異常處恢復執行,所以不能使用斷點異常的方法。Python 除錯器處理斷點的方法是 單步檢查代碼,即不停地在問自己“這一行有沒有斷點?”

這個性能影響的後果可能很嚴重。我們現在減小此影響的方法是,保證開發機器要比標的機器快得多。還有,將所有重量級計算用 C++ 擴展實現,這樣即使 Python 代碼拖慢了除錯器,也不至於讓整個游戲速度太慢。這是一個可以解決的問題,只是 Python 的主要開發者還沒考慮過。

代碼安全和游戲作弊

C++ 程式員有時開玩笑說,刪除註釋和縮短變數名可以優化代碼。然而,在 Python 中確實如此。

Python 代碼在運行時被編譯成位元組碼,並快取起來以備後續運行,所以刪除註釋的方法不會起到優化程式的效果,但是縮短變數名則是另外一回事。大多數腳本語言都是在運行時通過名字定位變數的,這也是腳本語言強大的原因之一,因為它可以突破很多由 C++ 編譯時系結造成的限制。然而,這也意味著變數名會一直伴隨著代碼而存在(譯註:C/C++ 等傳統編譯式語言則不同,經優化編譯後的 C/C++ 程式中沒有變數名而只有地址的概念)。

游戲程式中包含語意清晰 (scatological) 的變數名,會被人當做笑談。更嚴重的問題是,如果在多人游戲中使用 Python 腳本,作弊者反編譯 Python 程式後會得到完整的變數和函式名,這比起通過反編譯 C++ 程式來破解游戲要更簡單。

Python 的優點

Python 編程很有趣。Python 易於學習,有更高的生產效率,並且促使你使用另一種思維編程。學習 Python 編程讓我成為更好的 C++ 程式員。

快樂的程式員有更高的學習效率和生產效率,他們傾向創造更好的游戲。Humongous 公司中使用 Python 開發游戲的團隊,在整個公司中擁有最高的工作士氣。

Python 游戲編程系統(譯註:應指開發工具、框架、類庫等)具有很高的生產效率,而且它們仍然在發展之中。因為採用了它們,我們節省了很多資金。(原文:Productivity is higher with the Python game programming system, even though development is still being done on it. It is already clear that we will save a lot of money from this switch.)

用戶界面的開發,在 C++ 中可能花費較長的時間,而在 Python 中可以使用一些新意的方式進行實現。通常使用文本檔案定義 GUI 元素的位置和關聯圖形資源,進而定義選單。在 C++ 中會使用硬編碼的函式和控制元件物件,掛鉤 GUI 元素;而在 Python 中,可將函式及物件名放入文本檔案中,併在運行時掃描它們。Python 的動態和內省特性 (introspective) 使得做起這些事來很自然。(譯註:C++ 也可使用讀取文本配置方式,自動生成選單,只是用 Python 的反射特性做起來更自然)

很多起先我們擔憂的 Python 語言限制問題都已成為過去。Python 的開發者們對該語言進行持續地改進,有時他們就像一直在滿足我們對 Python 特性需求的渴望一樣。

游戲存檔和讀檔

C++ 程式員要花費很多時間解決腳本語言中不會出現的困難問題。例如,用 C++ 進行游戲狀態的儲存和讀取就是一個麻煩問題,經常要編寫大量的代碼。而且這種方法通常會導致,存檔只能和特定版本的游戲程式配合工作。而在 Python 中,使用 cPickle 模塊可以很方便的解決此問題,它可以儲存和讀取任何複雜的資料結構。

下麵例子中宣告了一個物件 mainObject,通常它是一個用戶自定義類物件,包含各種需要儲存的狀態的句柄,但為簡單起見,這裡只把它做成一個串列。最初該串列包含數字 0 和一個字串,然後將串列的第一個元素賦值為另外一個串列。這個過程可以繼續下去,讓 mainObject 包含任意複雜嵌套層次的物件,包括迴圈取用。

原始碼打印?

接下來儲存著這個 mainObject,這需要兩行代碼。一行匯入 cPickle 模塊,另一行打開一個檔案,將物件儲存為二進制格式。在開發時,儲存為文本格式很有用,只需省略掉 dump() 的最後一個引數即可。

原始碼打印?

然後是裝載檔案資料,這同樣需要兩行代碼。一行匯入 cPickle 模塊,另一行重建 mainObject 物件,以及包含的子物件、串列、成員變數等。第三行打印出 mainObject 物件,可以看出已經正確地恢復了嵌套的串列。

原始碼打印?

這個 Python 特性在 C++ 基本功能中不存在。

生成器:游戲 AI 的微執行緒

微執行緒將物件狀態信息放到區域性變數中(這是恰當的位置),從而極大簡化 AI 和物件更新代碼 [Carter01]。可以使用彙編語言的技巧將微執行緒放進 C++ 中,但是那樣很凌亂。在最近版本的 Python 中,微執行緒內建於語言之中。現在使用微執行緒會工作地很好。

在 Python 中它們叫做生成器 (generator),使用它們編寫函式,函式產生某個結果後,控制傳回到主程式。主程式稍後可以重新喚醒它們,並從中斷處繼續運行,並保持原來的區域性變數值。下麵的示例代碼展示創建一個物件,並移動它們穿過屏幕。這個簡單例子並不能從微執行緒/生成器中得到實際的好處,它只是基本展示它們怎樣用來簡化 AI 和物件更新代碼。

原始碼打印?

即使你不使用生成器,在 Python 中實現 AI 更新方法也比用 C++ 更乾凈。因為如果你的某部分 AI 代碼需要一些額外的臨時狀態時,Python 可以將它加入到物件中,然後在不需要時刪除它。而 C++ 因其靜態特點,不能在運行時加入新的成員變數,這使你的物件在任何時候都必須包含所需的所有狀態。

開始使用 Python

如果你開始使用 Python,第一件事是訪問 Python 的官方網站 http://www.python.org/ 下載你的平臺上的 Python 版本。

Python 文件在 http://www.python.org/doc/current/download.html,也有編譯的 HTML 版本 (CHM) 更便於檢索。

Windows 開發者可以使用 PythonWin 和各種 Win32 擴展http://users.bigpond.net.au/mhammond/win32all-142.exe

除錯器 HapDebugger https://sourceforge.net/projects/hapdebugger/

你可以下載並編譯 Python 原始碼,構建自己的 Debug 和 Release 版 Python。Python 2.2 原始碼下載ftp://ftp.python.org/pub/python/2.2/Python-2.2.tgz

最後,你可以閱讀關於手工創建 Python 擴展的細節http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66509,然後選擇一種粘合代碼包來幫你做這些事情,參考http://www.boost.org/libs/python/doc/comparisons.html

參考

  • [Stroustrup94] Stroustrup, Bjarne “The Design and Evolution of C++”, Addison Wesley, 115
  • [Lua01] “The Programming Language Lua”
  • http://www.lua.org/
  • [Python02] Python Language Website
  • http://www.python.org/
  • [Tismer01] Tismer, Christian “Stackless Python”
  • http://www.stackless.com/
  • [Dawson02] Dawson, Bruce “Python Scripts”
  • ftp://ftp.cygnus-software.com/pub/pythonscripts.zip
  • [Abrahams01] Abrahams, David, “Comparisons with Other Systems”
  • http://www.boost.org/libs/python/doc/comparisons.html
  • [Bilas01] Bilas, Scott, “FuBi: Automatic Function Exporting for Scripting and Networking”
  • http://www.gdconf.com/archives/proceedings/2001/bilas.doc
  • [IJG] http://www.ijg.org/ – docsREADME in the source distribution
  • [FSF01] “What is Copyleft?”
  • http://www.gnu.org/copyleft/
  • [Josephson02] Josephson, Neal “HAP Python Remote Debugger”
  • http://sourceforge.net/projects/hapdebugger/
  • [Carter01] Carter, Simon “Managing AI with Micro-Threads”, Game Programming Gems II, Charles River Media, 265-272

 

    赞(0)

    分享創造快樂