顯示具有 98360666 蔡振揚 標籤的文章。 顯示所有文章
顯示具有 98360666 蔡振揚 標籤的文章。 顯示所有文章

2012年6月23日 星期六

期末專案報告書

遊戲名稱:閃躲子彈(Dodge Bullets)
這次期末專案的構想是來自以前在網路上玩到的一個小遊戲
遊戲畫面
 遊戲畫面2
碰到子彈後,出現的分數畫面
這次的期末專案要製作的是擴充實境的互動小遊戲,擴充實境就是將實物和虛擬物件做基本的互動,例如碰觸後消失、拖拉物件、將物件放大或縮小等等都是擴充實境,而這次我所做的專案將以上述的小遊戲做為範本來製作。
以下是我的遊戲介面
一開始進入的遊戲介面
 賤兔與追他的子彈
碰到賤兔後出現的結束視窗
原本的構想是玩家利用頭去控制中央的賤兔,閃躲從四面八方來的子彈,時間撐最久者獲勝,但這種普通的Webcam要找出人頭的話,必須使用Open CV來偵測,因此一開始我就遇上這道難關。後來想說改利用顏色偵測來讓賤兔跟著顏色差異的點移動,例如瀏海貼或胸針之類的物品來控制,但想想似乎又不太可行,因為我們所認知的點和電腦所認知的點差很多,我們想像的點在電腦的認知裡可能是一大堆點的集合,如下圖
偵測到紅筆的畫面
紅筆的UV值範圍(感謝李佳芳同學提供)
可以看到電腦找到的幾乎都是一大片的範圍,因此賤兔到底要跟著哪一個"點"移動就是一項很大的問題了。因此經過同學的建議之下,我決定利用控制項來控制賤兔的移動,但由於時間不足,最後還是沒能將其完成,這是第一個賤兔的移動方式所碰到的問題。
接著遇到的問題是如何將子彈亂數產生在畫面上,一開始修改老師的程式碼時是用很笨的方法,一個物件就宣告一個變數,但這樣我的子彈數量就會是固定的,而且程式碼會變的又臭又長,後來問了廖宗育同學之後,他交了我一個辦法,就是利用一個for迴圈,將子彈的編號全部跑過一次,如下:
for(iDragonBallID=0;iDragonBallID<=6;iDragonBallID++)
利用這行就能將所有的子彈都叫出來,但位置都要從新調整過,否則會全部疊在一起,而我是先將所有子彈以亂數rand()的方法出現在畫面上,如下       
 iObjectX1 = rand() % 590;
 iObjectY1 = rand() % 430;
要注意的是,如果要使用rand(),要先在最上面#include <time.h>才可以使用。
亂數子彈產生圖
但這種亂數產生的方式和我所要的追蹤賤兔效果不太一樣,但既然都做出來了,就將它變成另外一種模式了。而追蹤賤兔的演算法在詢問過老師之後,大致了解該怎麼運行,就是將追蹤者的座標扣掉被追蹤者的座標後,再利用
iDeltaX = 5;
iDeltaY = 5;
控制追蹤的位移大小,也就是速度,將追蹤者的位移大小設定的比被追蹤者大,感覺就會像是在追一樣,且還可以利用Track Bar元件讓玩家自己控制追蹤的速度,但這些想法卻都因為時間不足只好停留在我的腦袋裡了。

心得與反省:其實這次專案的製作過程很特別,不是在家裡一個人完成,而是像夏令營的方式,利用一個禮拜的時間在學校和同學老師討論過後,再將專案"生"出來。可惜的是, 我因為暑修課程時間剛好卡到,導致5天的夏令營我只到了3天,其中兩天還是下午才到,甚至還錯過最重要的第6次範例程式講解,縱使我全心全力想把專案做出來,但這種對程式一知半解的後果當然是淒慘無比,真的就像老師說的,我們都太天真以為只要熬夜個一兩天就能做出來。而且心裡其實還有很多想法想加進這次的專案,例如我本來還想要玩家邊玩時,一邊錄影,這樣在遊戲結束之後就可以看到剛剛玩遊戲時自己的糗樣,但卻因為會造成遊戲的停格而做罷,雖然這次我是屬於沒有完成的那一部分,但我所學到不比完成專案的同學們少,不管是在程式碼或是在自己的態度上都要做很大的修正,如果當下碰到不會的地方,真的要立刻問同學或老師,而不是坐在那邊看著螢幕一個下午還Debug不出來,否則在DEMO完後,就會像我一樣有很多的不甘心與遺憾,同時也謝謝老師在第四天颱風天還陪我們到晚上10點,雖然電腦關機了,但回家後被你教的部分真的很快就code出來了,這次未完成版的DEMO影片會在之後更新成完整版的,就在給你上過課之後。
以下的遊戲DEMO為未完成版,影片的後段為最上方小遊戲的DEMO,藉以讓大家知道我到底想做什麼遊戲。

遊戲DEMO未完成版


P.S在做專案的過程中有發現一個小技巧,若是你想在main menu元件上的按鍵加上熱鍵,只要在選擇按鍵後,如下圖
在左方的屬性設定中找一個ShortCut再輸入你要的熱鍵就可以了
因此在我的遊戲中才能按下鍵盤就立刻開始遊戲





2012年6月7日 星期四

期末專案構想

閃子彈

這次遊戲的靈感是來自於之前我用Processing所做出來成品,不同於之前的是,這次我會利用和視訊做連結利用人體來控制,若你以為是單純用手來控制那你就錯了,我會利用的部位是"頭"!
遊戲圖

















遊戲規則

利用頭控制中間的點,閃開從四面八方來的子彈,特別的是當你靜止不動,子彈也不會動,這樣設計的原因是可以讓玩家有時間找出路,以延長遊戲時間,而遊戲時間不限制,撐越久越好,遊戲結束後才會出現視窗顯示你撐了多久,如下圖







PS遊戲開始後會加入錄影功能,因此遊戲結束後可看見您剛才用"頭"拼命閃子彈的英姿

2012年6月4日 星期一

HW03

第三次的作業分成(a)(b)兩部分,a部分的相框真的是讓我吃足了苦頭,本來在上課時已經有做出來了,回家後改一改卻一直無法正確顯示,程式雖然能執行,但相框卻好像被視訊視窗覆蓋住一樣,如下圖
  














後來重新再做一次,步驟很簡單,程式碼幾乎跟龍珠的一樣,只要照著打再小做修改就可以完成這次的作業。
以下是回傳函數修改的範例
 ucDragonBallRGB[iDragonBallID][j-iObjectY1][i-iObjectX1][0] != 0
 這行是龍珠的四維RGB陣列,分別儲存[龍珠編號][龍珠圖片的長][龍珠圖片的寬][紅色像素]另外兩行以此類推,只要修改成相框適用的三維陣列image2RGB[j][i][0] != 0就可以了,除非有需要做一個以上的相框,否則就沒有編號必要,因此就可以把第一維的陣列刪去,YUV陣列也是比照辦理,而不用減iObjectXY1的原因是相框的大小原本就會調整成和視訊擷取視窗的大小相同。
接下來只要在按鈕中將事先使用 capGetVideoFormat 來取得視訊內容的高與寬,再把相框的位置設定為視訊擷取視窗的大小就可以了,如下。
iObjectWidth = iVideoWidth;

iObjectHeight = iVideoHeight;
再將影像元件中的色彩資料放到陣列中,這邊一樣只需要用三維陣列。
image2RGB[j][i][0] = (unsigned char) iB;
最後再利用部落格的公式將RGB轉換為YUV就大功告成了。
















(完成圖)


b部分相較起來就簡單的多,只要將畫面轉換為灰階就可以完成。
















做法有兩種,一種是直接修改ptrCapture[k+1]和ptrCapture[k+3]的值,灰階的值都是128,另一種做法是跟元件Color Dialog做連結,就可以自己選擇喜歡的顏色,連結的程式碼如下
if (ColorDialog1->Execute())
iR = GetRValue(ColorDialog1->Color);
iG = GetGValue(ColorDialog1->Color);
iB = GetBValue(ColorDialog1->Color);
再將RGB用公式轉換為YUV即可。

我在Coding的過程中有發生一個問題,和元件做好連結後,選的顏色卻和顯示出來的顏色不同,如下圖
















我原本選的顏色是黑色,但畫面上卻顯示為奇怪的綠色,經過debug後發現,原來是我ptrCapture[k+3]的值放錯,將iV放成了iY,改正後顏色也便正常了。

 












(黑白照)

















(靈異綠照)

















 (情色紅照)

HW02

這次的作業存在草稿已經很久了,藉這次機會一次把作業做完吧

Hw2是要我們錄影一段長約15秒的影片並且上傳,一開始以為會有點困難,但看過老師的部落格後,發現其實簡單的要命。
只要利用capCaptureSequence(hwndVideo);這條函式就可以順利錄影
(錄影中的畫面)

接下來在停止錄影的按鈕中我用了這3個函式        
capDriverDisconnect(hwndVideo);
第一個是停止錄影的函式
capFileSetCaptureFile(hwndVideo,"C:\Video001.avi");
ShowMessage("儲存成功!");
這兩個函式可以將錄影的檔案儲存成"Video001.avi"檔名放在這個專案的資料夾裡,若再儲存一次,則會用預設的檔名存在預設的位置中,也就是C:/Capture.AVI。
















最後用個小巧思跳出一個視窗告訴我已經儲存成功。
















以下就是錄影20秒的成果

P.S如果要把Youtube的影片嵌入到作業部落格的話,只要按下面分享鍵並再按嵌入,把下面的程式碼複製起來
























再按撰寫文章上面的HTML把程式碼塞進去就可以完成嵌入

2012年3月20日 星期二

HW01

第一次的作業是取得Webcam驅動程式的相關資訊
一開始是利用
"lblCapDriverName->Caption = szDeviceName;"

"lblCapDriverVersion->Caption = szDeviceVersion;"
兩行指令擷取視訊鏡頭的名字與版本且顯示在label元件的caption上



創造一個能顯示視訊畫面的Window


還可以修改視訊視窗大小


再來利用capDriverConnect(hwndVideo, dwDriverIndex);這段程式碼和視訊鏡頭連結並顯示畫面


將畫面調整成
Preview模式


最後再設定畫面楨數就可以開始視訊了,我將畫面楨數調整為每秒33張圖,這邊用的是capPreviewRate(hwndVideo, 33);這段程式碼,為什麼最後面的數字是33而不是30呢?問過老師後才知道原來後面的數字指的是每微秒多少張圖片,而1000微秒才等於1秒,所以若每秒要30張圖,則要1000/33才會接近30S/FPS


心得:本來以為要用程式來擷取視訊鏡頭的畫面是很難的一件事,沒想到每段程式碼都是短短的甚至只有一行,只要懂得呼叫視訊鏡頭的驅動程式,也就是VFW的函式庫,再懂得調整他的參數,其實一點都不難。