2009年12月31日 星期四

Pacess 的科學構想(二):時空穿梭機

一直以來都有很多人爭議的時空穿梭問題,在我的判斷來說是沒有可能發生。但不可能發生的只是讓人回到當下的真實時空;假若是虛擬的就沒有問題。由於電腦的運算速度越來越快,有日便能計算(Render)指定時間指定地點的環境出來,到時加上 Virtual Reality 技術,便能使人回到過去及未來。可能有人會發現當中有一個矛盾,就是電腦運算中無法連電腦自己也包括在內,至少不能超越自己。所以,運算的方式是宏觀的,就像中國博大精深的術數一樣,計算出一個範疇之後,再以旁枝推敲,以求出答案。

2009年12月30日 星期三

EXC_BAD_ACCESS - NSZombie

又學到新技巧了!今天遇到關於記憶體的問題,遊戲在載入地圖時,差不多有 70% 會死機。在 Debug 模式下找不到問題所在,當中的物件 pointer 沒有異樣。於是我打開了 Guard Malloc 來檢測 Memory out of bound 的情況,結果亦沒有這些錯誤發生!在毫無頭緒之下,我唯有上網搜索有用的技巧,竟給我發現了 Zombi 方法,親身試過十分好用,能加快找到錯誤的成因。

在 XCode 左邊欄位 Groups & Files 下有個 Executables 分類,入面放著現時 Project 的名稱,點擊滑鼠右鍵並選擇 Get Info。在彈出視窗中選 Arguments 後,再在 Variables to be set in environment 下方點擊「+」。名稱輸入 NSZombieEnabled,數值輸入 YES,還要記得打前方的勾。這樣就行了!

每當有物件建立時,Zombie 都會自動建立,而遇上物件 Release 過龍時,便會觸及 Zombie 及發生中斷。透過 Log、停頓的位置及 Call Stack 便能進一步了解發生錯誤的原因。

2009年12月29日 星期二

在 OpenGL ES 下生成貼圖的發現

今日在移植的工作上又有新發現!按照元祖版本的設計,系統會建立一條新的綫程把圖檔載入,以減輕對遊戲在運行速度上的拖延。我在移植的過程中會盡量保留原先的設計,以方便日後兩個版本一併升級及除錯。可是問題來了!iPhone 版本在使用 OpenGL 的環境下,把圖檔讀進成為圖像的過程中是需要 glBindTexture;而在這個動作的之前及之後,也需要做一些設置上的處理。由於綫程只負責把圖檔載入,所以根本不會做以上的設置,導致所載入的圖案都變成全白。起初我還以為是流程上或數據上發生錯誤所導致,結果花了兩個多小時的追蹤也找不到原因;後來換個思考角度,再透過小實驗才找出問題是緣於 OpenGL 設置。

這樣說,綫程豈不是失去其意義?要解決問題豈不是要作出重大改動?正如先前所說,為了方便升級及除錯,我只好把綫程斷開,但維持綫程內的架構,並把綫程原有的工作進入點置入主流程之內。結果問題得以順利解決。

2009年12月28日 星期一

Pacess 的科學構想(一):元素分解及合成裝置

自小我已經渴望成為一個發明家。當時普遍人應為發明家等如科學家;但在我的腦海裡,發明家是較科學家高級很多。科學家只是有科學知識的人;而發明家不單止要有科學知識,更重要的是要有創意及毅力。

回顧我在少年時代(12-23)已經有很多科學方面的構想,可惜時值讀書時間,也沒有金錢發知識把構想變成現實。在眾多的構想中,很一些已經被其他人成功開發;有一些則在開發中;還有一些是未被開發。能想出如此多的構想,主要是從生活觀察中得來;還有的就可能是當時我在行用神大運,才有這股創意;現在的我已經無法想得到了。

其中一個構想是「元素分解及合成裝置」。它的設計就像一個小型房間,在運作時能發出電光射向房中心的物件,並使它分解成元素。在分解的同時會把所有元素的位置記錄。元素還會分類儲存在容器內,就像打印機的墨匣一樣。炭元素容器、氧元素容器、氫元素容器...等。

同時間,這台裝置亦能透過容器內的元素,加上元素位置記錄,把物體還原。相像一下這台機器還有甚麼用?若果把機器設在中國及美國,配合足夠的元素匣及通訊裝置,便能實電瞬間轉移了!當然也能實現複製物件!而且也很環保呢!

2009年12月27日 星期日

RPG 開發回顧

充實的時間是過得特別快!轉眼已經回歸 GameisLive 三個月!原本預計三個月便能完成的移植工作,到現時為止卻只有 40% 左右的完成度,真是超出估計很多。在這三個月裡,平均每天都加班 1.5 小時,理應不致落後太多。

若要總結當下經驗的話,我認為自己的 iPhone 開發知識不足;先是使用 UIView 來製作,導致後來繒畫速度上出現瓶頸,因而要花時間學習並改用 OpenGL ES。不過只花數天便完成改動,我是十分滿意。

第二是低估了遊戲的複雜程度。基本上,這個手機上的 MMORPG 遊戲的規模是很大,比我在 U1 時的《小鬥士大冒險》的規模還要大,真的不能因為手機遊戲而低估。下次還是使用網友 Tony 的建議,用源碼總行數來估計移植所需要的時間。

第三是原編程人員寫 Code 的方式很隨意,一不小心便能鑄成大錯,更有很多隱藏的陷阱。我一直都嘗試理解原編程人員的思考方式,可惜我那根深蒂固的寫作及思考方式完全是一個障礙;很多時候都需要遂行追蹤才能理解程序在做甚麼,往往花費很多時間。

現在,較大的部份已差不多完成,連線也沒有問題,之後便是主力做介面及戰鬥系統;再加上有新同事幫忙,相信能加快開發進程,在農曆新年前完成封測版本。順帶一提,我的所屬公司正聘請兩位 iPhone 編程人員,有興趣的網友可把履歷電郵到 hrcn@gameislive.com。無 iPhone 開發經驗者優先考慮!

2009年12月26日 星期六

讀取 Info.plist 中的數據

有些時候,我們會把一些資料數據放到 Info.plist 中。要讀取的話,可使用以下語法:
NSString *myName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"My name"];

2009年12月24日 星期四

2009年12月18日 星期五

Apple Magic Mouse

上星期訂購的 Apple Magic Mouse 終於都到了!加上上星期的 Apple Wireless Keyboard,我可以在這天寒地凍的天氣下,竄入被窩中繼續玩電腦!Yeah!

2009年12月12日 星期六

Renew iPhone Developer Program

今日收到 Apple 的來信,邀請繼續參加 iPhone Developer Program。正如我的估計一樣,要是合約期滿,我在 AppStore 的所有作品都會自動下架。這對於我來說未嘗是一件好事。由於現時的工作都是開發 iPhone 軟件,在事件上有所抵觸;二來是我在美國及歐洲以外地區的收入,可以來一個了結,反正現時我不可以推出新作品,這些地方的收入都很難滿足 US$150 的要求。不過,距離我的合約到期日(情人節)還有一段時間,可以仔細考慮一下。

2009年12月11日 星期五

iPhone 個人化撥號 Icon

在我的電話通話次數入面,有 90% 都是打給我的太太,為了方便起見,我特別做了一個「速撥 Icon」,只要輕鬆一按,便會立即至電我的太太,十分方便。這個功能十分好用,可惜只能適用於 JailBreak 手機。

不過,我學習了一個方法,可以不需要經過 Apple 的審批,而用正途安裝到 iPhone 上面。

i-KeyHole TV

今日從朋友的 Facebook 得知有個名為「i-KeyHole TV」的 iPhone 軟件,可以即時收看來自日本地區的電視節目,我當然第一時間搜尋這個軟件!測試過這個軟件,雖然流暢度不高,但能在街上隨時收看日本電視節目,都咪話唔爽!

這個軟件沒有在 AppStore 發售,因此,只有 JailBreak 的裝置才能享受箇中樂趣。真不禁要喊一句:「JailBreak unleashed the POWER!」

2009年12月10日 星期四

自家 App 製成 IPA 方法(二)

之前介紹過的方法只能利用 Installous 安裝,程序比較複雜;今次要講介的則方便得多,只需要用 iTunes 同步便可。


01)建立 IPA 資料夾

02)在 IPA 資料夾內建立 Payload 資料夾

03)把編譯好的 .app 拷到 Payload 內

04)利用 BBEdit 打開 .app 資料夾內的 info.plist 檔

05)在 </dict> 之前加入以下句子並儲存:

    <key>SignerIdentity</key>

    <string>Apple iPhone OS Application Signing</string>

06)把本來要上傳到 iTunes Connect 的 512x512 JPG 放到 IPA 資料夾

07)把 JPG 檔改名為 iTunesArtwork

08)把 Payload 及 iTunesArtwork 壓縮成 ZIP 檔

09)把 Payload.zip 改名為 Cracked.ipa

10)把 Cracked.ipa 拖拉到 iTunes 的 Applications 內

11)同步!

2009年11月27日 星期五

OpenGL 下的「退地」方案

經過幾天的吸星大法,東抄抄西抄抄,我已經成功在 OpenGL ES 秀出平面圖,並建立好自己的繪圖引擎。由於 OpenGL 沒有繪畫文字的功能,又不能使用 UILabel,唯有將文字變成貼圖秀出。由於文字多為單色,所以用 8 Bits 灰階就夠,再加上 Blending 便能轉為其他顔色!OpenGL 在我的 iPhone Orginal 上也跑得十分之快,真是簡單好用!

2009年11月26日 星期四

取得 iPhone OS 版本的方法

NSLog(@"Current system version = %@", [[UIDevice currentDevice] systemVersion]);

2009年11月25日 星期三

Quartz vs OpenGL

在開始製作移植 RPG 遊戲到 iPhone 之前,我曾經在網上尋求 Quartz 及 OpenGL 在 2D 效能上,及學習上哪個比較合適的答案。籍以決定 RPG 項目使用哪個技術。得到的結果是,網友大多宣稱在 2D 繪畫速度上 Quartz 跟 OpenGL 是差不多。亦由於我比較熟悉 Quartz 技術,因此決定做用這套技術。

除著開發的時間增加,繪圖的數目也提升了不少,一個畫面大約需要繪畫 400 幅 24x24 大小的圖片,當中包括透底處理、旋轉發倒轉處理。導致 Quartz 出現速度上的瓶頸。經過優化之後,在 iPhone Original 上繪畫的所需時間需要 0.4 秒左右,亦即是說一秒最多只有三幀;實在是不能接受的龜速。

於是我在 OpenGL 上做了一個測試,在 iPhone Original 上繪畫 400 幅 24x24 像素及帶有透明色的圖片,當中沒有做任個旋轉處理。出來的結果是平均時間 0.0160 秒,亦即是說大約為 62 fps。相信以這個速度,在加入遊戲邏輯、旋轉、網路通訊等處理後,保持 20 fps 是沒有問題。

由見及此,要製作繪畫次數不多的應用程式時,Quartz 是比教簡單易學、是比較好的選擇。但要很作較為大型及繪畫次數較多的應用程式時,Quartz 就不能勝任,反而 OpenGL 才是首選。

2009年11月24日 星期二

取得 iPhone Serial No. 的方法

NSLog(@"Serial: %@", [[UIDevice currentDevice] uniqueIdentifier]);

2009年11月20日 星期五

自家 App 製成 IPA 方法

更新:這個方法只適用於使用 Installous 安裝,利用 iTunes 安裝的打包方法,請參考本人較新的文章。

自從 Apple 把 Provisioning Profile 的期限改為三個月之後,久不久我便需要將 AppSales Mobile 的 Provisioning Profile 更新。於是我創作出解決方法,把 AppSales Mobile 變成自家製 IPA 檔案。方法如下:

1)建立 Payload 資料夾
2)把編譯好的 AppSales .app 拷到 Payload 內
3)把 Payload 壓縮成 ZIP 檔
4)把 Payload.zip 改名為 AppSales.ipa
5)把 AppSales.ipa 拷到 iPhone 裡的 /private/var/mobile/Library/Downloads
6)運行 Installous 安裝 AppSales.ipa

2009年11月19日 星期四

AppSales Mobile for 3.0

由昨天起,AppSales Mobile 不能從 iTunes Connect 下載銷售情報,是因為 iTunes Connect 的頁面更改了。要解決這個問題,可以到 http://github.com/omz/AppSales-Mobile 下載更新版 AppSales。這個版本在 3.0 能正常運作。

2009年11月10日 星期二

優化 Sprite 部份

今天嘗試把繪畫 Sprite 的部份優化,把重覆的部份移走,可惜失敗了。

把以下代碼:
spriteLayerData = malloc(SCREEN_WIDTH*SCREEN_HEIGHT*4);

colorSpace = CGColorSpaceCreateDeviceRGB();
spriteLayerContext = CGBitmapContextCreate(spriteLayerData, SCREEN_WIDTH, SCREEN_HEIGHT, 8, (SCREEN_WIDTH<<2), colorSpace, kCGImageAlphaPremultipliedFirst);
myRef = CGBitmapContextCreateImage(spriteLayerContext);

// Draw sprite to context
// ....
// ....

outputImage = [UIImage imageWithCGImage:myRef];
spriteLayer = [[UIImageView alloc] initWithImage:outputImage];
[self.view addSubview:spriteLayer];

CGImageRelease(myRef);
CGContextRelease(spriteLayerContext);
CGColorSpaceRelease(colorSpace);

換成:
spriteLayerData = malloc(SCREEN_WIDTH*SCREEN_HEIGHT*4);

colorSpace = CGColorSpaceCreateDeviceRGB();
spriteLayerContext = CGBitmapContextCreate(spriteLayerData, SCREEN_WIDTH, SCREEN_HEIGHT, 8, (SCREEN_WIDTH<<2), colorSpace, kCGImageAlphaPremultipliedFirst);
myRef = CGBitmapContextCreateImage(spriteLayerContext);

outputImage = [UIImage imageWithCGImage:myRef];
spriteLayer = [[UIImageView alloc] initWithImage:outputImage];
[self.view addSubview:spriteLayer];
memset(spriteLayerData, 0, (SCREEN_WIDTH*SCREEN_HEIGHT*4));

// Draw sprite to context
// ....
// ....
CGImageRelease(myRef);
CGContextRelease(spriteLayerContext);
CGColorSpaceRelease(colorSpace);

2009年11月6日 星期五

一個挑戰!

最近在處理圖片時出現了一個頗為嚴重的瓶頸。由於一個角色是由多個部份的圖片合成出來,在實時繪畫上,少不免會花上一點時間;而在我的 iPhone 2G 實機上測試出來的結果,才是令我頭痛的主要原因:

以下的結果是以「秒」為單位:
測試一:
》一張全畫面的 UIImageView 背景圖
》一張 UIImageView 標誌圖
》一個 UILabel 文字
所需時間:0.0003~0.0005 秒

測試二:
》一張全畫面的 UIImageView 背景圖
》一張 UIImageView 標誌圖
》一個 UILabel 文字
》建立一個及取消一個 Device Context(每幀)
所需時間:0.0016~0.0037 秒

測試三:
》一張全畫面的 UIImageView 背景圖
》一張 UIImageView 標誌圖
》一個 UILabel 文字
》建立一個及取消一個 Device Context(每幀)
》在 Device Context 上繪製圖片(每幀)
所需時間:0.7060~1.0885 秒

足足需要接近一秒的時間才完成!是一個極低的 Frame Rate。下一步要解決的是把這個部份加快至少 30 倍,確實是一個挑戰!

2009年11月3日 星期二

@selector in NSArray

除了之前學習到的 Class in NSArray 外,今日嘗試製作 Selector in NSArray。方法同樣很簡單:

- (void)runAllTest:(id)sender {
NSArray *menuList = [[NSArray alloc] initWithObjects:
@"test01:",
@"test02:",
@"test03:",
@"test04:",
nil];

NSString *currentTestName = [menuList objectAtIndex:currentTest];
[self addLog:[NSString stringWithFormat:@"[%@]...", currentTestName]];

// Get the selector of next test
SEL currentSelector = NSSelectorFromString(currentTestName);
int assertResult = (int)[self performSelector:currentSelector];

if (assertResult == 0) {[self addLog:@"OK\n"];}
else {[self addLog:[NSString stringWithFormat:@"ERROR %d\n", assertResult]];}

// Test complete
currentTest++;

// Stop if all tests have been ran
if (currentTest >= [menuList count]) {
[self stopTest:sender];
currentTest = 0;
return;
}

// Set timer for next test
timer = [NSTimer scheduledTimerWithTimeInterval:(0.5f) target:self selector:@selector(runAllTest:) userInfo:nil repeats:NO];
}

2009年11月1日 星期日

2009年10月31日 星期六

2009年10月30日 星期五

2009年10月29日 星期四

Leopard 捷徑

要在 Leopard 建立捷徑,只要在圖示上按右鍵,再選擇 Alias 即可。

2009年10月22日 星期四

XCode 小秘技(三)

在 XCode 裡有一個名叫 Guard Malloc 的功能。它主要在程序運行時,檢查有沒有使用到非法的記憶體空間。經過試驗之後,發覺非常好用;唯一的問題是執行效率下降了不少,使得整個過程都慢起來。所以,我只會在有需要時才打開它。

2009年10月20日 星期二

XCode 小秘技(二)

一直以來,我都有把 iPhone 專案內使用到的檔案以 Group 的方式分門別類;主要是方便管理及使用。但在編譯成為 IPA 後,原本按 Group 整整齊齊分類的檔案都會變得散亂地放在 IPA 內應用程式的根目錄。我一直都想解決這個問題!

現在由我開發的角色扮演遊戲,已經包含上 2500 張圖片及資料檔案,更需要清清楚楚地分門別類。我嘗試了很多次都無法成功,也找不到類似的功能;最後發現,原來先在 Finder 建立起資料夾,把相應的檔案放進去,並把資料夾拖拉到 XCode 左方檔案清單的 Resources 內;這時會有一個視窗彈出,選擇 Create Folder References for any added folders 即可。而該資料夾的圖示亦會由正常 Group 分類的黃色,變成藍色。這樣編譯出來的 IPA 便會出現該資料夾及檔案。

2009年10月19日 星期一

XCode 小秘技

在開發大型軟件時,為了在最快的時間內創造出一點成果,很多時都會先建立程序框架及其部份內容;而較為複雜細微的部份會在較後的時間去實現。我習慣在相關部份加入 TODO: 註解。在 IDE 的上方會有一個快速函數跳轉功能,原來 XCode 對於「TODO:」會有特別處理。在這個快速函數跳轉功能內也會顯示「TODO:」的內容,而且還以粗體顯示,十分方便。

2009年10月16日 星期五

替 Function 換名

對於日漸壯大的代碼,有時會想到把某些功能函數換過一個更合適的名字,但考慮到在現時千絲萬縷的連結下,若利用 Search & Replace 的話,錯誤的風險會很高。

原來在 XCode 下有著一個名為 Refactor 的功能,可以有效地處理以上問題。只要在功能函數上點選滑鼠右鍵,便會彈出如左圖般的選單。點選 Refactor 後輸入新的函數名稱,切記要輸入冒號!按 Preview 後會出現將要修改的地方,同時 Preview 按鈕也會變成 Apply 按鈕。其中 Snapshot 是打勾了,這個是備份功能,方便還原之用;但會把整個 Refactor 進程拖得很慢,我通常都會把它關掉!反正 Refactor 之後的代碼不會立即儲存。最後就是按 Apply 啦!

2009年10月15日 星期四

Shadow warnings!


今日花了半天時間找 Bug,到最後原來是因為使用了一個跟 Class member 同名的 Variable 而導致!這個錯誤已經是連續第二天犯下,為免再重蹈覆徹,決定要有效地找出相同的 Variable 名稱。做法很簡單!在 XCode 內 Build Configuration 內的 Other Warning Flags 加入 -Wshadow,代碼在編譯時會找出定義了相同 Variable 名稱的地方,給編程人員一個警告。

2009年10月9日 星期五

AppleScripts 處女作



最近工作上的關係,很想在 Leopard 上把大批大批的檔案改名。這個在 Windows 上很簡單的一個指令(ren *.m *.x),卻在 Leopard 上成為難題。雖然我可以用 Windows 來處理這個工作;但在 Leopard 下進行開發,始終想找個解決方法。原來網上也有很多朋友遇到相同的情況!他們多會改用軟件處理(居然連改名都會出一個專用軟件),而我不想下載及安裝,便決定改為使用 AppleScripts 來代替。它是內建在 Leopard 之內,所以不用安裝,而且是免費!我是第一次接觸 AppleScripts。發現它很像英語,單憑指令語句來學習,真是一頭霧水!花了兩個小時,我最後都能編寫出批次修改副檔名的 AppleScripts 了!
 
------------------------------------------------------------------------------
-- Rename File Extension script
-- Program by Pacess HO
-- 2009-Oct-09 22:30
------------------------------------------------------------------------------
try
-- Set focus to the top folder window
-- And put the path to "sourceFolder"
tell application "Finder" to set the sourceFolder to (folder of the front window) as alias

on error
-- In case no open folder windows, show an error message
display dialog "Please select a folder first and then run script again." with icon caution buttons {"Finish"}
beep 2
return
end try

-- Enter the existing file extension
repeat
display dialog "Enter the extension want to be replaced" default answer "m" buttons {"Cancel", "OK"} default button 2
set the oldExtension to the text returned of the result
if the oldExtension is not "" then exit repeat
end repeat

-- Enter the new file extension
repeat
display dialog "Enter the NEW extension" default answer "x" buttons {"Cancel", "OK"} default button 2
set the newExtension to the text returned of the result
if the newExtension is not "" then exit repeat
end repeat

-- Put files in "sourceFolder" to "fileList"
set the fileList to list folder sourceFolder without invisibles
set sourceFolder to sourceFolder as string

-- Process each file
repeat with i from 1 to number of items in the fileList
set thisFileAndPath to item i of the fileList
set thisFileAndPath to (sourceFolder & thisFileAndPath) as alias
set thisFileInfo to info for thisFileAndPath

-- Remove the path and remain filename with extension
set the thisFileName to the name of thisFileInfo

-- Just process the file which is not a folder or alias
if folder of thisFileInfo is false and alias of thisFileInfo is false then

-- Is it end of old extension?
if the thisFileName ends with the oldExtension then

-- Get the length of old extension
set the nameLength to the number of characters of the oldExtension

-- Remove the old extension
set the newFileName to (characters 1 thru -(the nameLength + 2) of the thisFileName) as string

-- Add the new extension
set the newFileName to the (the newFileName & the "." & the newExtension) as string

-- Rename
tell application "Finder"
try
set the name of thisFileAndPath to the newFileName
end try
end tell

end if
end if
end repeat
beep 2

2009年10月7日 星期三

靈活調動 UITableView 項目的方法

由於 Unit Test 的項目漸漸增加,而某些項目的使用頻率增加了;為了方便起見,我需要能靈活調動項目的次序,以及其相對應的 viewController。

首先在 loadView 內定義好一個 NSArray,內裡包含了項目名稱及其 viewController 的類:

// Prepare menu items
menuList = [[NSArray alloc] initWithObjects:
@"Test 1", [Test01Controller class],
@"Test 2", [Test02Controller class],
@"Test 3", [Test03Controller class],
@"Test 4", [Test04Controller class],
@"Test 5", [Test05Controller class],
@"Test 6", [Test06Controller class],
@"Test 7", [Test07Controller class],
nil];
之後在 didSelectRowAtIndexPath 中加入以下指令:

//-------------------------------------------------------------------------------
// Respond to user selection
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)newIndexPath {
UIViewController *viewController;

int itemSelected = [newIndexPath row];
int index = (itemSelected<<1)+1;
Class thisClass = [menuList objectAtIndex:index];
viewController = [[thisClass alloc] init];
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
}
這樣,日後要更改項目的次序時,只要修改 menuList 中的排位即可;要新增項目時,在 menuList 中加入即可。

2009年10月6日 星期二

搜尋應用程式目錄下的檔案

今天我為 Unit Test 的 Java UTF Text 測試進行了更新;把原本放在 UIPickerView 的固定地圖檔名改為即時在應用程式目錄下搜尋出來。

// Search png file names
NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
mapFileList = [[[[NSFileManager defaultManager] directoryContentsAtPath:resourcePath] pathsMatchingExtensions:[NSArray arrayWithObject:@"png"]] copy];
搜尋出來的檔名會包含了檔案類別名稱,在使用到 pathForResource 時便要把它刪除,可使用以下指令:

// Remove file extension .png
NSString *fileName = [pngFileName stringByDeletingPathExtension];
NSString *filePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"png"];
if (filePath == nil) {return @"Error";}

2009年10月5日 星期一

設定公司名稱的方法

在 XCode 內新增新代碼檔案時,在頂方都會出現 __Company_Name__ 字眼,一直都想更正這個問題,今日給我找到了答案。其中一個方法是在 Terminal 輸入
defaults write com.apple.Xcode PBXCustomTemplateMacroDefinitions '{ORGANIZATIONNAME="CompanyNameHere";}' 
即可。

2009年9月29日 星期二

關於 Build Configuration


為了方便測試遊戲中各個部份,我們習慣會建立一個 Unit Test 介面。這個 Unit Test 部份會在程式啟動時決定是否執行。原本是利用 #define UNIT_TEST true 的方式決定編譯的是正常版,還是測試版;但發現使用 Build Configuration 更為方便。我的做法是把 Debug Configuration 複製一份並命名為 Debug with Unit Test;再如圖所示,在 Preprocessor Macros 中定義 UNIT_TEST;這樣只要在代碼中使用 #ifdef 來分辨版本即可。

int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

#ifdef UNIT_TEST
int retVal = UIApplicationMain(argc, argv, nil, @"TestAppDelegate");
#else
int retVal = UIApplicationMain(argc, argv, nil, @"iPhoneAppDelegate");
#endif

[pool release];
return retVal;
}

2009年9月28日 星期一

iPhone 開發的隱藏開支(二)

最近收到了 Apple 的第二次匯款。今次的收入下降了不少,而匯款費用亦由 $60 下降至 $15。原先以為因為金額的不同,令到服務費亦有所下降;但向 Double-Sys 作者查證後,發現他的服務費亦只是 $15。翻查匯款收據後,發現第一次匯款是以 Telegrahic Transfer 方式處理;而今次的卻是 Interbank Fund Transfer。相信是處理方式不同,導至收費不同。問題是:由何人決定使用哪個方法呢?相信已經呼之欲出;但不論是誰,結帳都是我。Apple 這個角色真好賺!

2009年9月26日 星期六

Pivot


今天網遊時發現了一個軟件,對於遊戲製作,尤其是動作設計時十分適用。有興趣的網友可到 http://www.snapfiles.com/download/dlstickfigure.html 下載(Windows only)。

2009年9月25日 星期五

Quartz 學習記錄

這幾天專注於設計一個程序,去讀取公司遊戲中常用的 SPX 格式。當中包含了遊戲資料、切片數據及圖片數據,這是遊戲製作人很常用的組合方法。完成了讀取後,便需要按照數據把相關圖片中的切片繪畫出來。由於要繪畫整張圖片中的細部份,因此而要用上 Clipping 方法。今之的 Clipping 跟我之前處理 TravelHunt 遊戲內的時間軸的方法不同;那個應該說是 Masking 而不是 Clipping。

UIImage *image = [arrayImage objectAtIndex:0];
int png_width = image.size.width;
int png_height = image.size.height;

int x = 100;
int y = 100;
int width = 50;
int height = 50;

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL,
width, height, 8, (width<<2), colorSpace,
kCGImageAlphaPremultipliedFirst);

CGContextSaveGState(context);

CGRect clipRect = CGRectMake(0, 0, width, height);
CGContextClipToRect(context, clipRec);
CGRect drawRect = CGRectMake(-x, -(png_height-(height+y)),
png_width, png_height);

switch (framefrag.transform) {
case TRANSFORM_NONE:
transform = CGAffineTransformMake(1, 0, 0, 1, 0, 0);
break;

case TRANSFORM_MIRROR:
transform = CGAffineTransformMake(-1, 0, 0, -1, fw, 0);
break;

case TRANSFORM_MIRROR_180:
transform = CGAffineTransformMake(1, 0, 0, -1, 0, fh);
break;

case TRANSFORM_ROTATE_90:
transform = CGAffineTransformMake(0, -1, 1, 0, 0, fw);
break;

case TRANSFORM_ROTATE_180:
transform = CGAffineTransformMake(-1, 0, 0, -1, fw, fh);
break;

case TRANSFORM_ROTATE_270:
transform = CGAffineTransformMake(0, 1, -1, 0, fh, 0);
break;

case TRANSFORM_MIRROR_270:
transform = CGAffineTransformMake(0, -1, -1, 0, fh, fw);
break;

case TRANSFORM_MIRROR_90:
transform = CGAffineTransformMake(0, 1, 1, 0, 0, 0);
break;

default:
transform = CGAffineTransformMake(1, 0, 0, 1, 0, 0);
break;
}

CGContextConcatCTM(context, transform);
CGContextDrawImage(context, drawRect, image.CGImage);

CGContextRestoreGState(contextPart);
有一點要特別留意,Quartz 是採用 Painter’s model,意謂效果只會在設定後的繪畫動作才出現。所以 Transform 會先行出現,後面才 DrawImage。

2009年9月22日 星期二

Snow Leopard 真的快


昨天把公司的 MacBook 更新至 Snow Leopard 後,體驗到 Snow Leopard 的快感,而且原本在公司讀取不到的 Gmail 也能順利運作,是一個很好的升級。

2009年9月19日 星期六

Tour Album 上架


今次 Tour Album 的審批進程回歸正常,只需要八至九天便完成審批。之前 Sansu Law 出現的 23 天長審批,相信是 Apple 人員遺漏了而導致。事關當我在 15 天過後發電郵給他們查詢時,他們還就不能就個別軟件回覆審批狀況,不料 7 天後 Sansu Law 就能上架了。

http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=331099499&mt=8&s=143441

2009年9月15日 星期二

UIScrollView 下的拖拉問題


根據介面設計,由標題畫面跳轉到排行榜/遊戲等畫面,會使用拖拉方式。這個部份亦經已完成。但遇到的問題是在遊戲畫面下,亦同樣遇上 UIImageView 的拖拉功能,系統會先行處理 UIScrollView 的拖拉後才會處理 UIImageView 的。這樣便構成了問題,當玩家希望拖拉方塊時,卻形成了拖拉畫面。雖然 SDK 文件中交代過可以撰寫新的 touchesShouldBegin:withEvent:inContentView: 及 touchesShouldCancelInContentView:,情況卻只是稍為改善。在敏捷的拖拉動作下,仍然會把畫面拉倒。

對於這個問題,仍然在尋找合適的解決方案。

2009年9月12日 星期六

最新遊戲作品的 Ranking 畫面


這是最新遊戲作品的排行榜畫面。今次加入了 Online Ranking,數據是即時從伺服器下載;在模擬器及 iPhone 真機上試跑過,效果很滿意。

2009年9月11日 星期五

十字形 UIScrollView

在我最新的遊戲裡,其介面設計希望呈「十字形」,即是畫面可以蹤向拖拉之外,亦可以橫向拖拉。我分別把蹤及橫的 UIScrollView 加入 Superview,但出來的效果卻只有最後一個向的拖拉。

正確的方法是先建立橫向 UIScrollView 後,再建立蹤向 UIScrollView,並加入到橫向 UIScrollView 內。

2009年9月10日 星期四

Tour Album 審批進行中


Tour Album 原先的名稱是「Tour Book」。取這個名稱是一來想叨 Facebook 的光,二來裡面有 122 張照片,足以成為一本書。但這個原先沒有使用的名字,竟然在一個月後上傳時不能使用(原因就是有其他人搶先使用了咯!)。看來下次還是先下手為強,製作好 Icon 後便立即註冊,避免軟件開發完成後要再花時間換名換標題畫面。

這個軟件是利用「Sansu Law」的框架完成,並改為橫向版本。跟「Sansu Law」一樣,都是一個相片集軟件,用家可以把圖片儲存到 Photo Album 內作為壁紙之用。今次總共收錄了 122 張風景及寫實照片,有部份是不曾公開。希望這個軟件能為無業的我增加一點點收入。

2009年9月9日 星期三

「Sansu Law」上架了


我的第八個 iPhone 作品「Sansu Law」,經歷了 23 天的審批終於上架了。請大家多多支持。

2009年9月3日 星期四

今天失業了

我今天失業了。需要找下一份工作,但仍然想在遊戲界發展。

現在時間多了,會加速 iPhone 遊戲的開發,以及繼續把小機械人完成。

2009年8月28日 星期五

Apple 的審批進程

Sansu Law 已經上傳 12 天,但仍沒有得到任何回覆。比起平常的時間多出 85%,也比最近同事那個大賣的 DoubleSys 的 9 天審批來得長。難道 iPhone 的軟件開發人員增加得那麼利害,導致審批時間拉長?真希望 Apple 能對審批時間作出承諾,令到開發者們有個預算。

2009年8月25日 星期二

Alphabet Trainer 完成





Alphabet Trainer 的學習功能終於完成了!若遇上無法辨認的字母時,它便會要求使用者指引一下,辨認的資料庫也會增加多一筆數據。這些數據將會作為 iPhone 遊戲開發之用。

2009年8月23日 星期日

Provisioning Profile 到期日


我的第一個 Provisioning Profile 的使用期限已經結束。由於 TravelHunt:Europe 是在 Apple 改制後建立,因此它是最快一個到期的 Profile。不過,我不清楚到期後有甚麼不同。反正軟件仍然能夠執行,相信只是無法再組譯後放到 iPhone 吧。

2009年8月22日 星期六

收集手寫資料

平時當我有新遊戲的構思時,總會把它記錄下來,方便日後需要時可以派上用場。今天想出了一隻需要手寫字母的遊戲,於是急不及待利用 Flash 製成了一個收集手寫資料的軟件。暫時只有很少資料,仍未完成學習功能。有興趣可以試試:

http://www.pacess.com/flash_games/alphabet_trainer.html

2009年8月20日 星期四

2009年8月19日 星期三

iPhone VNC: Veency

在網上找了幾個 Leopard 的畫面擷取軟件,最終只有 Copernicus 能成功把 iPhone 模擬器的畫面抓下來。可是由於電腦效能的關係,影片會出現畫面斷裂的情況,尤其是當畫面進行 Transition 的時候;這樣的影片質素,絕對不能放在官網使用。

後來我嘗試另一個方法,在 iPhone 上安裝 Veency,使得我可以透過 VNC 進入 iPhone 手機,並在 Windows 上顯示出 iPhone 的畫面。不過今次的試驗也告失敗,在 Windows 上顯示 iPhone 畫面的情況跟畫面擷取時差不多,都是在 Transition 的時候,畫面會出現斷裂。

2009年8月18日 星期二

iPhone 8 號審批進行中

我的第 8 號 iPhone 作品已經完成,並進入審批階段。這個作品跟以往的獨立製作不同,今次跟另一家公司合作,是一個長足的進步。希望是一個成功的試點,為我的目標及合作伙伴帶來益處!預計在 8 月 25 日上架,敬請留意官網 www.pacess.com

2009年8月17日 星期一

無法抓取畫面

原本想將 www.pacess.com 官網的遊戲硬照改為影片,可是最近我總是無法在 Leopard 10.5.7 下成功抓取畫面。要是使用 DV 來拍攝,效果又不好...。相信短期之內都實現不了!還好的是現在這個版本,利用 iPhone 來看是沒有問題,要是轉了 Flash 的話,可能會出現問題~

2009年8月15日 星期六

YouTube 小秘技

對於現時官網 www.pacess.com 只顯示遊戲畫面的硬照,我感到十分沉悶,因此想把它改為影片播放模式。要達到這個目的,就需要兩個功能,幸好 YouTube 是支援的:

&autoplay=1:自動播放
&loop=1:自動回帶

還有播放 Playlist 功能對我來說也是十分實用,可以把我過往的影片剪接作品一氣呵成地展示出來。我不知道怎樣才是正途,卻只用了一個愚蠢的方法達成:

1) 在 YouTube 製作好 Playlist
2) 點擊「分享此播放清單」
3) 輸入自己的電郵地址並傳送
4) 點擊推薦電郵內的圖片
5) 在網頁內會出現 Embed 的程式碼

2009年8月14日 星期五

2009年8月8日 星期六

新開發工具:iPhone File Packer


以前在製作電腦遊戲時,往往都會將遊戲中使用到的圖片打包成一個大檔案,目的除了阻難黑圖的人之外,也能使編程更為簡單,甚至乎日後升級時(如加入編碼或壓縮功能)也不用修改原有程式。今次我利用 C# 編寫了這樣的一個工具,主要都是為了阻難黑圖的人...。

2009年8月5日 星期三

iPhone 開發的隱藏開支

回到家後,收到由 HSBC 寄過來的信件。拆開後原來是 Apple 匯款的通知單,當中有一項是手續費,要 HK$60,是由 HSBC 收取。為了更加了解費用的計算方法,我到 HSBC 的網頁查詢,可惜找不到確實的資料,希望這個費用是固定的,而不是按匯款的金額來計算。

其實這裡還有一項「海外費用」,幸而是不用收費。難怪 Apple 訂立了要 US$250 才匯款一次,不然我們的版權費用會被銀行蠶食得很利害!

2009年8月2日 星期日

終於都出糧喇

經歷了四個月的努力,iPhone 的生意在美金類別中已經累積滿 US$250,在前幾天收到六月份的 Financial Report,而今天則收到了這筆權利金!亦即是說收到 Report 後大約一個星期之內便能收到錢。這也證明了之前的 SWIFT Code 及 Local Clearing Code 是正確!

Travel:Hunt Universal 上架


Travel:Hunt Universal 已經上架。今集包含了過去三集(日本關西、香港、歐洲)的部份相片,再加入北京、台灣、東京、泰國,以及新的香港相片。請多多指教!

2009年8月1日 星期六

動漫節 2009 - Game Girls #10

動漫節 2009 - Game Girls #09

動漫節 2009 - Game Girls #08

動漫節 2009 - Game Girls #07

動漫節 2009 - Game Girls #06

動漫節 2009 - Game Girls #05

動漫節 2009 - Game Girls #04

動漫節 2009 - Game Girls #03

動漫節 2009 - Game Girls #02

動漫節 2009 - Game Girls #01













雖然我唔鍾意 M$,但我覺得 Zensu(唔知係咪咁寫)最靚~

Updates:
原來正寫係 Sansu,以下是 Sansu 的連結:
http://www.vivaphoto.com/yahoo/Portraits/Sansu+Law/
http://www.fotop.net/ming181920/sansu?page=1
http://www.fotop.net/fanling409cq/SANSU/sansu19
http://mihk.hk/forum/thread-917668-1-1.html
http://www.fotop.net/laipeter93/laipeter93716
http://ecfoto.net/altgecfoto/tags/Sansu%20Law
http://www.dcfever.com/models/viewphoto.php?id=1002&photo_id=2755
http://www.mihk.hk/forum/thread-377709-1-1.html

http://ifs8.imagefly.info/v/de/jpg/s26.html
http://ifs8.imagefly.info/v/de/jpg/s27.html
http://ifs8.imagefly.info/v/de/jpg/s28.html
http://ifs8.imagefly.info/v/de/jpg/s29.html

2009年7月28日 星期二

Pacess.com 正式登場

一直以來,我都很想建立一個網頁去吸引生意。之前參考其他 iPhone 開發者的成功經驗,發現他們都有為自己的 iPhone 軟體建立網頁,今次就借機會申請一個!www.pacess.com 就在今天正式登場,請多多指教。

2009年7月25日 星期六

Travel:Hunt - Universal 完成

昨晚提起勁把 Travel:Hunt - Universal 完成,並已經上傳到 Apple 等待審批。

2009年7月22日 星期三

把 Sleep Mode 關掉

Turn Off iOS Sleep Mode

如果想在 iPhone Apps 運行期間把 Sleep Mode 關掉,只需要在應用程式載入後執行:

[[UIApplication sharedApplication] setIdleTimerDisabled:YES];

2009年7月21日 星期二

Destiny Clock 轉為免費


Destiny Clock 其實是從 Love Pair 體內抽出來的一個部份,並把它產品化。原本都沒有打算它能為我增加收入;而事實上獲得的也極之少。但既然造出了一個產品,我也希望能有很多人使用,因此我決定把它變成免費版。有興趣的朋友,可以點選上圖,或到以下地址下載。

http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=310499729&mt=8

2009年7月20日 星期一

觀察結果

我一直都有留意香港遊戲公司 CDE 的 iPhone 作品,原因是他們的水準不錯,而且產量甚高,更經常在暢銷排行榜出現;還有一個私人因素,就是 CDE 是由惡名昭彰的 Victor 所創立。不過,現在他已經不是老闆。

在觀察其 iPhone 作品時,發現他們的作品名字都以 A, B, C 字母為首,其目的不外乎是希望在搜尋結果中爭取最好排位。他們的作品能有好成績,相信這個命名方法有一定的作用。

2009年7月19日 星期日

US Dollars


一直以來,我都想製作一個數美金的 iPhone 應用程式。不過一直都只停留在構想階段,沒有實際的行動。原因是一不小心,便很容易觸犯美國的法例。今天,我在網上 http://www.faqs.org/faqs/coin-collecting/paper-money-faq/section-43.html 搜尋到一則關於複製美金圖案的資料:

Writing "COPY" or something similar, or copying only a portion of a note does not exempt you from the copying law. The act of copying is the crime.

始乎要實現這個構想是不行了;除非在圖案上加上 Copy 字樣,但這樣會對軟件的感覺大打折扣。

2009年7月18日 星期六

Travel:Hunt 系列上架

經過一個星期的時間,Travel:Hunt - Europe, Hong Kong, Kansai 都得到 Apple 的審批。我的收入也有望回復先前的水平。

2009年7月13日 星期一

Midas touch: Smartphone apps: the new gold rush

今天收到 Vanessa 的通知,之前的訪問已經在昨天的 South China Morning Post 刊登了,因此我只有電子版本,而找不到報紙版本。以下是節錄自 7 月 12 日的 SCMP 內容:

Pacess Ho Siu-kay, 33, enjoys making iPhone apps but is more focused on their money-making potential.

"I want to generate some income ... after having spent two to three weeks developing an application," says Ho, who devotes a couple of hours after work each night to his passion. His ultimate goal is to pay off his mortgage and enable his wife to quit her job to look after their daughter full time.

Ho has been an online game developer for more than 10 years. Last November, he started learning Objective-C by consulting books, the internet and sample code from Apple. Three months later, he paid US$99 to use the iPhone developer program.

He launched his first application, Lottery Pro (a Mark Six predictor; 99 US cents), on the App Store on March 1. Since then, he has put Destiny Clock (the date and time in relation to the 60 animal-element combinations of the Chinese zodiac; 99 US cents), Love Pair (the assessment of relationships using Chinese numerology; US$1.99) and several spot-the-difference puzzles on the Apple shelf. He has made more than US$300 in three months.

Apple keeps 30 per cent of the money it takes but requires sales of an app to reach US$250 before it hands any to the developer.

Ho says he hopes to find a killer app that will deliver a windfall.

2009年7月12日 星期日

Travel:Hunt - Universal


手上的自由工作已經開發完畢,而 PhotoHunt 系列亦已經完成「改名任務」。我也要全力繼續開發 Travel:Hunt - Universal 版本。這個版本集合了部份 Europe, Hong Kong, Kansai 版本的圖片,再加入大量新圖片!今次 Universal 版本將會收錄 100 張相片!現在的進度只有 60%,相信要花兩個星期的時間才能完成。

2009年7月11日 星期六

Travel:Hunt - Europe 改名完成


PhotoHunt: Europe 已經改名為 Travel:Hunt - Europe。現正待 Apple 審批。今次除了改名之外,還針對小錯誤作出修正,以及替整個系列加入簡單保護。希望今次的審批能在一個星期內完成。

2009年7月10日 星期五

PhotoHunt 系列全線落架

今天收到 Apple 轉寄過來的信件,一間名為 AMI 的美國公司去信 Apple,指它們已在 1999 年為 "PHOTO HUNT" 名稱註冊了商標;而在我的作品中,恰巧用上了 "PHOTOHUNT" 字眼。所以 AMI 公司發信要求 Apple 在十天內處理今次事件。

雖然在 PhotoHunt 系列中使用到的是單一個連字,而且當中沒有空白位,這跟 "PHOTO HUNT" 是有分別。但為了安全起見,以及遊戲名稱更改也沒有大影響的情況下,我決定暫時將 PhotoHunt 系列全線落架;待更改名稱後會再次上架。

2009年7月3日 星期五

SCMP 訪問

今天很高興接受了 SCMP 的 Vanessa 訪問。整個過程花了 34 分鐘,我們談及參與 iPhone 軟件開發的目的、遇到的困難、題材的構思...等。當中有些提問值得我再花時間思考一下。希望今次的訪問能盡快刊登吧。

2009年7月1日 星期三

2009年6月27日 星期六

五月份財政報告

今天收到了四份五月份的財政報告,還有三份應該會在明天到達。由於五月份仍然未有 PhotoHunt 上架,所以生意額仍然低迷。

最新,Apple 接二連三延遲了每日報告的發出時間,昨天的報告到現在還沒收到,我十分著急,因為前兩天的生意一直下跌,希望昨天能有點反彈;不過,遇上巨星 Michael Jackson 的離世,亦可能會導致生意下跌...。

2009年6月26日 星期五

儲存資料數據

在我所有的 iPhone 作品中,都會用上儲存資料數據;如 Lottery Pro 會存取號碼的數量及範圍、Love Pair 會存取配對的分數及名字、PhotoHunt 會存取分數及名字等。我是使用以下方法:

儲存數據

NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
[preferences setObject:@"9999" forKey:@"score"];

讀取數據

NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
NSString *textData = [preferences stringForKey:@"score"];

2009年6月24日 星期三

Firmware 3.0 下使用 iTunnel

最近把 iPhone 升級為 Firmware 3.0 之後,只能透過 WiFi SFTP 進入 iPhone;而平時使用 USB + iTunnel 的方法卻失效了。經過查證之後,原來需要把 iTunnel 內的 iTunesMobileDevice.dll 更新。自 iTunes 8.2 開始才支援 Firmware 3.0 的 iPhone。所以這個 DLL 需要在 iTunes 8.2 的資料夾(C:\Program Files\Common Files\Apple\Mobile Device Support\bin)內找到。只要把它覆蓋 iTunnel 內的 DLL 後,便能再次利用 USB + iTunnel 連接 iPhone。

2009年6月23日 星期二

2009年6月22日 星期一

Leopard 下的 PS/2 鍵盤問題(二)


今天在公司借來了一個 USB 鍵盤,插入後簡單設定一下便能使用,於是我便繼續升級的步驟。我先用 ASU-0.5 來更新,可是無論我怎麼輸入,都說的的密碼錯誤。經過多番嘗試,我決定利用 iPC 光碟,重新設定帳號密碼及把帳號設定為「系統管理員」身份。處理完成之後,我再以 ASU-0.5 來更新,可是錯誤依然存在。於是我冒險使用 Software Update 來更新,並只更新系統部份。這個過程十分順理,在第一次重啟後,系統會再次重啟,有點像更新出現問題一樣。但在第二次重啟便沒有問題,唯一就是 PS/2 鍵盤仍然無法運作。

我利用 Kext Helper 來安裝 ApplePS2Controller.Kext 及 AppleACPIPS2Nub.Kext 之後,在沒有重啟的情況下,鍵盤能回復正常。現在,我的系統終於能更新至 10.5.7 了。