跳到主要內容

發表文章

使用source control system的壞習慣

很多人都有使用 source control system(SCM) 的好習慣,不過我也發現到有些人在使用SCM時的壞習慣,以致於把使用SCM的好處給抵消掉不少,有時候甚至還得到反效果。其實我自己在初期剛使用SCM時,也是犯了同樣的壞習慣,一直到後來才意識到。因為這個壞習慣是那麼的不明顯,以致於大多數人都很自然而然的犯而不自知。 這個壞習慣是什麼呢? 那就是把SCM當作是純粹的source code database來使用。為什麼我會說這是一個壞習慣(或錯誤)?雖然說source code database原本也是SCM的功能之一,但我認為並不是最重要的功能,最重要的功能應該是在control這個字的功能上面才對。SCM讓我們對source所作的修改、內容增減作記錄,每一筆記錄就是一個版本,每一個版本的所有變動都匯入到database裡。我們可以透過SCM client介面對這些版本作檢視,隨時可以更新到任意版本,隨時復原所作的變動回到指定版本。 在軟體開發過程中,有一大半都是在對原有的程式作修改,尤其是在大型的系統來說,有更多的小修改、錯誤修正等等。想想看,假如某一個版本的修改(bugfix或功能增減)僅在一個版本裡面就包含了十項、數十項或甚至數百項或更多的修改會是什麼樣的情況? 當開發的軟體一切都正常的時候,把SCM當作source備份的database沒什麼問題,事實上也很合適。但是軟體的開發並不那麼簡單順利,尤其是大型系統的開發過程中,絕對會產生大大小小的bug。這些bug有時候很容易就可以解決修正,在一些複雜系統裡面,有些bug需要利用復原回朔(revert)的功能,將修改的內容還原到舊版本,一個一個版本往上回朔檢查問題是從那一個版本開始發生的。利用這個雖然辛苦但有效的土方法來找到問題發生點的版本,再去比對所作的修改是那裡產生的問題再去修正。 想想看當你用回朔法找到你想要解決的問題發生的某個版本,而在這個版本裡面有一堆的修改,裡面混雜了多個bug修正、功能增減等等會是什麼樣的情況?這一定會增加debug的難度。如果在這個版本裡面只包含對一件事情的修改,無論是bugfix或是功能增減,要回朔到上一個版本一定是件相對容易多的事情。一個版本只作一件事情,同時對於review也會是一件單純的事情。 所以對於SCM的使用,我永遠都秉持底下幾個...

Android遊戲5連發的一些記錄

這二個月裡面很密集的連發了5款android小遊戲,雖然這些遊戲主要都是移植或改版的作品,但在作移植或改版的過程還是學到了一些東西,並且最重要的是又對good作了點改良,雖然都是小改進但也是小進步,只要持續的作,這些小改進累積起來也是很可觀的 !這篇文章主要目的是在作這幾個遊戲的過程中,把那些值得記錄的事寫出來。 1, 跳跳伯尼熊 UpUp! 某一天終於心血來潮,很想要把什麼遊戲放上google play。這個遊戲是很早之前就完成的,因為也都是用GL成像的,程式也不大所以就挑了它開工。 移植UpUp第一個版本到android手機上很快,大概只花了不到二個小時,因為在那之前我就已經 移植過good ,直接套用相關的經驗很快就可以在手機上執行UpUp。完成第一步的任務後,接下來就要改版了。原來的設計是單機的,有個單人排行榜,現在要改版成有個多人排行榜。為了作到這件事,有好幾件事需要完成。 首先需要有個排行榜的server,這個功能我用php+mysql作了一個很陽春的server,透過http 和json作溝通。 玩家在排行榜上的名字要怎麼來?原來的版本是在gameover,成績有上排行榜時,讓user輸入,不過因為我只用了英數符圖的字圖,所以最後改成抓google account,然後再一開始用toast顯示。 AccountManager accountManager = AccountManager.get(this); Account[] accounts = accountManager.getAccountsByType("com.google"); String name = accounts[0].name; myName = name.substring(0, name.indexOf("@")); Toast.makeText(getBaseContext(), "hello " + myName, Toast.LENGTH_SHORT).show(); 再來就是聲音的處理。將相關的資源檔放在res/raw目錄下,再透過MediaPlayer.create(this, idRes);作到播放聲音的功能。 2, 報數快手123   ( src ) ...

Good Game Editor 1.4 Release

* 粒子程式編輯器(STGE Script Editor)編譯程式前提示存檔。 * 動作編輯器(Sprite Editor)選取項目使用紅色框。 * 新增Resource.GetMapTileSize。 * 新增範例snake(貪食蛇)。 * 新增範例solar(物件階層)。 * 取消TGA圖形格式支援。 * 最佳化繪圖程序。 * 修正Good.Clone的錯誤。 * 動作編輯器(Sprite Editor)改版,整合Preview視窗至編輯區。 * 修正Good.CallPackage機制堆疊錯誤。 * 更名Resource.GetMapTileSize為Resource.GetTileSize。 * 更名Resource.GetTextureId為Resource.GetTexId。 * 更名Resource.GetTextureSize為Resource.GetTexSize。 * 更名Resource.GetTileMapSize為Resource.GetMapSize。 * 更名Sound.ReleaseSound為Sound.KillSound。 * 線上API參考手冊改連至 WIKI 。 * 關卡編輯器(Level Editor)新增自訂貼齊格線大小。 * 修正當Tile寬高不同時顯示地圖物件的錯誤。 * 修正Resource.GetNextLevelId錯誤。 * 新增範例link(連連看)。 * 自動儲存及載入視窗屬性。 * 編輯器內建的播放器支援即時顯示除錯訊息。 * 修正開啟另一個專案時程式崩塌的錯誤。 * 修正Good.PickObj無法Pick子物件的錯誤。 * 移除Good.PickColorBgObj/PickMapObj/PickSpriteObj/PickTexBgObj。 * 新增Good.PauseAnim。 * 新增Good.AddChild index參數,允許指定位置加入父物件。 * 所有類型的物件都可在關卡編輯器(Level Editor)中指定顏色。 * 新增Good.IsAnimPlaying。 * 新增開新專案對話盒(New Project Dialog)。 * 編輯器不支援縮放。 * 新增範例numbers。 * 新增關卡編輯器貼圖物...

Reduce C++ code size

如果拿程式執行速度和code size二者來比的話,我個人會先偏好較小的code size,而不會特別先去關注較快的執行速度,除非效能問題是個問題。很多時候,較小的code size,也意謂著較快的速度。C++程式最讓人經常誤解的一點是,會產生較大的code size,較慢的執行速度是另一個常見的迷思。不過事實上,在使用STL之類的template library或template class時,的確使用不當的話是特別容易產生較大的code size。下面提供幾個簡單的要點,可以幫忙稍減code size。 使用compiler的最佳化選項。一般分為針對執行速度最佳化或code size最佳化。以Visual Studio為例,/O1是minimize size對code size最佳化,/O2是maximize speed對執行速度作最佳化。 避免重複。把common code抽出來,作成function,library或之類的東西。減少source size也減少code size,也減少bug發生的可能性。 砍掉沒用的code。整支程式裡面若是包含了大量的無用程式,除了增加code size外,也可能會隱藏潛在的bug。花點時間,整理一個你的程式把無用的程式碼,短期內或可見的未來內用不到的程式碼清一清。不要過早加入用不到的功能,減少code size也減少bug。 不要include <iostream> ,假如你沒有用使用cin/cout/cerr/clog之類的內建物件。用include < iosfwd> 來取代 ,避免包含使用不到的物件來減少code size。 避免類似型別參數的template類。例如:vector<int> ,vector <unsigned int> 等,這些類別的參數可以替換成同一種型別,例如vector<unsigned int> 。使用同一類別的template容器,也能減少code size。 減少使用exception及RTTI。沒必要的話,減少使用exception及RTTI也能減少code size。 以上是幾個大方向上,如何減少code size的要點。當然還有一些手法,但都是較細節的小技巧,不一定有什麼幫助。就好像在作最佳...

HTML5 互動式象棋譜

十多年前在舊書攤上挖到寶,發現一本曾經在某處讀到得到高度評價的棋譜”佈局津梁”,雖然只有下集,立刻把它買下來,印象中花了100塊左右,現在倒是漲了不少,可惜的是一直找不到上集...不過和許多買過的書的下場同樣,後來大多變成收藏用,只有有時候心血來潮會把它拿出來翻看。因為這本書的年紀比我大,怕把它給翻壞了,事實上封面皮都快掉了,好像隨時都要碎掉的感覺,所以後來花了不少時間將內容手工輸入電腦建檔。最近因為玩些HTML5的東西,所以順便就把它作成網頁版本,實作一個簡易版的互動式棋盤幫助看譜,順便當作練習題。程式很簡單,倒是花了非常大量的時間在校對棋譜內容改正原書的錯誤,不過因為個人能力有限還是有許多錯誤還沒更正... 這個程式主要在Chrome及Firefox測過,手機版viewport寬限定為320。 ( 玩玩看 ) 整個程式很簡單,因為棋譜格式是制式的,所以只需要利用幾個簡單的re的幫忙,很簡單的可以用來找出那一段是文字那一段是棋譜,然後再parse出棋譜內容走步。基本上棋譜還是以字串方式作處理,只要棋譜格式及內容沒有錯誤,都能正確演示。有任何顯示錯誤,則表示棋譜格式或內容有誤,因為我並沒有多作錯誤的檢查。 實際實作時在Chrome及Firefox有二個地方需要特別注意。 Firefox不支援innerText的用法,需改用textContent。實作上可以簡單以a = p.innerText || p.textContent解決。 Firefox不支援mouse event的offsetX/offsetY,我們可以另外包裝一個getOffset的函式解決: function getOffset(e) { if (e.offsetX) { return {x:e.offsetX, y:e.offsetY}; } var el = e.target; var offset = {x:0, y:0}; while (el.offsetParent) { offset.x += el.offsetLeft; offset.y += el.offsetTop; el = el.offsetParent; } offset.x = e.pageX - offset.x; offs...

HTML5 WebSocket 多人連線麻將

之前以java實作了 多人連線的麻將 Client及Server,現在加上使用HTML5 WebSocket的client端,經最新版的FireFox及Chrome測試。這同樣只是一個Demo,由簡單AI打麻將。現在二種不同平台不同網路協定的Client,可以連線對打麻將了。 ; 底下對於WebSocket的Server及Client實作作一個重點摘要。 1,依據 RFC6455 完成WebSocket的Handshake,網路上有很多資料細節這裡就不多作說明。需要注意的是,對於"Connection: "這條內容,Client送給Server什麼,Server就需要回同樣的東西給Client。例如:Chrome送給Server的是" Connection: Upgrade", 而Firefox送給Server的是" Connection: keep-alive, Upgrade"。Server端對Handshake的回應也是以HTTP response形式,之後就可作一般的socket讀寫。 2,Server端的讀寫,需要特別注意的是Payload len的處理:如果小於等於125,那就是原始資料長度;如果等於126,則實際資料長度為接下來的二個byte指定的16bits數字;如果等於127,則實際資料長度為接下來的八個byte指定64bits數字。 3,Client端的onmessage事件中,如果處理的資料是binary,需對傳入的物件作型別檢查。 ws.onmessage = function (evt) {   if (evt.data instanceof ArrayBuffer) {   } else if (evt.data instanceof Blob) {   } else if (typeof evt.data === "string") {   } else {   } }

Good Player移植到Android平台

花了三天終於把Good Player移植到Android平台了... 為什麼拖了那麼久才作這件事呢? 真是一言難盡... 下面稍微講一下移植的主要過程和重點。 * 下載adt-bundle-windows-x86-20140321及android-ndk-r9d,免安裝解壓縮即可。 在這之前,我拿 野火機 的時代也曾經裝過Android SDK,不過那時只compile了hello程式就沒下文了,因為我的野火機實在太慢,讓我興致全無就沒有繼續下去。後來最近改拿 A6S 才又臨時起意,再把eclipse打開試試,結果又發現連不到我的手機。改安裝以上版本SDK,果然和版本有關可以連了,不過還是又拖到這幾天才真正開工。 *  編譯測試NDK sample: hello-gl2。 先確認可以編譯出來,並在A6S上跑。這點很重要,找一個可以編譯並執行的範例,這個範例可以demo我需要的功能,這樣我就能以這個範例為基礎開始工作。 * 參考hello-gl2範例,新建一個proj。 * 編譯需要的lib。 good主要使用到幾個lib,zlib, lua, libpng, libjpeg, smallworld2 。SDK裡面已經有zlib了,所以直接使用。編譯lua5.1.4時遇到compile error,這是因為locale.h支援不足問題,很容易解決。libpng及libjpeg都沒遇到問題,smallworld2是自己的lib也很順利。最後加上good的code,也都OK編譯過了。非常好,一切順利! * 把畫面顯示出來。 hello-gl2的畫面是個三角形,現在把它換成good的畫面。要顯示good的畫面很簡單,我只在JNILib_step把原來的renderFrame換成good的render就行了,不過一開始沒有顯示東西。搞了老半天,原來我每次改的東西需要在eclipse裡面第二次執行的時候才會update到手機上。但因為我只執行一次,所以看到的是舊的程式,而我又以為有問題所以又再修修程式重新執行,所以一直看不到新改程式的結果,工具不熟這個問題就讓我搞了不少時間... 加上版本設定之類的問題,最後終於讓我看到我畫的一個紅色方塊。可以看到紅色方塊方塊後,表示good可以畫出東西了,現在可以換成測試用的good p...