• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            白云哥

            身披半件長工衣,懷揣一顆地主心

             

            有關游戲開發的幾點體會

            1。還沒有真正的次世代網游,更別指望它能賺錢

            好幾次有朋友問我,次世代網游到底是什么東西

            我說,次世代網游就是模型至少上萬面,貼圖每張都起碼2048,法線圖,高光圖,多層蒙版一個都不能少;動態光滿天飄,還都是開著陰影的;體積云,體積霧,體積光,全都是立體的,酷;水面的反射,折射,波紋,浪花,樣樣精彩;超大型,超豪華場景,無限視野。就一個字:真實!哦不對,是兩個字,超真實。

            這樣的游戲用現在能配到的最好的機器,跑起來FPS也一定不允許超過15,否則那就不能叫次世代了。

            說白了,次世代就是你用當下的機器完全跑不起來的游戲,要么怎么能叫“次”世代呢。

            這樣的游戲,不是讓大多數玩家能玩得起來的,不是拿來賣錢的,就跟北京的商品房一樣,是給大家去追捧的。最多,會等Intel,Nvidia來給開發商返點利。嗯,我是說,大概可能估計會有的吧。

            次世代的游戲其實已有不少了,比如戰爭機器,比如戰神,比如彩虹六號……但次世代的網游還沒有。

            魔獸是次世代嗎?不是,完全不是。

            永恒之塔是次世代嗎?也不是,它也還差的遠。

            天下二,劍網三就差的更遠了。

            2。真正賺錢的游戲技術都很普通

            也許你會說,真正的次世代游戲都還沒有出來,你怎么就敢預言他們不能賺錢呢?

            是的,我不能,如果我有未卜先知的本領,那我早就不再需要靠做游戲來養活自己了。

            可是,我們卻能夠看到現在賺錢的游戲是什么樣的,這些是明明白白擺在那里的。

            魔獸世界:把這個游戲譽為國內3D游戲的教程書完全不為過,不過你承不承認,策劃也好,程序也好,美術也好,都從這里面學到了很多東西,模仿了很多東西,在目前國內的游戲里面,到處都能找到魔獸的影子。

            可是魔獸又用到了多神奇的技術?主角模型算上所有部件,3000多面,各部件的貼圖組合在一起,512大小,沒有法線沒有高光,絕大多數還都只是一層貼圖,偶爾有一些多層混合的。地形最簡單的分塊4層混合,最簡單的lightmap。水面,把鏡頭拉遠一點都能看出來貼圖形狀。天空盒,一個普通的m2模型。

            可是,魔獸所表現出來的整體場景效果,有哪一個游戲敢說超越呢?

            天龍八部,基于開源引擎Ogre制作的典范,也因為天龍八部鼓舞了國內好多使用Ogre開發的小團隊。

            不得不承認,Ogre所使用的技術是最樸實的,樸實到我這樣一個3D新手都能拿來修修改改,做點簡單的demo。

            同樣不得不承認,天龍的畫面效果確實很一般,2.5D的場景,固定的視角,輕盈的有些像紙片人的模型,可是,這并不妨礙他每月近兩億的收入。

            夢幻,大話,DNF,征途,傳奇……

            除了這些表面上能看到的技術以外,背后的技術是同樣的道理。

            早期的單服務器,分線方式,依然沿用在現在很多主流的游戲服務器端,并且依然是非常賺錢的項目。而類似于BigWorld的高深架構,事實上也并沒有成功的項目。如果把天下二的商業結果跟其他項目一比較的話。

            3。2D游戲比3D游戲賺錢

            我一樣很認同,未來的趨勢是3D,但是,那時候賺錢的3D項目不應該是現在這個樣子的。

            以國內游戲玩家的年齡及文化層次來看,要讓他們接受“右鍵旋轉朝向,左鍵旋轉視角”太過于困難,而即使是一個很熟悉3D操作模式的老玩家,進入到一個新的場景中,要分辨出“上北下南,左西右東”也是很煩人的一件事。

            如何盡可能的使用上3D的表現力,但又避免掉目前3D游戲的復雜操作模式,這要看未來誰先能走好這一步。

            但是,在3D真正應用起來之前,目前還是2D的天下。

            國內最賺錢的夢幻,還有大話系列,同樣最高在線超過200萬的DNF、征途,還有那不應被忘記了傳奇。

            不用歷數這些名字,文化部2009網游行業發展報告上統計的結果是,2D游戲收入占整個游戲行業收入達70%多。

            這也無怪乎騰迅到現在還在開發2D新項目,以3D起家的完美也要開2D項目,網易的大話到3代了還是2D,把unreal3應用得純熟的韓國人也同樣還在制作2D游戲。

            4。游戲開發并沒有什么高深的技術

            首先需要明確的一點,游戲項目是工程項目,不是科研項目。

            工程項目的目的是在有限的人力跟財力之下實現出既定的需求,而這個需求從前面的分析可以知道,要求并不高,所以,需求的實現過程也就并沒有多么高深。

            至少在我經歷過的項目里,沒有什么驚天地泣鬼神似的英雄人物,沒有創造出多么偉大的算法,我們所做的,只是使用現在的技術,現有的方法,拼合成一個軟件產品,一個融合了程序、美術、策劃勞動力的軟件產品。

            游戲開發的過程里,沒有,也不需要多厲害的技術高手,需要的僅僅只是有耐心,有責任心的普通技術人員。

            5。游戲的賣點在內容而不是畫面,但是畫面不夠好卻沒有機會去展現內容

            說這一點不是想強調到底是程序重要還是美術重要,或者是策劃更重要。這三者是缺一不可,而且哪一方弱都不行的。

            我想說的是,游戲真正留住玩家靠的還是內容。

            一樣是拿現在賺錢的游戲來說,夢幻沒有華麗的3D場景跟畫面,天龍有3D,但沒人會說那里面有華麗的場景,DNF的2D畫面還是非常粗糙的,唯獨好一點的魔獸,但他的市場表現在國內游戲里面來說,并不算太強。

            但是好的畫面在最開始的幾分鐘里卻是相當重要的,這就好比是長的帥的人能夠更吸引女孩子一樣。

            也許你能用你的魅力,你的錢袋子來打動女人,但如果你穿著一件破衣服,臉上只有著殘缺美,那你后面那些魅力,那些優點永遠沒有機會展示出來。游戲也是一樣。

            至少,你的新手村一定要做到富麗堂皇。

            6。游戲并不需要追求太多的游戲性,提供一個交流的平臺就行

            這是我最近的感悟。

            很多人玩游戲其實就是為了打發時間,我也問過很多沉迷于魔獸,沉迷于偷菜,沉迷于這些那些游戲的人,包括偶爾玩一下的,包括職業玩家,包括像我這樣,為了游戲而玩一下的人。

            游戲靠什么來留住人,在這一點上達成共識并不難,那就是里面的朋友。所以,給玩家營造一個更好的交流氛圍,交流環境,做到這一點了,游戲玩法可以要多俗有多俗。

            又在游戲里面,還有社區里面接觸了一些新生代的玩家們,似乎家族是一個很流行的東西。這其實可以看作是以前游戲里公會的升級版。在某個兒童游戲里,一個玩家帶著我去參觀他們的家族,帶我一個個拜見他們的官員。可我并沒有看到這些官員的頭銜,于是我問,你們這些官員是怎么來的?答曰:自己封的。

            就好像公園里的小道一樣,有時候,游人們會按照自己的喜好在草地上走出一些新的路來,這些路才是最合理的。

            為什么不順著這些玩家的路,把這些功能做的更強大一點呢。

            其實,把社群的功能做得更強大,更高級一點,那就像文明。或者做的更容易,更低齡一點,那就像過家家。不管是怎樣,應該在系統里就增強了交流的便利性,甚至可以在玩家一加入到游戲中,就開始引導著他加入社群。只有在社群里,他才能找到家的感覺,他才會因為朋友們而留下來。

            當然,怎么找對這條路,走好這條路,可不像寫下這幾行字這么簡單。

            posted @ 2010-04-14 00:07 白云哥 閱讀(748) | 評論 (3)編輯 收藏

            游戲小創業團隊最終的結局

              根據文化部2009年游戲行業發展白皮書上的數據,游戲運營失敗比例30%左右,游戲開發失敗比例50%左右,當然這個是指登記注冊了公司的,其實還有更多小團隊,小工作室,直接死在了起步的路上。

              單從這個比例來看,似乎創業的風險還是挺大的,每一個成功活下來的公司都踩著一個或幾個死去公司的尸體。可是,相比起大家常說的,十家創業公司一家成功,這個比例也不算高,而且,要是再看看成功的游戲公司獲得的回報,這個風險也就真的不大了。

             

              說游戲創業的風險不如說小創業團隊最終的結局。

              幾個志同道合的朋友走到一起,當然是想把事情做成功的,但是美好的期望不能保證全都能實現,不過,即使這個過程失敗了,也不一定全都失敗,除了最好的結局之外,也還是有其他幾種可能性的。

              從最好到最壞,大致有以下這么六種結局:

             

            1。游戲在預期時間內開發成功,并上線運營

              當然,這是最理想的結局,也是團隊組建初期給自己設定的目標。

              國家政策規定,運營網絡游戲的公司注冊資金必須一千萬以上,另外游戲的宣傳推廣費用一般都比較高,所以如果沒有足夠的資金實力,獨立運營的可能性不大。

              但是如果一切都進展順利,順利的將游戲開發完成,順利的找到了投資人,自己組建運營團隊其實是最好的選擇。因為都知道,運營才是創造利潤的地方。

             

            2。游戲開發成功,但不具備獨立運營的條件,轉做單純的開發商,把產品代理給別人運營

              如果很不幸的,沒有足夠的資金實力去運營自己的游戲,或者,創業伙伴們對自己運營游戲的把握都不大,也找不到一個放心的人來做,再或者,投資人不希望由開發團隊自己來運營。那么,把產品代理給專業的運營公司,獲得利潤分成,也是一個不錯的選擇。

              其實很多的創業小團隊最終選擇的都是這條路,更不用說參與18計劃,贏在巨人計劃的那些團隊了,本身就是屬于投資公司旗下的。

              運營畢竟不同于開發,游戲開發需要解決是技術問題與團隊內成員的合作問題,而運營面對的競爭卻有可能是血淋淋的,商場如戰場,沒有十足的把握與充分的資金支持,需要慎重對待。

              但是代理給別人最大的一個問題是收入將受制于人,首先這個分成比例可能會并不高,另外,如果游戲比較成功了,運營公司很可能會山寨一款同樣的游戲,并把用戶引入他自己的游戲,而避免與原來的開發商分成。這樣的例子在國內已不鮮見。

             

            3。游戲開發過程中遇到問題,團隊加入大公司,以工作室或獨立部門方式存在

              團隊最終加入大公司的情況,也并不一定是自己遇到了問題,也有可能是合作的需要。

              當創業團隊度過了最初的一段時間,游戲基本成形,開始大量的內容制作的時間,將可能需要招聘大量開發人員,這時,人員的管理不像以前幾個核心人員那樣,完全靠自覺了。而創業的伙伴們顯然對技術的把控比對人員的把控能力要強,也許,找一家成熟的公司,由他們來處理這些人事、財務方面的瑣事要容易得多。

              另外,也有可能投資人希望開發團隊能夠在自己身邊,能夠經常看到開發成果,能夠讓自己更放心。畢竟,投進去的錢那是真金白銀,花錢的人不在身邊,心里總會有些不大放心。

              還有可能就是團隊確實遇到了問題,比如資金方面的問題,找一家有實力的公司進行合作,整體并入大公司,成立一個新的部門,或者獨立工作室,繼續原來的工作。

              這種一般會與公司按比例分紅,但因為公司在開發期就在支持付工資,也承擔了風險,所以這個分紅比例不會比代理分紅高,但對于當初創業的核心開發人員來說,也絕對比在公司打工強。

             

            4。開發團隊整體被收購,繼續回到打工狀態

              這種結局就已經是不大愿意看到的了。

              當然,收購的方式也有多種,如果收購后在新公司成立部門,繼續進行原來項目的開發,那與上一種情況其實相差不多,但因為是收購,支付了費用,或者是以股權方式收購的,所以開發團隊的身份會有改變,說白了,就是現在是純粹的打工仔,不能再談更多的條件。

              不是,既然是被收購,那還是會有一點收入,讓初創人員有一定的回報。

             

            5。創業失敗,團隊整體加入新公司,在新的公司里再繼續開發新項目

              如果很不幸的,團隊最終因資金問題,或者合作問題,不得不結束創業的過程。

              這時也還是有可能繼續博一次,比如找一家有實力的大公司,以團隊方式加盟,可以帶上以前未完成的項目,或者不帶項目。當然,進入新公司后做什么項目,這很難再由自己決定了,另外團隊成員是否會被新公司拆散,這也不由自己控制。

              但總之,團隊加盟新公司,比單打獨斗要好。

              這只能算是不得已而為之的最后選擇了吧。

             

            6。團隊失敗,解散。各回各家,各找各媽。各自回到自己的打工狀態

              最壞的情況就是,創業過程失敗,最終團隊完全解散,或者還沒有完全解散的人也找不到合適的去處,這時只能是各回各家,各找各媽了。

              進入新一輪的打工狀態。

             

              每一個創業的團隊都是帶著對未來美好的憧憬開始的,并且在開始的時候也是認真在做的,但有人的地方就有江湖,也許合作的過程并不像想象的那么順暢,也許后來才發現投資人并不像之前承諾的那樣大方,也許,大家都錯誤的估計了自己的能力。

              但是,每一個勇敢走出第一步的團隊,每一個敢于走上創業這條路的個人都是英雄。

              至少,他們的人生有了這段經歷而變得精彩起來,至少,他們向成功的人生方向又邁出了一步。

              這比那些只會贊嘆某某游戲公司有多賺錢的人要強得多,這比那些只敢臨淵羨魚而不敢退而結網的人要可敬得多。

             

             

              或者,走向創業路上第一步的時候,可以問一問自己,兩年或者三年以后,希望自己能是個什么狀態。再問一問自己,如果失敗了,最壞將是個什么狀態。然后再回身看一看現在的自己,現在是怎樣一個狀態。如果今天換到行業里最好的公司,有同等條件下最好的待遇,兩年或三年后自己將可以是怎樣的狀態。

              或許,你會覺得,還是應該走出去試一試。

            posted @ 2010-04-08 00:51 白云哥 閱讀(411) | 評論 (0)編輯 收藏

            做成一款游戲有多難

              好游戲的標準很難定義,往往商業上的成功與品質上的優秀并不是完全一致的。那就不談好游戲,說說怎么做成一款游戲吧。

              做成的意思是指能夠成功上線運營,至少,保證能有個兩萬人同時在線吧,這樣,其實也就是做成了,一年還能有兩千多萬的收入,如果只是個小團隊開發,那足夠收回成本并讓開發人員獲得基本滿意的回報了。只是,她可能不算好游戲而已。

             

              游戲,雖不是軟件項目里最復雜的,但也屬于最復雜的軟件項目之一吧。倒不是說游戲程序寫起來有多難,而是游戲項目的需求變更太頻繁,游戲項目涉及到的人員配合太復雜。

              策劃的思路始終在變,朝三暮四是常事,繞個大圈又回到原點也是會有的;運營方隨時也會跟進,提出一些更有利于運營推廣的想法要求程序去實現。

              程序、策劃、美術,完全不搭邊的一群人,思維方式跟工作習慣存大巨大的差異,卻要在一起,把各自的工作揉合起來,成為最終的游戲產品。

              這一切,說起來似乎并不復雜,但在執行過程中一旦出現點小差錯,一般都是人為的一點小問題,后果基本上卻會是災難性的,之前所付出的努力都付之東流。

             

              但是我們又不能說這些需求的變更不應該有。正是因為大家都在為這項目而努力,都希望做好產品,才會有這樣的反復。有句話說的好,好游戲是改出來的。

              程序、策劃、美術的配合更是無法避免的。以前那種靠一兩個程序員單挑所有事情的時代已經成為歷史,即使今天某個人確實有這能力,原畫畫的超級棒,3D模型做的一流好,程序還寫的讓人刮目相看,可是,時間總是有限的。今天一個優秀的創意,如果等個十來年才能實現出來,那等到出來的那一天,也只能放進博物館了。

              而且,以目前的小型MMORPG項目來看,就算是效率比較高的創業小團隊,就算是在一些既有代碼的基礎上修改來完成項目,也至少需要20到30人年的開發時間。

             

              大概這些描述已經給你蒙上了一層悲觀的陰影,事實上做成一款游戲的風險其實并沒有想象的那么大。

              每一個在游戲公司呆過的人都清楚,游戲開發其實也就那點事。

              策劃的需求雖然總在變動,但到了今天,沒有哪個程序會硬編碼策劃們的邏輯需求。腳本的引入完全可以讓策劃們自己去配置、調試、驗證一些想法,如果能做的更進一步,提供GUI的工具讓他們更方便的去修改這些東西,那策劃們將會更少來麻煩程序。

              一個稱手的工具會讓美術人員以最高的效率去制作游戲內容。有時候你會發現,程序只需要花上半天時間為編輯器增加一個很小的功能,卻能讓美術減少幾天的工作量。而美術花上幾分鐘時間檢查所做的東西是否符合程序制定的規范,也能讓程序兄弟們少花那兩三天的時間去調試到底是什么原因讓程序崩潰。

             

              理想的情況下,程序給美術和策劃們制作好了工具,游戲的一切內容,都與程序再無關。程序所要關注的,是如何讓游戲運行的更順暢,如何讓策劃配置的自由度更高,如何讓這些工具更好用,如何最大可能的減輕美術與策劃的工作量。

              再加上這些相互的理解與支持,合作會變得越來越順暢,大家會更愿意為對方多付出那么一點點時間。我想,真正做到了這一點,在一些團隊里經常會聽到的美術、策劃與程序們相互之間的抱怨也就沒有了。

             

              當然,這樣的情況有些過于理想化,也許這些不一定都能做到。

              實際上你可能依然會在團隊里聽到程序對美術不遵守規范的抱怨,依然會聽到美術對工具不能完全滿足使用需求的指責,依然會有策劃過來要求程序反復修改或者實現某個功能。

              本來嘛,程序、策劃、美術工作性質的差異,思考問題方式的差異,使得他們很難完全一致,這時,我們需要有一兩個能夠顧全到大局的人,去化解這些問題。這一兩個人的以身作則,還有他們的感染力,也在帶動著團隊的合作向著良性的方向發展。

              很多時候,箭在弦上,只要有人輕撫一下,緊張局勢便可破解。很多時候,只是缺少這樣一兩個愿意主動站出來的人。每一個團隊都會有核心,所謂的核心,并不僅僅在于技術上的主導性,很多時候,他需要把他當作是團隊的領頭人,主動承擔起這些責任。

              只要找對了兩個這樣的人,我相信,小團隊要做到和諧融洽還是比較容易的。

             

              如果順利的話,團隊成員每天都能夠看到自己所做的東西一點一點在成型,一點一點在完善,這對團隊的士氣將是很大的鼓舞,每個人都看到未來將會是怎樣。

              小團隊相比大公司,優勢在于行動迅速,但劣勢在于抗風險能力較弱,更需要注意士氣的維持。所以,一個始終充滿激情的旗手就顯得很重要了。他不應該離大家很遠,更不能高高在上,他就是集體的一份子,每個人都能看到的一份子。

              中國的國情使得車庫文化不大可能產生,即使是對于小團隊來說,可是,在我們還在成長的過程中,每個人都應該坐在一張桌子上。

             

              我也始終認為,開發人員本身是并不復雜的,不管是程序、策劃還是美術。尤其是一些真正想做好事情的人,在大家認同的合作方式下,有共同的利益訴求,每一個理性人必將選擇通力合作,首先把項目做成功。

              每一個團隊成員,尤其是核心人員,只要心里面陽光一些,再陽光一些,沒有那些所謂的辦公室政治,沒有那些所謂的圈子圈套。小團隊十來號人,只有一個圈子,就是這個集體。那么,做事情其實是應該很順暢的。

             

              只要找對了人,做成一款游戲,其實并不難。

            posted @ 2010-04-05 02:35 白云哥 閱讀(430) | 評論 (1)編輯 收藏

            游戲到底有多賺錢

              游戲有多賺錢,看一下上市游戲公司的財報就知道了。http://tech.163.com/caibao,這里有國內互聯網公司財報匯總,摘錄09年第四季度幾家公司的游戲業務贏利情況,見下表:

            公司 游戲營收(萬元) 毛利潤(萬元) 毛利率
            盛大 133600 80200 60%
            完美 54000 52600 86.60%
            暢游 48250 28800 92%
            巨人 27300 23200 83.90%

             

              當然,這是占據了國內游戲行業收入一大半的幾家大公司,不過就算是小公司,只要能成功讓產品上線,利潤率也是一樣的。

             

              從上市公司的財報里可以看到,一般MMORPG的每活躍付費用戶平均每月貢獻收入大致在60元左右,有些游戲會高很多,有些稍低一些。也就是說,只要有2萬活躍付費用戶,以85%的利潤率來計算,扣除運營成本后的月利潤就能達到100萬。

             

              不過,目前游戲的類型基本上都是道具收費,這樣不是每個玩游戲的人都會掏錢。按照暢游財報中披露的信息,非付費用戶向付費用戶的轉化比例為18%,其他游戲的這個比例應該也不會相差太多,2 * 18%,月收入100萬就需要有11萬的活躍用戶。

             

              活躍用戶的統計方法一般是如果該賬號在一天內累計在線時間超過2小時,剛該玩家的活躍天數就加1,如果在線時間在半小時到2小時之間,則活躍天數加0.5,在線時間小于半小時的不算活躍天數。當然,這是每日活躍用戶數的統計方法。

             

              我們以2小時為單位,只要在每個時間單位內有11 / 12萬用戶在線,則就達到了10萬活躍用戶。也就是說,平均在線只要不到一萬人就達到了月入100萬的目標。

             

              這個數字基本上是可信的。可以再看一看完美的財報,完美Q4財報顯示,平均同時在線(ACU)為115.7萬人,網游收入為5.4億元,平均每月為1.8億,這樣每1萬平均在線貢獻的收入為 18000 / 115.7 = 155萬,這個數字比前面計算的不到一萬同時在線貢獻收入100萬還要高,這是因為完美的ARPU值比暢游高,為每月74元。

             

              所以,每當跟別人介紹我是做游戲時,別人都會感嘆一下,游戲啊,挺賺錢的,我也笑笑,確實是挺賺錢的。可是,如此賺錢的產品,開發人員的回報又有多少呢?

             

              再來看一下上市公司的財報。依然是暢游的,“非美國通用會計準則產品開發費用為510萬美元,環比增長5%,同比減少12%。環比增長主要是由于聘用了更多的游戲研發人員而導致員工薪酬與福利費用的增加。同比減少主要是由于公司管理層獎金方案的調整——之前授予的股權激勵在IPO后價值提高,因而公司減少其現金獎勵。”

              從這句話上可以看出來,這個研發費用不僅僅只是開發人員的工資,還包括了由于員工的相關福利,也包含了為員工所繳納的保險,公積金等費用。另外也還包括了獎金,以及股權獎勵等等。就這520萬,也只占到了營收的7%。

              在公司管理層解讀財報的時候有另外一句話,“截止到2009年12月31日,共有520位工程師。地面推廣團隊中正式員工有50人,另外還有臨時雇員大約還有600人。”不知道這510萬的研發費用是否包括了上面提到的地面推廣人員和臨時雇員,暫時認為其不包含吧,假定這些錢都花在了520位開發人員身上。

              另外也不知道這510萬是否包含研發相差的辦公室租金等費用,這個估計應該包含吧。

              公司為員工繳納的保險,公積金跟我們交的一樣,會占工資的20%多,辦公開支不大好算,另外福利也不好說,比如聚餐,組織出去玩等,這些不好統計,還不排除有一些無法統計到的灰色內容。簡單一點,就算這510萬有50%最后以money的形式發到了開發人員手上吧,包括每月固定工資與獎金。這樣,平均每人每月是1600美元。

              因為大部分公司的獎金都是以多發一個或者幾個月的工資形式來發放的,據說暢游每年相當于能發16個月工資,1600 * 12 / 16 = 1200美元。平均8000元的月薪,可能大部分人會感覺到自己并沒有這么多。當然,因為有一小部分人有股權的獎勵,他們的收入遠超過了8000 * 16,所謂20%的精英獲得了80%的利益 :) 其實也是差不多的。

             

              如此高利潤率的游戲產品,到頭來生產者們的回報卻也還是一樣。所以,再聽到人說游戲很賺錢時,有必要好好對其解釋一番 :) 游戲確實是賺錢,可錢并不在我們這些人的口袋里。

             

              再來看近期網易的大話二團隊集體離職,大明龍權開發團隊集體跳槽完美,還有華義成都差不多整個公司跳到騰訊,金山的團隊到網易去開發大唐,盛大的英雄年代團隊出走征途等等,這不能說是員工不夠忠誠,實在是利益分配的不合理。新的老板只要肯多拿出一個甚至半個百分點,分到開發人員的手中就是沉甸甸的誘惑了。

             

              而且還有另外一條很重要的因素,游戲的成功與否很大程度上來自于那幾個開發人員。縱觀國內游戲廠商,基本上都是只靠著開發團隊做的一款游戲就撐起了整個公司,讓公司擠進二線、一線游戲廠商行列,甚至靠著這一款游戲去賺美國股民的錢。當然這種成功也有很大的偶然性。

              就像一個正在創業路上的朋友所說,游戲是能讓你迅速從楊白勞變成黃世仁的最好選擇。當前,前提是你不是在為別人打工。

            posted @ 2010-04-04 01:18 白云哥 閱讀(4212) | 評論 (6)編輯 收藏

            Ogre終于開始改進其對地形渲染的支持

              Ogre正在開發中的版本,1.7版,引入了新的Terrain Component與Paging Component,Ogre終于開始對地形渲染進行官方的支持了。Ogre官方論壇上sinbad也提到了這個新的Terrain Component的特性及目前的進展,不過他自己也說,雖然他很希望1.7版能在今年發布,但是結果卻也很難預測 :(

              曾幾何時,在Ogre中尋求更加完善的地形渲染支持是多少人都在做的事,Ogre源代碼庫中的Terrain Scene Mananger只能實現最基本的高度圖渲染功能,搭配一張普通texture和一張detail texture,根本無法實現出我們想要的真實地形效果。于是,Addon論壇上不少人也開始了為Ogre擴展地形渲染支持的工作,比較有名的是PLSM,這部分代碼經過不少的修改,之后也被納入了Ogre的Octree Scene Manager代碼庫,不過其依然還是相當的簡陋。另外還有一個就是Myrddin,這里是論壇上的介紹頁面,在1.7版出來之前,這應該是最好的地形渲染選擇了。

             

              所以,之前使用Ogre的游戲要么自己來寫地形渲染這一塊,要么干脆就不要地形,一切皆mesh,比如最近挺火的火炬之光(Torchlight)。

              其實,一切皆Mesh也并不是不可以,相反,用Mesh能夠表現出更加細膩真實的效果,比如場景本來就是由大師的地下城或者陡峭的山脈構成時。就像前幾年玩過的“地牢圍攻2”。當然,全Mesh場景的問題也是很明顯的,其需要渲染的面數太多,所以,這樣的游戲也只好采用固定的斜視角,并且打上很近的霧來減少需要渲染的對象數,就如同前面提到過的兩個例子,“地牢圍攻”和“火炬之光”那樣。

             

              從OgreSVN上checkout出來代碼,簡單看了下相關的代碼注釋,其特性還是挺讓人期待的。

              首先,地形資源有了自己的文件格式,不再是以前的terrain.cfg和terrain.png或terrain.raw了,

              另外,terrain和paging以Component的形式實現,不再依賴于Scene Manager的實現。

              然后,貼圖的混合也已基本實現。目前地形渲染的一個pass最多支持6層貼圖,地形渲染常用的normal map, light map, colour map,specular map都已經支持,從其提供的幾張試驗用的截圖來看,多層混合、法線以及高光實現的都已經沒有問題了。

              另外還有一個額外的特性是支持運行時對地形的修改,并能在后臺線程中對地形數據進行加載和保存。

              雖然這個特性在目前的游戲中都不需要,因為地形編輯一般是在場景制作的時候完成,也就是由美術人員在制作地圖時就已確定好了,在游戲中只需要將地圖文件讀出來并渲染到屏幕,游戲進行過程中也不允許對地形數據進行任何破壞和修改。

              其實,從技術上來說,這并不是絕對的限制,地形及場景完全是可以破壞的,可以重建的,比如,可以讓一顆炸彈落過的地方永久的留下一個彈坑,讓火燒過的地方只留下一片殘骸,樹木及雜草都被燒毀,另外,城鎮與村落也不需要是美術預先編輯好的,玩家完全可以在一塊空曠的地方建起一座城來,當然也可以把別人的一座城燒毀掉,等等。

              只是,當地形及場景改變后服務器需要同步大量的數據給客戶端,并且,如何保證這些數據的完整性和一致性。這最主要的還是受限于網速的原因,如果網絡速度足夠快,我們完全可以把游戲做成瘦客戶端,甚至無客戶端,就像現在的flash web game一樣,客戶端總是去服務器上取最新的場景數據,這樣就不再有問題了。

              但是,另外一個問題可能會稍麻煩一些。當地形和場景改變后,服務器端的AI相關數據會受到很大的影響,比如尋路數據,不論是用nav mesh還是用waypoint,這些數據都要重新構造,而這個構造過程一般來說將會是漫長的,但是地形的重建卻可能會是相當頻繁的。。。還有AI對象的出生數據,等等,這都需要我們花一些精力去思考。

             

              當然,一切能夠想得到的問題都不會是大問題,總會有方法去解決它們。今天覺得不可能做到的事,隨著明天硬件環境的提升,新的算法的實現,這也將成為我們在游戲中能夠親眼看到的事實。

            posted @ 2009-11-26 15:27 白云哥 閱讀(2988) | 評論 (3)編輯 收藏

            Android 2.0 SDK發布

              最近在我的關注領域內的消息還真不少

              1。Unity2.6發布,并且將indie版免費。(當然,之前也有30天的試用版)Unity的制作人說過一句話:如果做web,2D就用flash,3D就用Unity。雖然這是一句宣傳詞,不過,Unity也確實挺不錯。

              2。Android 2.0 SDK發布,可惡的GFW,好在Android Setup Tools非常體諒我們這些墻里的人,升級工具里有個選項叫https,當然,這是通過犧牲速度來換取的。真不明白GFW封堵sourceforge, developer.android這樣的開發者網站是何用意,怕國外的先進技術毒害了我們這群求知的人們?

              另外,摩托的支持Android 2.0的新手機也即將發布,售價是誘人的199刀,不知道國內有沒有渠道能夠買到。當然,這199刀不會是跟之前的iPhone售價一樣吧。

              3。一款叫做Torchlight的游戲發布,其制作人以前在北方暴雪呆過,所以,這游戲怎么玩怎么像是暗黑卡通版。另外,據說其網絡版在一年半后發布,國內由完美時空代理。不過,我更加關注的是它使用Ogre渲染引擎。

              4。Qt4.6正式發布,新特性確實添加的很快,想拿它來做工具試試。

            posted @ 2009-10-30 00:07 白云哥 閱讀(183) | 評論 (0)編輯 收藏

            用cl.exe生成對象內存布局來學習虛函數

              這篇文章所使用的方法來源于 CuteQt博客 上的一篇文章:http://www.cuteqt.com/blog/?p=868 

             

              生成對象內存布局所使用的方法來自于vc8編譯器一個未公開的參數,即 /d1 reportSingleClassLayoutXXX或者 /d1 reportAllClassLayout,MSDN上關于這個的簡單說明及示例可以見這里:http://blogs.msdn.com/vcblog/archive/2007/05/17/diagnosing-hidden-odr-violations-in-visual-c-and-fixing-lnk2022.aspx

              一般來說用reportSingleClassLayout,因為reportAllClassLayout會生成許多中間類的結果,干擾我們的分析。

             

              按照上面博客中介紹的方法,一步步來跟蹤各種虛函數使用情況下的對象內存布局,可以很直觀的看到虛函數是怎樣分布的,各種繼承情況下虛函數是又是怎樣生成的,等等。

             

              一點簡單的總結:

              1。以前常說的,因為虛函數的使用,使得類多了一個vtable指針,大小增加了4字節,其實是不完全正確的。因為一個class內可能會有多個虛表的存在,比如當有多個帶虛函數的父類時。

              2。多個虛函數在虛表里的順序由其定義順序決定。如果是從多個父類派生來的,則這多個虛表的順序由父類的申明順序而定。

              3。多繼承情況下的同名虛函數處理使用了一種叫做thunk的技術,這樣通過不同的基類調用同名的虛函數時,都會調用到相同的函數體內。

              4。虛基類的實現多了一個vbi表,記錄的是虛基類中的虛函數表地址信息。同時在派生類中計算好了到這個vbi表的偏移,這樣虛基類里的虛函數在菱形繼承關系的派生類中就只有了一份實現。

              5。使用的時候其實不必要意這些細節問題,編譯器在生成函數調用代碼時已經幫我們處理好了,即這個函數在哪個虛表中,是第幾個虛函數,最終也就是要做多少個字節的偏移。

            posted @ 2009-10-13 22:13 白云哥 閱讀(357) | 評論 (0)編輯 收藏

            QT Everywhere

             

                不得不承認,QT在Nokia的懷抱中越活越滋潤,如長成的少女一般越來越漂亮。

             

                程序速度越來越快,Nokia QT推出的第一個版本運行速度比原來快了近一半,而即將推出的4.6版還將把圖形渲染底層重寫,以進一步提升運行速度。

                平臺支持范圍也越來越廣:S60手機平臺的支持,當然,這是Nokia收購QT的最主要目標吧,最新的Windows7和Max OS X以及更多的Unix平臺的支持,讓QT無孔不入。

                完全獨立的IDE:QT Creator,雖然說用慣了VS IDE之后在剛接觸這個Creator時有很多的不習慣,但QT要做到更大可能的跨平臺支持,有一個統一的IDE和編譯環境也是必要的,另外,Nokia也提供了Addons以以VS或者Eclipse IDE集成。并且,在新的1.3版Creator上還將使用一個叫做jom的程序來代替VS默認使用的nmake程序,最終應該將會完全擺脫VS吧。

                使用硬件加速的OpenVG實現以達到高速的矢量圖形繪制,Nokia打算無視Flash的存在?當然,這與“實現自己的Creator”,“使用自己的jom代替nmake”一樣,所有的技術都要自己來DIY。或許,只有把所有的技術都掌握在自己手上才是最可靠的。

                對觸控系統的支持是未來所有操作系統都必須要具備的,包括Windows7,包括iPhone,包括Android,QT4.6在這一塊上也不甘落后。

             

                QT的野心從其博客上的一篇文章似乎能夠看出點端倪。做游戲,這個跟QT以前所專注的GUI開發八桿子也打不著的領域也要囊括進來,那還有什么東西的出現是你所不敢想象的呢?

             

                也許,這就是未來的軟件開發大平臺。

                或者,正如QT的一個博客站名一樣:QT Everywhere!

            posted @ 2009-09-30 21:12 白云哥 閱讀(3206) | 評論 (5)編輯 收藏

            FXComposer中的Annotations與Semantics

            DXSAS : DirectX Standard Annotations and Semantics,DirectX引入的一項在Shader代碼與應用程序之間進行數據綁定的規范,當出到0.8時被廣泛用于各種應用程序中,后來從MS的產品線中神秘消失,有關DXSAS的規范文檔被從MSDN中移除,只留下幾頁引用說明。。。

             

            簡單來說,當我們在DX中使用Shader的時候,我們會使用一個常量表來設置各種參數值,其中最重要的當屬世界變換矩陣了。這在用DX寫游戲程序時沒有問題,但是在其他一些Shader編輯工具中問題就出來了,如何設置這些變量?當然,每種工具可以提供自己的方法,比如現在Max,Maya都提供了自己的方法在Shader中綁定世界變換矩陣,但問題是每種工具提供的方法都不一樣,這樣寫出來的Shader文件就麻煩了。。。

             

            于是,MS這時站出來,提出了一個標準:DXSAS。這是目前還能找到的DXSAS的一段描述:

            Standard annotations and semantics (DXSAS) provide a method of using shaders in a standard way that enables shaders to be used with tools, applications, and game engines. DXSAS defines a set of semantics and annotations that are attached to host application values and effect parameters for the purpose of sharing effects.

            地址:http://msdn.microsoft.com/en-us/library/bb173004(VS.85).aspx

             

            有標準是好事,而且我們也能看到,大量的Shader工具及游戲引擎也使用到了SAS,比如FXComposer,比如RenderMonkey,比如CryEngine。。。當然,各工具可能對SAS都會有自己的擴展,但大部分還都是按照標準來的。

             

            可是,為什么MS突然就將這標準移除了。。。而且,沒有任何理由的。。。以至于FXComposer1.8版本以前的文檔中附帶的SAS描述章節也跟著一并刪除,我在FXComposer2.5上找遍了整個手冊也沒找到這個 WorldViewProjection 從哪里來,翻遍了MSDN上HLSL有關的內容也沒有看到這幾個關鍵字。無奈Google之,原來受此困惑的人還真不少。

             

            好在,Nvidia推出了一份新的文檔,描述SAS的使用方法,或許Nvidia也很困惑,“which came from DirectX 9, and are sometimes hard to find”。。。但是新的FXComposer手冊中對這些只字未提卻是我仍然很困惑的,對于像我這樣的一個新手來說,完全不可能知道這些東西是如何來的,如何去找這些Semantics的定義。

             

            Nvidia網站上的SAS說明文檔:http://developer.nvidia.com/object/using_sas.html

             

            以及FXComposor官方論壇上置頂的關于SAS文檔的說明貼,當時我竟然沒看到這個置頂貼 :(  http://developer.nvidia.com/forums/index.php?showtopic=1358

             

            其他人提出的一些相關疑問:

            http://developer.nvidia.com/forums/index.php?showtopic=750

            http://developer.nvidia.com/forums/index.php?showtopic=31

            http://developer.nvidia.com/forums/index.php?showtopic=1061

            http://developer.nvidia.com/forums/index.php?showtopic=1347

            http://developer.nvidia.com/forums/index.php?showtopic=1394

             

            留下這些記錄,也許有跟我一樣的初哥們,少點困惑 :)

            posted @ 2009-09-28 00:02 白云哥 閱讀(1903) | 評論 (3)編輯 收藏

            Structuring the Main Loop

                看到CppBlog上翻譯的一篇游戲主循環,想起之前也看到過一篇類似的文章,因為筆記本上第一篇記錄就是這個主循環的簡短翻譯,對比了一下,發現這篇文章對實現細節的描述更多一些,也發上來與大家共享。

                這篇文章最早是出現在flipcode的論壇上,地址在這里,后來有人整理了一下,并添加了更多的描述,也就是下面的內容。原貼地址在這里

                文章中關于網絡的描述是指局域網環境下的情況,另外這個主循環也沒有考慮到windows環境下與Windows Message Loop的結合,如果是應用在windows環境下,可以再參考下這里,把兩者結合基本上就差不多了。

                翻譯并未嚴格遵照原文,為了讀起來流暢,很多句子都是按照我個人的理解來描述。

             

            This article is about a way of structuring a game's main loop. It includes techniques for handling view drawing with interpolation for smooth animation matched to the frame-rate with fixed-step game logic updating for deterministic game logic. A lot of this is still pretty much a work-in-progress as I muddle my way through, learning better ways of doing things or new tricks to add to my bag, so please bear with me.

            這篇文章描述的是如何組織游戲主循環的一種方法。內容包括了如何處理平滑的動畫繪制,并且能夠根據當前幀率做正確的動畫插值,另外還要保證固定的游戲邏輯更新幀率,以確保游戲邏輯的計算結果是確定的。

            這些內容的實現有很多都還在進行中,我也在不斷地學習更好的方法,以及將一些新的技巧添加進來,所以,希望能夠給我一些耐心與寬容。

            The heart of a game, any game, is the game loop. This is where the action takes place, where the guns fire and the fireball spells fly. In some games, the concept of the game loop may be diffused among different components or game states, which implement their own version of the game loop to be exectued at the proper time, but the idea is still there.

            任何游戲的核心都是游戲主循環。游戲的動作執行、子彈的射擊以及火球魔法的飛行等等都是在這里實現。

            在一些游戲中,你可能會找不到一個唯一的游戲主循環,取而代之的是,你會在一些組件及狀態機中找到各個不同版本的主循環。

            其實這個原理也是一樣的,只不過是把原來的一個主循環拆分成了多個,這樣可以控制游戲在不同的時間及狀態下執行不同的循環過程。

             

            The game loop is just that: a loop. It is a repeating sequence of steps or actions which are executed in a timely and (hopefully) efficient manner, parceling out CPU time to all of the myriad tasks the game engine is required to perform: logic, physics, animation, rendering, handling of input. It must be constructed in a deterministic, predictable fashion so as to give expected behavior on a wide array of hardware configurations. Classic failures in this regard include old pre-Pentium DOS-based games that were synchronized to run well on old hardware, but which did not have the controls in place to control the speed on newer hardware, and consequently ran so rapidly that they became unplayable on new hardware. With such a broad diversity of hardware as now exists, there must be tighter controls on the game loop to keep it running at a consistent speed, while still taking advantage of more powerful hardware to render smoother animation at higher framerates.

            簡單來說,游戲主循環就是一個循環過程。

            在這個不斷重復執行的過程中,我們需要把CPU時間按照一定的規則分配到不同的任務上,這些任務包括:邏輯、物理、動畫、渲染、輸入處理等等。

            游戲的主循環必須保證是以一種確定的、可預測的方式來執行,這樣才能在大量的不同硬件配置環境下都得到我們所期望的相同行為。

            以前的DOS游戲曾經出現過這樣的問題,它們在舊的硬件上運行的很好,但是放到新的硬件上以后就失去控制了,游戲的運行速度變的如此之快,以至于根本無法去玩它。

            現在市場上存在這么多的硬件種類,所以就必須要緊緊地控制住游戲的主循環,保證他們以一個固定的速度運行,但同時又能獲得這些強大的硬件所帶來的好處:以盡可能高的幀率來渲染出更平滑的動畫。

             

            Older games frequently tied the rendering of the view very closely to the game loop, drawing the view exactly once per logic update and waiting for a signal from the display system indicating a vertical retrace period, when the electron gun in the CRT monitor was resetting after drawing the screen. This synchronized loops to a predictable rate based on the refresh rate of the monitor, but with the advent of customizable refresh settings this leads again to unpredictable loop behavior. Retrace synchronization is still useful, especially to avoid visual artifacts when rendering the view, but is less useful as a means for synchronizing the game logic updating, which may require finer control.

            以前的游戲經常將渲染過程與游戲循環緊密地綁在一起,首先執行一次邏輯更新,然后繪制畫面,接著等待顯示系統觸發一個垂直同步信號,之后就是下一輪循環周期:邏輯更新、渲染、等待……周而復始。

            這種同步的循環方法在顯示器的刷新率可預測的情況下是有效的,但是當可以自定義刷新率以后,這種行為又變得不可預測了。

            垂直同步仍然是有用的,尤其是在避免畫面的渲染出現撕裂的情況下,但是用來同步游戲的邏輯更新就沒多大用了,這時可能需要更好的控制方法。

             

            The trick, then, is to separate game logic from rendering, and perform them in two separate sub-systems only marginally tied to each other. The game logic updates at it's own pace, and the rendering code draws the screen as fast as it possibly with the most accurate, up-to-date data the logic component can provide.

            這種方法就是將游戲邏輯更新與屏幕渲染過程分離開,將他們放到兩個分離的子系統中去處理,只是在需要的時候才與另一個打交道。

            游戲的邏輯更新嚴格按照計劃來執行,但是屏幕渲染則以它所能達到的最大速率來進行。

             

            The system I am accustomed to using is based on a Tip of the Day ( http://www.flipcode.com/cgi-bin/msg.cgi?showThread=Tip-MainLoopTimeSteps&forum=totd&id=-1 ) posted to http://www.flipcode.com by Javier Arevalo. It implements a loop wherein the game logic is set to update a fixed number of times per second, while the rendering code is allowed to draw as rapidly as possible, using interpolation to smooth the transition from one visual frame to the next.

            這里描述的方法基于Javier Arevalo發表在flipcode Tip of the Day 上的代碼來實現。

            在這個游戲主循環里,游戲邏輯更新被設置為每秒執行固定次數,但同時渲染代碼被允許執行盡可能多次,并且還使用了插值來使得兩個渲染幀之間的動畫變化盡可能的平滑。

             

            Briefly, here is the code. I will then attempt in my own crude fashion to explain the workings, though I suggest you check out the original tip at the above link to read Javier's explanation, as well as the forum posts accompanying it which offer up insights and suggestions on how the performance of the loop may be improved.

            閑話少說,下面首先是代碼,然后我會簡單的按我的方式描述一下代碼的工作原理,同時我建議你閱讀一下上面鏈接地址所給出的內容,其中有Javier的解釋,并且論壇上的回貼也有一些不錯的內容,包括別人的評論和一些關于如何提高效率的建議。

            (注:flipcode論壇早就已經關閉,上面的鏈接地址已經失效,flipcode上只保留有一些優秀內容的archives在這里能找到這篇原文,其中包括Javier的解釋)

             

            time0 = getTickCount();
            do
            {
              time1 = getTickCount();
              frameTime = 0;
              int numLoops = 0;
            
              while ((time1 - time0) > TICK_TIME && numLoops < MAX_LOOPS)
              {
                GameTickRun();
                time0 += TICK_TIME;
                frameTime += TICK_TIME;
                numLoops++;
              }
              IndependentTickRun(frameTime);
            
              // If playing solo and game logic takes way too long, discard pending time.
              if (!bNetworkGame && (time1 - time0) > TICK_TIME)
                time0 = time1 - TICK_TIME;
            
              if (canRender)
              {
                // Account for numLoops overflow causing percent > 1.
                float percentWithinTick = Min(1.f, float(time1 - time0)/TICK_TIME);
                GameDrawWithInterpolation(percentWithinTick);
              }
            }
            while (!bGameDone);
             

            Structurally, the loop is very simple. The above snippet of code can encapsulate the entire workings of your game.

            從結構上來說,這個主循環非常簡單。上面的代碼片段基本上能夠囊括你的游戲的整個工作過程。

             

            First of all, the main loop portion is embodied as the do{} while(!bGameDone); block. This causes the loop to run endlessly, until some game condition indicates that it is finished and it is time to exit the program, at which point the loop ends and the game can be properly shut down. Each time through the loop, we perform game logic updates, input updating and handling, and rendering. Now, for a breakdown of the sections of the loop.

            首先,主循環的執行過程被包在do…while循環塊中,這使得游戲主循環將永不結束地運行,直到游戲明確地被告知需要結束并且退出程序時為止。

            在每次進入循環的時候,我們會執行游戲邏輯的更新,輸入更新與處理,還有渲染。接下來,把循環分為幾個片段來描述。

             

            time1 = getTickCount();
            frameTime = 0;
            int numLoops = 0;
            
            while ((time1 - time0) > TICK_TIME && numLoops < MAX_LOOPS)
            {
                GameTickRun();
                time0 += TICK_TIME;
                frameTime += TICK_TIME;
                numLoops++;
            }
             

            This portion is the game logic update sequence that forces the game logic (physics updates, object motion, animation cycling, etc...) to update a set number of times per second. This rate is controlled by the TICK_TIME constant, which specifies the number of milliseconds the logic update is supposed to represent in real time. It probably won't take that long to perform, in which case the update won't be performed again until enough time has passed. For example, with TICK_TIME=40, each logic represents 40 milliseconds, thus forcing the code to update game objects at a rate of 25 times per second.

            這部分代碼處理游戲邏輯的更新,并且強制要求游戲邏輯每秒執行固定次數。

            游戲的邏輯處理包括物理更新、對象行為、動畫循環等等。更新速率通過TICK_TIME常量指定,其含義為兩次邏輯更新的時間間隔,即經過TICK_TIME后應該再次進行更新,而不是說一次邏輯更新要持續這么長時間。

            例如,TICK_TIME = 40,其含義為每次游戲邏輯更新后表現40毫秒,這將使得每秒游戲對象會被更新25次。

             

            The logic is encapsulated in it's own while loop. It is possible during a given frame that game logic will take too long. If a logic update cycle goes overtime, we can delay rendering for a bit to give ourselves a little extra time to catch up. The while loop will continue to process game logic updates until we are no longer overtime, at which point we can go ahead and continue on with drawing the view. This is good for handling the occasional burp in logic updating, smoothing out the updates and keeping them consistent and deterministic; but in the case that the logic repeatedly goes overtime, it is possible to accumulate more time-debt than the loop can handle. Thus, the MAX_LOOPS constant is in place to dictate a maximum number of times the loop can repeat to try to catch up. It will force the loop to dump out periodically to handle other tasks such as input handling and rendering. A loop that is constantly running at the MAX_LOOPS limit runs like hell and is about as responsive as a tractor with four flat tires, but at least it keeps the loop operating, allowing the user to pass input to terminate the program. Without the MAX_LOOPS failsafe, it would be entirely possible for a slow computer to lock up with no way to exit as it chokes on the loop, trying to catch up but getting further and further behind.

            邏輯更新的代碼被包在他自己的while循環中。

            可能在某一幀里游戲邏輯的處理時間會非常長,甚至會超時,這時我們可以稍稍暫停一下屏幕的渲染,使得游戲邏輯更新能夠在這段時間里趕上來。

            這個while循環就是用來讓游戲邏輯繼續更新,直到我們不再超時,之后我們繼續游戲的主循環并且進行屏幕渲染。這可以很好地處理突發的邏輯更新超時,使得我們的更新更加平滑,并保證邏輯的一致性和可預測性。

            但是如果游戲邏輯處理持續地超時,甚至使得我們的主循環無法處理過來,這時MAX_LOOPS將會起到作用,他將使游戲控制權從邏輯更新中跳出來,去執行如輸入處理和屏幕渲染等其他任務。

            MAX_LOOP常量限制了這里的while循環用來追趕邏輯處理時間時最多能重復的次數。這樣當游戲真的出現完全無法處理完邏輯更新的時候,用戶也有機會結束程序。

            如果沒有MAX_LOOP的檢測,很有可能會出現一臺很慢的電腦試圖追上邏輯處理時間,但是卻越追越遠,而又沒有機會退出這個過程,最后陷在了這個死循環中……

             

            IndependentTickRun(frameTime);
             

            This section is where input is gathered, events are pumped from the event queue, interface elements such as life bars are updated, and so forth. Javier allows for passing how much time the logic updates took, which can be used for updating on-screen clock or timer displays and the like if necessary. I've never found occasion to use it, but I regularly pass it anyway on the off-chance I'll need it someday. frameTime basically gives the amount of time that was spent in the logic loop performing updates.

            這部分代碼用來處理用戶輸入的捕獲,事件會從事件隊列中被取出來處理,界面元素,如血條等,會在這里被更新,還有其他類似的處理。

            Javier在這里留了一個frameTime參數,用來指明邏輯更新所花的時間。可以用這個值來更新游戲屏幕上的時鐘或定時器等類似信息。

            雖然我目前還沒有找到機會用它,但我還是習慣性地把它帶上了,也許某天我會需要。

             

            In order for the game loop to run predictably, you should not modify anything in this step that will affect the game logic. This portion of the loop does not run at a predictable rate, so changes made here can throw off the timing. Only things that are not time-critical should be updated here.

            為了使游戲循環的運行是可預測的,你不應該在這里修改任何可能影響游戲邏輯的東西,因為此部分在游戲主循環中的執行次數是不可預測的,所以在這里只能做一些時間無關的更新。

             

            // If playing solo and game logic takes way too long, discard pending time.
            if (!bNetworkGame && (time1 - time0) > TICK_TIME) time0 = time1 - TICK_TIME;
             

            This is where we can shave off our time debt if MAX_LOOPS causes us to dump out of the logic loop, and get things square again--as long as we are not running in a network game. If it is a single-player game, the occasional error in the timing of the game is not that big of a deal, so sometimes it might be simpler when the game logic overruns it's alloted time to just discard the extra time debt and start fresh. Technically, this makes the game "fall behind" where it should be in real time, but in a single player game this has no real effect. In a network game, however, all computers must be kept in synchronization, so we can't just cavalierly discard the pending time. Instead, it sticks around until the next time we enter the logic update loop, where the loop has to repeat itself that many more times to try to catch up. If the time burp is an isolated instance, this is no big deal, as with one or two cycle overruns the loop can catch up. But, again, if the logic is consistently running overtime, the performance of the game will be poor and will lag farther and farther behind. In a networked game, you might want to check for repeated bad performance and logic loop overruns here, to pinpoint slow computers that may be bogging the game down and possibly kick them from the game.

            當由于滿足了MAX_LOOP條件而跳出邏輯循環時,可以在這里減掉多加的上TICK_TIME時間,并且只在單機游戲時才這樣做。

            如果是在單機游戲中,偶爾出現時間上的錯誤是不會有什么大問題的,所以當游戲邏輯執行超時后也沒有多大關系,我們簡單的把多花的時間減掉,然后重新開始。從技術上來說,這會使得游戲有一點點時間上的落后,但在單機游戲里這不會有什么實際的影響。

            但是在網絡游戲中這樣做卻不行,所有連網的電腦都必須要保持時間上的同步。

            在網絡游戲中,如果某臺電腦落后了,他應該保持其落后的狀態,然后在下一次進入邏輯更新循環時,自己讓自己多重復幾次,以便追趕上來。

            如果時間延遲只是個孤立事件,這將不會有多大問題,經過一兩次超速就會追趕上來,但是如果游戲邏輯更新總是超時,游戲的表現將會非常糟糕,并且最終將會越來越滯后。

            在網絡游戲中,你可能需要檢查出這些持續超時,表現總是很差的電腦,并將這些可能拖慢整個游戲環境的電腦踢出去。

             

            // Account for numLoops overflow causing percent > 1.
            float percentWithinTick = Min(1.f, float(time1 - time0)/TICK_TIME);
            GameDrawWithInterpolation(percentWithinTick);
             

            This is where the real magic happens, in my opinion. This section performs the rendering of the view. In the case of a loop where TICK_TIME=40, the logic is updating at 25 FPS. However, most video cards today are capable of far greater framerates, so it makes no sense to cripple the visual framerate by locking it to 25 FPS. Instead, we can structure our code so that we can smoothly interpolate from one logic state to the next. percentWithinTick is calculated as a floating point value in the range of [0,1], representing how far conceptually we are into the next game logic tick.

            在這里我們將進行屏幕繪制。

            當TICK_TIME = 40時,邏輯更新幀率為25FPS,但是現在大多數顯卡都能支持更高的渲染幀率,所以我們沒必要反而鎖定渲染幀率為25FPS。

            我們可以組織我們的代碼,讓我們能夠平滑的從一個邏輯狀態到下一個狀態做插值。percentWithinTick為一個0到1之間的浮點數,表示我們應該向下一個邏輯幀走多遠。

             

            Every object in the game has certain state regarding LastTick and NextTick. Each object that can move will have a LastPosition and a NextPosition. When the logic section updates the object, then the objects LastPosition is set to it's currentNextPostion and a new NextPosition is calculated based on how far it can move in one logic frame. Then, when the rendering portion executes, percentWithinTick is used to interpolate between these Last and Next positions:

            每個可移動的對象都有LastPosition和NextPosition。邏輯更新部分的代碼在執行時會將對象的LastPosition設置為當前的NextPosition,再根據它每一幀所能移動的距離來計算出NextPosition。

            然后,在渲染對象的時候,可以再用percentWithTick來在Last和Next位置之間進行插值。

            譯注:

            time0為最后一個邏輯幀所在的時間點,time1為當前實際時間,(time1 – time0) / TICK_TIME表示當前時間比最后一個邏輯幀所在時間超出了多少百分比,用這個百分比來向下一邏輯幀做插值。

            如果機器比較快,在兩個邏輯更新時間點之間執行了多次屏幕渲染,這樣插值就有效了。此時time0不變,time1一直在增長,可以根據增長的百分比來計算動畫應該從最后一次執行邏輯更新的位置向下一次邏輯更新所在的位置走多遠。

            也就是上文所說的,在Last和Next位置之間進行插值。插值后的實際位置,即DrawPosition的計算方法如下:

            動畫播放的插值也是類似。

             

            DrawPosition = LastPosition + percentWithinTick * (NextPosition - LastPosition);
             

            The main loop executes over and over as fast as the computer is able to run it, and for a lot of the time we will not be performing logic updates. During these loop cycles when no logic is performed, we can still draw, and as the loop progresses closer to the time of our next logic update, percentWithinTick will increase toward 1. The closer percentWithinTick gets to 1, the closer the a ctual DrawPosition of the object will get to NextPosition. The effect is that the object smoothly moves from Last to Next on the screen, the animation as smooth as the hardware framerate will allow. Without this smooth interpolation, the object would move in a jerk from LastPosition to NextPosition, each time the logic updates at 25FPS. So a lot of drawing cycles would be wasted repeatedly drawing the same exact image over and over, and the animation would be locked to a 25FPS rate that would look bad.

            游戲的主循環以電腦所能夠達到的最大速度不停地運行,在大多數時間里,我們將不需要執行邏輯更新。

            但是在這些不執行邏輯更新的周期里,我們仍然可以執行屏幕渲染。當循環的進程越接近我們的下一次邏輯更新時間,percentWithinTick就接近1;percentWithinTick越接近1,DrawPosition的位置就越接近NextPosition。

            最后的效果就是游戲對象在屏幕上慢慢的、平滑地從Last位置移動到Next位置,動作將以硬件幀率所能允許的程度盡可能的平滑。

            如果沒有這個平滑插值過程,對象位置將會從上一幀所在的LastPosition直接跳到下一幀所在的位置NextPosition。大量的渲染周期都被浪費在把對象反復渲染到相同的位置上,并且動畫也只能被鎖定在25FPS,使得看起來效果非常差。

             

            With this technique, logic and drawing are separated. It is possible to perform updates as infrequently as 14 or 15 times per second, far below the threshold necessary for smooth, decent looking visual framerate, yet still maintain the smooth framerate due to interpolation. Low logic update rates such as this are common in games such as real-time strategy games, where logic can eat up a lot of time in pathfinding and AI calculations that would choke a higher rate. Yet, the game will still animate smoothly from logic state to logic state, without the annoying visual hitches of a 15FPS visual framerate. Pretty danged nifty, I must say.

            使用了這項技術之后,邏輯更新與屏幕渲染被分離開了。

            這將允許我們把邏輯更新幀率降低到14或15FPS,這遠遠低于平滑的動畫渲染所需要的幀率,但是在使用動畫插值之后卻仍然能維持平滑的渲染幀率。

            在實時策略類游戲中可能會使用這樣低的邏輯更新幀率,這里邏輯更新會因尋路和AI計算而占用大量的時間,在這種情況下使用高的邏輯更新幀率顯然不行。

            但是,游戲卻仍然能夠在不同的邏輯狀態之間做平滑的動畫過渡,不會因為只有15FPS的渲染幀率而出現那些令人生厭的動畫跳躍現象。

            非常的漂亮,我不得不說。

             

            I've created a simple program in C to demonstrate this loop structure. It requires SDL ( http://www.libsdl.org ) and OpenGL. It's a basic bouncy ball program. The controls are simple: Press q to exit the program or press SPACE to toggle interpolation on and off. With interpolation on, the loop executes exactly as described to smooth out the movement from one logic update to the next. With interpolation off, the interpolation factor percentWithinTick is always set to 1 to simulate drawing without interpolation, in essence locking the visual framerate to the 25FPS of the logic update section. In both cases, the ball moves at exactly the same speed (16 units per update, 25 updates per second), but with interpolation the motion is much smoother and easier on the eyes. Compile and link with SDL and OpenGL to see it in action: http://legion.gibbering.net/golem/files/interp_demo.c

            posted @ 2009-09-14 20:29 白云哥 閱讀(2750) | 評論 (2)編輯 收藏

            僅列出標題
            共3頁: 1 2 3 

            導航

            統計

            常用鏈接

            留言簿(4)

            隨筆分類

            隨筆檔案

            相冊

            我的鏈接

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            国内精品人妻无码久久久影院导航| 国产成人综合久久综合| 久久伊人精品青青草原日本| 久久国产精品免费| 久久99国产精品久久99小说| 99国产欧美精品久久久蜜芽| 欧美亚洲另类久久综合婷婷| 久久国产色AV免费看| 久久久久亚洲AV无码去区首| 人妻少妇久久中文字幕| 久久综合久久鬼色| 久久最近最新中文字幕大全| 久久久亚洲欧洲日产国码是AV| 一本一道久久精品综合| 亚洲综合熟女久久久30p| 久久精品国产一区二区| 久久精品99久久香蕉国产色戒| 久久综合色老色| 久久狠狠一本精品综合网| 久久精品国产亚洲av高清漫画| 久久笫一福利免费导航 | 国产精品久久成人影院| 欧美日韩成人精品久久久免费看| 国内精品久久久久久野外| 一本色综合网久久| 香蕉久久夜色精品国产尤物| 精品久久久久中文字幕一区| 久久最近最新中文字幕大全 | 99久久亚洲综合精品网站| 无码精品久久久天天影视| 精品国产乱码久久久久久呢| 无码任你躁久久久久久老妇| 久久久99精品一区二区| 免费观看久久精彩视频| 91精品免费久久久久久久久| 久久久久久久99精品免费观看| 国内精品伊人久久久久av一坑| 久久久久久亚洲精品成人| 色欲久久久天天天综合网精品| 久久久久久人妻无码| 99久久99久久久精品齐齐|