2012年2月29日 星期三

六足板金完成

Sheet Metal Done
跟網友 Peter 校對好足部板金的 Servo 鑽孔之後,已經進入少量生產,六塊足部板金全部完成,還有兩塊後備。之後就是要針對身體部份進行製作!

2012年2月28日 星期二

AMIGO Hexapod 身體設計二號

New Body Plate Design
由於 AMIGO Hexapod 第一版本的板金身體出了嚴重的位置錯誤,於是在製作第二版本時,順便改動一下設計。使得六隻足部相隔均等的距離及角度,變成沒有指定方向的設計。

2012年2月27日 星期一

AMIGO Hexapod 足部成品

Leg of AMIGO Hexapod
從網友 Peter 手上取得數件 AMIGO Hexapod 的板金,回家後一試,發現足部板金容不下 Futaba S3003。先機的 Peter 已經為我準備好另一件修改版本,能放入 S3003。可是由於鑽孔在繪圖時已經出錯,所以這塊板金的鑽孔也沒有對正 Servo。然而,我把本來 2mm 的鑽孔增大為 3mm 後,算是能夠把 Servo 裝起。

至於身體的板金,放入 S3003 後的虛位較大,需要作出修改。而鑽孔問題則不像足部板金來得容易處理,需要把鑽孔增大到 6mm 才能勉強把 Servo 裝在圓心那邊。圓周那邊則因為闊度問題而無法把鑽孔增大。整塊面板需要重新設計...。

2012年2月26日 星期日

AMIGO Mini 新設計

AMIGO Mini New Design
完成了 AMIGO Hexapod 的設計之後,便是 AMIGO Mini。

2012年2月25日 星期六

AMIGO Hexapod 身體板金

AMIGO Hexapod Body Plate
AMIGO Hexapod 身體板金已經生產出來!在繪畫設計圖時都是以 1mm 來計算,但考慮到硬度問題時,決定把面板改為 2mm。Servo 的位置橫直預留了 2mm 的空間,避免實物不完美而放不下的情況。

2012年2月24日 星期五

UIScrollView 的縮放處理

最近替客人開發一個類似 iBooks 的應用,當中使用 UIScrollView 來處理放大縮小頁面。我希望如果圖片小的話便置中在中央;要是圖片大過畫面時,則把它 Fit 入畫面中。可是花了一輪時間仍然解決不了大圖的位置問題。上年替「新鴻基」開發的「瓏璽」也遇過相同問題,當時花了很多時間去解決。為了節省時間,還是取用那段源碼好了。
- (void)updateContent:(UIImage *)image  {
 NSLog(@"[ContentViewController updateContent]");
 if (self.image == nil)  {return;}

 //  Assign image
 self.image = image;

 //  Calculate scroll view size
 CGFloat screenWidth = _scrollView.frame.size.width;
 CGFloat screenHeight = _scrollView.frame.size.height;
 CGFloat width = image.size.width;
 CGFloat height = image.size.height;

 int contentWidth = width;
 int contentHeight = height;

 CGFloat scaleW = (screenWidth/width);
 CGFloat scaleH = (screenHeight/height);
 CGFloat scale = (scaleW < scaleH) ? scaleW : scaleH;
 
 int centerX = 0;
 int centerY = 0;
 if (scaleW >= 1.0f && scaleH >= 1.0f)  {

  //  Both width and height less than frame size
  scale = 1.0f;
  contentWidth = screenWidth;
  contentHeight = screenHeight;
  centerX = (contentWidth/2);
  centerY = (contentHeight/2);

 }  else  {
  
  //  Either or both side larger than frame size
  if (scale == scaleW)  {
   //  Width ratio is longer than height
   if (height <= (screenHeight/scaleW))  {contentHeight = screenHeight/scaleW;}
   else  {contentHeight = (height/scaleW);}
   centerX = (width/2);
   centerY = (contentHeight/2);
  }  else  {
   //  Height
   if (width <= (screenWidth/scaleH))  {contentWidth = screenWidth/scaleH;}
   else  {contentWidth = (width/scaleH);}
   centerX = (contentWidth/2);
   centerY = (height/2);
  }
 }
 
 //  Order is important!  Must remove photoView before set new value to contentView
 _contentSize = CGSizeMake(contentWidth, contentHeight);
 CGRect rect = CGRectMake(0, 0, contentWidth, contentHeight);
 [_backView removeFromSuperview];

 UIView *uiview = [[UIView alloc] initWithFrame:rect];
 [uiview setBackgroundColor:[UIColor darkGrayColor]];
 [_scrollView addSubview:uiview];
 [uiview release];
 _backView = uiview;

 [_scrollView setContentSize:CGSizeMake(contentWidth, contentHeight)];
 [_scrollView setMinimumZoomScale:scale];
 [_scrollView setZoomScale:scale];
 
 //  Update image to image view
 UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
 [imageView setCenter:CGPointMake(centerX, centerY)];
 [_backView addSubview:imageView];
 [imageView release];
}

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView  {
 return _backView;
}

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale  {
 CGSize size = _contentSize;
 size.width *= scale;
 size.height *= scale;
 [_scrollView setContentSize:size];
}

2012年2月23日 星期四

AMIGO Hexapod Arm 製成品

得到網友 Peter 的幫助,第一塊關節板金已經順利切割完成。簡直跟繪圖一模一樣,效果十分之好!多謝 Peter!

2012年2月22日 星期三

AMIGO Hexapod Design 04

今年訂下的一個目標是完成六足機體,經過多次嘗試及修改後,有了第四個設計。雖然在設計上不是最好,但暫時算是滿意。

機身上的鋁片原本打算用 1mm 厚度,但得到網友 Peter 的意見後,決定將面板改用 2mm,增加硬度以承受較大的重量。底面兩埋面板將會用 Peter 的 CNC 製作出來,很期待看到成品的一刻。

要是造出成品後 Futaba S3003 不夠力支持身體重量的話,則會改用 TowerPro MG995。

2012年2月21日 星期二

在折曲線上打孔

Snap a Hole on a Line
在 Inventor 製作好板金模樣後便可以拿去給 CNC 切割。板金製成後需要折曲成形,但以肉眼及人手折曲時很容易出錯,導致角度及斜度不如理想。網友 Peter 教了我一個準確折曲方法。在折曲線的頭尾上打孔,然後利用幼細的金屬線貫穿,放在虎鉗上。金屬線承托起板金,折曲線便能跟虎鉗達致平衡,從而造出接近完美的角度。

但是在 Inventor 內要如何畫到呢?就算利是 Snap to Grid 之類的方法也無法準確地把孔打在折曲線上。找了很久,終於給我研究出方法來。只要在 Sketch 模式下,於折曲線的附近打孔後,點選 Coincident 便能把孔蝕入折曲線內。

2012年2月19日 星期日

六足的腳部設計.四

AMIGO Hexapod Leg Design 04
對於六足機體的設計,我希望盡量少用 Servo。參考過國外不同的設計,最新的成果如上圖一樣。有網友提示過 Futaba S3003 不夠力,但之前添置了很多,要是不用的話是很浪費,所以即本嘗試一下。畢竟六足一起支持身體的重量,情況應較為理想。

2012年2月18日 星期六

「反斗車王」引擎升級

Modify Cars 2 Turbo RC Racer - McQueen
上星期買了一台「反斗車王」遙控車。這是在三個級別中幾經考慮之下購買的。買回來的原意不是當玩具般使用,而是希望加裝 MCU 及檢測器,造成一架能自動遊走及穿梭障礙物的機體。選擇「麥坤」是因為我喜歡它的造型。

今天經過旺角時,特意去找四驅車模型專用的高速馬達。找了十家模型店後終於找到了。那裡有三款相同電壓但不同消耗的馬達。消耗越大,速度越高。我選擇了以下這款,售價 HK$48。
回到家裡,先把「麥坤」拆開,用電錶量度一下遙控車馬達的電壓。前進是 +3V,後退是 -3V。剛好符合新買馬達的規格。要把原有馬達除下來,是需要先把後輪拆下。
原有馬達連接著一顆編號 104 的電容,相信是作為穩定電流之用。幸好家中也有不同型狀但相同編號的電容。把它連接到新馬達。
經過一輪焊接,終於更換完成。可惜落場起跑時,發現跟原裝的分別不大,而且後退時的速度更慢。希望日後能改善速度吧。

2012年2月16日 星期四

死神學神

構思到一個故事大崗,如果有機會能拍成電影就好了。

在冥界中有一種叫「死神」的職業,祂們每天都會接到「柯打」準時到達死亡地點,靜待死亡的發生,引領靈魂到達輪迴的地方。時間對於祂們來說十分重要。若然錯過引領靈魂的時間,祂們要因此而付出代價。「死神」這種職業並不是依照自己的意願選擇;而是生前種下的罪孽太深,需要成為「死神」經歷多次死亡來獲得救贖。當祂們看淡生死之時,便能重返輪迴之道。這是剛剛成為「死神」的阿一接到「柯打」,由上級帶領之下執行第一次任務,及之後發生的一連串故事與面對多次生死的領悟。

2012年2月15日 星期三

After Effects 下的影片加速

Fast Forward in After Effects

很久很久沒有剪片了。今個星期接了一個項目,替客人製作兩段影片作為報告之用。雖然這個項目沒有難度,但步驟很多。總算完成了第一段。要在 iPad 中為動畫編程,然後錄下模擬器的動畫,把影片裁好後,還要將原來 2 分 17 秒的影片濃縮到 8 秒。否則看報告的人必然睡著。花了一點時間,才找到影片加速的方法。在 Composite 中點右鍵,選 Time 內的 Time Stretch 後,輸入最終想要的時間長度。

2012年2月14日 星期二

raw2UIImage

以下是 raw2UIImage 的源碼:
+ (UIImage *)raw2UIImage:(unsigned char *)rawData width:(int)width height:(int)height  {
 if (rawData == NULL)  {return nil;}
 if (width < 0)  {return nil;}
 if (height < 0)  {return nil;}
 
 //  Link up raw data to context
 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
 CGContextRef contextRef = CGBitmapContextCreate(rawData, width, height, 8, width*4, colorSpace, kCGBitmapByteOrder32Little|kCGImageAlphaPremultipliedFirst);
 
 //  Create a UIImage from raw data
 CGImageRef imageRef = CGBitmapContextCreateImage(contextRef);
 CGContextRelease(contextRef);
 free(rawData);
 UIImage *outputImage = [UIImage imageWithCGImage:imageRef];
 CGImageRelease(imageRef);
 CGColorSpaceRelease(colorSpace);
 
 return outputImage;
}

把這段源碼跟 obm 檔的解密源碼(http://pacess.blogspot.com/2011/07/street-fighter-iv-volt-obm.html)一齊使用,便能輕易製作出 obm 轉 png 的工具。

2012年2月13日 星期一

關於 Activity 之間的數據傳送

About Data Passing Between Activities

習慣了 Objective-C 的想法,在開發 Android 應用時,很自然把 Activity 當成 UIViewController 來使用。然而,有些時候需要在兩個 View 之間傳送數據。在 Android 上可使用 startActivityForResult 及 onActivityResult。
public class MainActivity extends Activity  {
     ...
     @Override
     private void userLogin()  {
          Intent intent = new Intent(this,LoginViewActivity.class);
          intent.putExtra("defaultUsername", "Pacess");
          intent.putExtra("defaultPassword", "Password");
          startActivityForResult(intent, 1);
     }

     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent intent)  {
          if (resultCode != RESULT_OK)  {return;}

          switch (requestCode)  {
               default:  return;

               case 1:  {
                    int userLevel = intent.getExtras().getInt("userLevel");
                    String sessionID = intent.getExtras().getString("sessionID");
               }  break;
          }
     }
}

public class LoginViewActivity extends Activity implements OnClickListener  {
     ...
     @Override
     public void onCreate(Bundle savedInstanceState)  {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.main);

          Intent intent = getIntent();
          String username = intent.getStringExtra("defaultUsername");
          String password = intent.getStringExtra("defaultPassword");
     }

     @Override
     public void onClick(View view)  {
          Intent intent = getIntent();
          intent.putExtra("userLevel", 1);
          intent.putExtra("sessionID", "s01234");

          setResult(RESULT_OK, intent);
          finish();
     }
}

2012年2月12日 星期日

關於 Android 的 onClick 寫法

About Android onClick
在看《The Android Developer's Cookbook》講解 Button.onClick 時,它的寫法是:
public class MainActivity extends Activity  {
     ...
     @Overrider
     public void onCreate(Bundle savedInstanceState)  {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.main);

          Button button = (Button)this.findViewById(R.id.button);
          button.setOnClickListener(new View.OnClickListener()  {
               public void onClick(View view)  {
                    doSomething();
               }
          });
     }
}
然而,我比較喜歡另一個寫法:
public class MainActivity extends Activity implements OnClickListener  {
     ...
     @Override
     public void onCreate(Bundle savedInstanceState)  {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.main);
        
          Button button = (Button)this.findViewById(R.id.button);
          button.setOnClickListener(this);
     }

     @Override
     public void onClick(View view)  {
          doSomething();
     }
}
這個寫法代碼的 Indent 層次亦較淺,看起來比較清楚明確。如果在同一個 Activity 內有多於一個 Button 時,亦能共用同一個 onClick函數。

2012年2月11日 星期六

情.尋朱古力

Catch Moses If You Can
半年前,針對 iPhone 及 Android 利用 HTML5 開發了不用下載 Apps 來即場玩遊戲的技術。2011 年 8 月時曾向 YSL 推銷這個尖端技術,我建議開發一個釣魚遊戲。嘉賓只需要即場打開瀏覽器便能進行遊戲,而且是在游泳池旁邊。沒錯,在游泳池旁釣虛擬魚!很吸引吧?她們對 BeyondZ 這項技術及遊戲都很感興趣。我自己很滿意這個構想與技術,亦很希望能成為香港第一家實現這個技術的公司。可惜的是,經過現場觀察及專業器材人員的意見,實現起來的工程浩大之餘,效果亦不如理想,最終只能放棄收場。

半年後的今天,路過尖沙咀海港城時,看到有公司已經把這種技術應用出來了。效果做得不錯,而且獎品有朱古力及 iPhone 4 套呢。

2012年2月10日 星期五

在 Mac OS X 上安裝 Eclipse 及 Android SDK

Install Eclipse on Mac OS X with Android SDK

為了開發 Android 項目,需要在我的 MacBook Air 內安裝 Eclipse。之前已經在公司的 iMac 上安裝好,但安裝過程已經不想記起了。跟 http://developer.android.com/sdk/installing.html 再做一次。

1. 到 http://www.eclipse.org/downloads/ 下載 Eclipse Classics 3.7.1
2. 到 http://developer.android.com/sdk/index.html 下載 Android SDK
3. 解壓 Eclipse 並拷到 Applications 內
4. 解壓 Android SDK 到 Eclipse 目錄下
5. 啟動 Eclipse。選 Help 中的 Install New Software,按 Add
6. 在 Name 格輸入 ADT Plugin
7. 在 Location 格輸入 https://dl-ssl.google.com/android/eclipse/
8. 按 OK
9. 點選 Developer Tools 內所有插件後點 Next
10. 按畫面指示接受所有條款
11. 安裝完成後重啟 Eclipse
12. 在 Android SDK 畫面選剛才安裝 SDK 的目錄
13. 選 Applications - eclipse - android-sdk-macosx - tools - android
14. Android SDK Manager 會自動選擇需要安裝的元件
15. 安裝所有元件

2012年2月9日 星期四

Linux 指令筆記(二)

關於公司的服務器設定,除了我就沒有其他人懂得去做。可是我自己對這方面沒有興趣,只有頂硬上來做。所以很多指令都記不清楚,要做記錄才行。

重啟 CentOS 6 的 Apache
/sbin/service httpd restart

重啟 QNAP TS-210 的 Apache
/etc/init.d/Qthttpd.sh restart

關閉 CentOS 6 的目錄清單功能
1. vi /etc/httpd/conf/httpd.conf
2. 找尋位於 Directory "/var/www/html" 下方的 Options Indexes
3. 把 Indexes 刪除
4. 儲存改動,並重啟 Apache

2012年2月8日 星期三

寫給有心轉行的人

時值轉工季節,收到的求職信亦多起來了。今天剛好約了一位應徵者面試。我選擇約見這位應徵者,原因是他的履歷中包含了兩個 iPhone App 的截圖。

每一位應徵者來到 BeyondZ 都需要花 30 分鐘去完成一份問卷。編程崗位如是、美術崗位如是。這份問卷的作用是篩選出態度及技術較好的人。30 分鐘過去了,我收到的問卷機乎空白。回答的都是風馬牛不相及的東西。這刻我充滿疑問,為何有 iPhone 應用開發經驗的人,連 Objective-C 的題目都無法回答?這個謎團將在面見時解開。

試題時間之後便是 30 分鐘的面見時間。我們會向應徵者提問各式各樣的問題,應徵者亦能發問關於 BeyondZ 的問題。在溝通的過程中,我瞭解到他完全沒有任何編程方面的底子,只是因為想轉行而報讀了為期 4 個月的 iPhone 開發課程。他在履歷中的作品是由幾位同學加上 Open Source 而製成。我頓時明白為何問卷的答案會是這個樣子。本來還對自學編程有一絲希望,畢竟我的編程也是自學而來。對於應徵者的求變態度,我是肯定的。可惜 BeyondZ 付不起由零開始去訓練新人成為編程人員所需的資源。我不禁反問,那家教育機構在想甚麼?難度他們相信 4 個月能把零編程經驗的人訓練成為有編程思考能力的人嗎?縱使應徵者交出了一個 iPhone 應用,只是因為他們把老師所教的整合而成,卻沒有編程方面的思維,根本無法編寫別的程式。校方亦沒有給他們後續的支援。校方的心態根本在賺他們的錢,而不是在教育他們。真是氣憤!香港的教育機構都忘記了教育的本義嗎?從應徵者口中得知沒有一個同學能順利轉行。我希望那位有緣的應徵者能繼續努力,打好編程的底子,這樣才有能力跨越未來的障礙。

2012年2月7日 星期二

Icon 0x0


最近在提交《中國神馬天氣》事宜中,不論是 App Store 還是 SmartMAD 都遇到阻滯,但總算跨過了。

在 iTunesConnect 建立新版本,把版本 2.00 錯誤地輸入了 1.20,之後惡夢來了。本來能簡單地改回 2.00,可是介面卻指沒有上傳屏幕截圖而無法更新。問題是那個介面只有圖示可上傳,而且截圖在 1.00 時已經存在,怎可能沒有截圖?原來這樣的改動,是需要把舊有截圖刪除後,重新上傳圖檔,即使上傳一模一樣的截圖。

好了,版本號搞好了,又到上傳 App 那邊出問題。指 Icon.png 大小是 0x0 像素,無法提交。翻查過無數次,圖檔的尺寸都是正常。最終的解決辦法是在 Xcode Build Settings 內的 Compress PNG Files 設定為 NO 才能成功上傳。

至於 SmartMAD 方面,指引中說明需要加入測試機的 UDID,可是找遍 SDK 文件都找不到。發電郵給他們,三天也沒有回覆。改用 MSN 查詢才得悉現在不用 UDID 了 >_<。好在事先已經提交一份,不過又遇到審批拒絕。拒絕歸拒絕,也在介面中給我原因好嗎?追問之下,原因已經電郵寄出,可是電郵卻是客戶的地址。我只好向客戶查詢。一問之下,拒絕的原因竟然是應用超過 20 天...。天呀!過了 20 天就拒絕,是甚麼道理?還好,得到 SmartMAD 親切員工的協助,終於可以重新上傳。

2012年2月6日 星期一

黑色星期一

今天是黑色星期一,至少對我來說是。

早上到 Super Sandwiches 買外賣早餐,點了奶茶。回到公司卻發現給的是咖啡糖。幸好公司還有一包白砂糖。

上周五跟一位應徵者面試,他卷答的很好,為人態度也很好。為免重滔上年的覆轍,當晚已經致電給他一個職位。他指要在周末深思熟慮。今天得到的回覆是另有他就。對於兩次物識到好人選,人選卻不選 BeyondZ,我感到失望。在失望之餘作出反思。如果人是物以類聚,哪是因為 BeyondZ 不夠好?還是我們也沒有讓對方看到最好的東西?對於想學習的人,BeyondZ 雖新,但核心開發團隊卻有 11 年市場經驗,19 年遊戲開發經驗,總算有點東西可學。問題出在哪裡?有一點可以肯定是 BeyondZ 網頁根本沒有提及以上內容。

另外,得知舊公司營運上遇到難題,同事們亦人心惶惶。希望他們能渡過難關。

2012年2月3日 星期五

Tapworthy

在《誠品》網購的第二批書籍到了,選擇了當中的《Tapworthy》來看。讀過頭兩章,感覺這本書十分好。它包含了很多 App 介面實戰前後的改動與原因。對於設計 App 介面有莫大的幫助。

2012年2月2日 星期四

iOS vs Android

最近成功取得一份開發項目,負責開發一個平板應用程式給客戶外判公司的出勤人員使用。希望能提升工作效率、減少攜帶文件的數目之餘,亦能讓管理階層即時查看工作進度。為了確切了解員工的工作內容,在報價之前,我親身到現場觀看她們工作時的情況。對於她們來說,小型的平板在體積及重量方面都比較合適,但 iPad 則能顯示更多美觀的內容,續航力及穩定性也較強。在訪問的過程中,出奇地發現她們竟然喜愛 Android OS 多於 iOS;還指 iOS 難於使用。相信是受 Android 迷上司所影響。

考慮過開發時間、系統反應、介面設計、重量、續航力...等因素之後,跟競爭者們一樣,決定開發 iOS 版本。憑著三年的 iOS 開發經驗,加上過往客戶的開發項目,我們最終勝出了。可是,外判公司同事卻反對使用 iOS。我不喜歡 Android,原因是介面的反應慢,而且難用。有朋友說我是蘋果迷。確切一點說,只是蘋果的設計實在太好,我才選擇蘋果產品。我不介意開發 Android,只是 SDK 一樣是慢,感覺不耐煩,做起上來會很火。現在正惡補 Android 的開發技巧,務求開發出穩定的作品。

2012年2月1日 星期三

決戰第三螢幕

花了兩個星期,把從誠品網購回來的《決戰第三螢幕》看完。雖然從這本書中沒有得到甚麼啟發或見解,但她引述了不少例子,在構思點子時有不錯的參考價值。

P.S.: 這本書在大眾書局可以找到。