《魔獸爭霸》的錄像,為什麼長達半小時的錄像大小只有幾百 KB?


相信你提出這個問題是以為魔獸的錄像文件是份視頻,所以才提出了"為什麼它只有幾百KB"這樣的問題,事實上這份文件不是一份視頻文件,它實際上是一份自定義格式的文件具體格式和內容可以參考下面的內容。
我在GitHub找到的一份非官方發布魔獸3錄像格式的文件描述,作者通過逆向工程和自己遊戲的經驗得出,裡面非常詳盡地描述了一個錄像文件的格式和內容包括哪些東西,幫助你了解;
錄像原理簡而言之:魔獸客戶端就是一個播放器,錄像就是輸入內容,播放器根據輸入播放輸出,其中的格式就是自己根據需求定義。

1.文件格式目錄:
文件的目錄大致包含以下內容,首先錄像文件頭包含了版本信息。雖然看到了這個版本的定義,但是對錄像文件的數據沒有做版本控制,這也是為什麼播放錄像的時候,如果客戶端版本不對,就無法播放的問題。擴展一下,其實這個問題可以在定製錄像文件的時候,針對不同部分的數據做特別的版本控制,以此達到兼容的問題,至少可以做到向下兼容。
===============================================================================
Table of Content 錄像文件描述文件目錄摘錄
===============================================================================
1.0 Introduction
2.0 [Header]
2.1 [SubHeader] for header version 0
2.2 [SubHeader] for header version 1
2.3 Version information
2.4 WarCraft III The Frozen Throne beta replay information
3.0 [Data block header]
4.0 [Decompressed data]
4.1 [PlayerRecord] 玩家記錄
4.2 [GameName] 遊戲名稱
4.3 [EncodedString] 加密字元串
4.4 [GameSettings] 遊戲設置
4.5 [MapCreatorName] 地圖角色
4.6 [PlayerCount] 玩家數量
4.7 [GameType] 遊戲類型
4.8 [LanguageID] 語言ID
4.9 [PlayerList] 玩家列表
4.10 [GameStartRecord]
4.11 [SlotRecord] 得分記錄
4.12 [RandomSeed] 隨機種子
5.0 [ReplayData]
6.0 General notes
6.1 Notes on official Blizzard Replays
7.0 Credits
8.0 Document revision history

===============================================================================5.0 [ReplayData]
===============================================================================
在上面的ReplayData中,包含了錄像所有的時間片數據,被細分為多個區塊Block,每個塊的數據或固定大小,或不固定,數據的都是以一個位元組代表blockID,用以標識要跳過某些固定的內容,以實現錄像跳過等功能。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0x1F - TimeSlot block 時間片數據 [ n+3 byte ]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1 word - n = number of bytes that follow 記錄時間片數據長度
1 word - time increment (milliseconds) 時間增長量(ms)
about 250 ms in http://battle.net 戰網250毫秒
about 100 ms in LAN and single player 區域網100毫秒
n-2 byte - CommandData block(s) (not present if n=2) 輸入命令數據塊

For every player which has executed an action during this time slot there is
at least one "Command data block".

CommandData block:
1 byte - PlayerID
1 word - Action block length
n byte - Action block(s) (see file "w3g_actions.txt" for details)

這裡有兩個重要的概念
1.TimeSlot Block"時間片數據塊",魔獸客戶端播放錄像就是嚴格按照時間片進行解析播放,時間片數據中主要記錄了數據長度和該時間片內遊戲中所有對象發生的動作序列,可以參考下面的動作描述文件內容。
2.CommandData Block,「命令數據塊」包括玩家的ID, 對應的動作序列長度和動作數據。
例如:
DD 00 0D 00 - use ability: cripple (UD Necromancer) [12-44-ID-ClickX/Y-TargetID]
這條記錄就描述了此刻時間片內發生的事件,亡靈的巫師使用了殘廢,點擊坐標(X,Y),對象的ID是誰誰誰醬紫,然後魔獸客戶端內部定義一套播放的介面,根據輸入的數據進行播放就能完成播放了。

ReplayData中主要數據是一下內容:===============================================================================
WarCraft III Replay action format description content 動作描述文件目錄摘錄
===============================================================================
1.0 Introduction
1.1 Standardized APMs
2.0 Action ID"s
3.0 AbilityFlags
4.0 ItemID"s
4.1 Stringencoded ItemID"s
4.2 Numeric ItemID"s
5.0 ObjectID"s
6.0 Click Coordinates
7.0 General notes
8.0 Notes on older Patches
9.0 Credits
10.0 Document revision history

裡面就記錄一些描述遊戲世界中對象的動作數據:
eg:
Following is a list of alphanumeric ID"s found so far:
03 00 0D 00 - rightclick
04 00 0D 00 - stop

08 00 0D 00 - cancel (train, research)

0C 00 0D 00 - set rally point

0F 00 0D 00 - attack
10 00 0D 00 - attack ground (e.g. Orc Catapult)

12 00 0D 00 - move unit

16 00 0D 00 - patrol

19 00 0D 00 - hold position

- - - - - -
21 00 0D 00 - give away item (from inventory to unit or ground)
- - - - - -
22 00 0D 00 - swap item place 7 (slot of item to swap with!)
23 00 0D 00 - swap item place 8
24 00 0D 00 - swap item place 4
25 00 0D 00 - swap item place 5

2.格式讀取說明
這裡以PlayerRecord說明一下裡面的具體錄像格式,按照二進位的方式讀取的
其中offest代表流的偏移,size/type代表讀取的數據大小,這樣就能精準的定位到具體的數據了。
4.1 [PlayerRecord]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

offset | size/type | Description
-------+-----------+-----------------------------------------------------------
0x0000 | 1 byte | RecordID:
| | 0x00 for game host
| | 0x16 for additional players (see 4.9)
0x0001 | 1 byte | PlayerID
0x0002 | n bytes | PlayerName (null terminated string)
n+2 | 1 byte | size of additional data:
| | 0x01 = custom
| | 0x08 = ladder

BTW:
回答一下,頂樓的問題:
「掉落表怎麼做,實際掉落生成方式怎麼設計,這個水很深,超出了我認知範圍,還是請專業的數值人員來回答吧」

我不是專業數值,其實掉落就是實現一個權重概率的問題,遊戲設計策劃人員會配置一個掉落庫,包括掉落的物品ID,掉落權重,然後在怪物配置裡面去綁定掉落的信息,魔獸裡面的怪物都是一個野怪會掉落不同的物品,這是一對多的關係,然後實現權重就可以了,權重也是偽隨機,就是說如果記錄下了隨機種子,那隨機結果就是唯一且確定的,所以錄像中一定會保留所有產生的隨機種子,這樣所有遊戲隨機的結果也就被記錄下來了。

趕腳劍聖錄像中的台詞是不是都是都一樣呢?For the burning Blade!


參考文件地址:
WarCraft III Replay file format description
http://w3g.deepnode.de/files/w3g_actions.txt


錄像文件有三個主要內容:

  1. 隨機種子數
  2. 基本信息(玩家、地圖)
  3. 操作序列

在我們玩war3的時候,地圖初始化會產生一個隨機種子,這個種子的作用是用來計算遊戲中的隨機數(例如AI行動,單位攻擊造成的傷害)。
接著,我們每一次的點擊、按鍵操作都會被序列化記錄下來。這裡記錄有分成三種:

  1. 時間X,玩家X對單位X執行命令(無目標,無點)
  2. 時間X,玩家X對單位X對單位Y執行命令
  3. 時間X,玩家X對單位X對點X執行命令

遊戲結束後,這些序列化數據會被保存下來。而不是正真保存了遊戲錄像。
再次載入錄像時,war3會按照隨機種子和序列重播一遍遊戲。這樣就保證了單位的攻擊傷害,和原本的傷害完全相同。操作也會完全相同。

如果玩的多的話,大家應該會注意到。有時候有些圖的錄像會和原本遊戲不一樣。播放到一半的時候單位行為變得不正常,莫名其妙的站在原地或者明明不該死的英雄居然死了。錄像完全亂套。原因也是因為隨機種子和操作序列和原本的出現偏差導致的結果。

=============================================================
應 @王biubiu 的要求,舉一個例子:
某個時間,英雄斧王跳入戰場吼住敵方英雄ABC,並且人品爆表。次次觸發反擊螺旋。轉了3圈就把對麵糰滅,FW帶領幾個扶不起的隊友A爆高地防禦塔,奪得勝利。

其中本次遊戲某時刻的隨機數為0.99,0.12,0.87,0.03,0.77,0.08,0.89。簡化一下,假設其他單位都沒有用到隨機數,只有FW和攻擊他的英雄使用了隨機數(攻擊傷害範圍,反擊螺旋概率)。反擊螺旋觸發概率17%,即隨機數小於等於0.17就會觸發。英雄A攻擊FW使用了隨機數0.99,反擊螺旋使用隨機數0.12,觸發反擊螺旋。英雄B攻擊FW使用隨機數0.87,反擊螺旋使用隨機數0.03,觸發反擊螺旋。以此類推。導致次次都觸發,爆死了對面。
遊戲存檔很盡責的保存了這次操作記錄:
時間1: 玩家1 命令 單位231 執行 閃爍(跳刀) 到 點A
(其中要注意的是,對於war3,英雄也是單位,所以只需要記錄單位ID即可。)
時間2: 玩家1 命令 單位231 執行 吼叫(無點無目標)
時間3: 無玩家 命令 單位189 執行 攻擊 到 單位231
(其中由於強制攻擊不是玩家操作,是ice forg編碼實現的攻擊,所以不需要設置命令玩家)
時間3: 無玩家 命令 單位166 執行 攻擊 到 單位231
時間3: 無玩家 命令 單位214 執行 攻擊 到 單位231
時間4: 玩家1 命令 單位231 執行 攻擊 到 單位59 (防禦塔)

其中,你會發現為什麼完全沒有記錄反擊螺旋的事件呢?因為很簡單,隨機種子是一定的情況下。觸發反擊螺旋也是一定的。對英雄ABC造成傷害也是一定的。因而錄像回放的時候直接模擬一遍命令,就會再次觸發反擊螺旋,殺掉英雄ABC的情況。

那麼,接下來就是有趣的現象了。如果其中一次命令序列出現了問題會怎麼樣?
命令序列出問題會有很多原因,比如自定義地圖(例如dota就是)中存在過多的腳本存在很多不會被記錄的操作(例如上面的反擊螺旋),遊戲使用了注入操作或者遊戲時網路通訊的問題(如果你注意的話,你會發現在線dota時,人物靠近單位有時會被莫名其妙的擠出去一小段距離)。
(以上都是概率性事件,不是次次都會出現這個問題)
言歸正傳,命令序列出了問題。遊戲在上述時刻之前多用了一個隨機數。接下來,錄像回放就變成了,英雄A攻擊FW,沒有觸發反擊螺旋。英雄B攻擊FW,沒有觸發反擊螺旋。英雄C攻擊FW,沒有觸發反擊螺旋。結果FW殘血,直接無視存活的三個英雄執行玩家1的攻擊防禦塔命令。
這時ABC3個英雄還活著,所以他們會繼續執行之前的 無玩家 命令攻擊FW的命令。
結果FW還沒A掉防禦塔,自己掛了。
故事還沒有結束,由於FW掛了。所以之後出現的單位也產生了影響。比如野區一個空點,本來要刷新3個巨魔一家的,因為隨機數變化,刷新出了小狗頭一家。這時,提到之前說的。war3隻記錄單位的ID。而不記錄單位本身。這時原本應該被下一個單位使用的ID被多出來的那個狗頭用了。可想而知,這個小狗頭之後會出現很多奇怪的行為。例如本來應該分配ID的是熊貓大招的風靈,對單位X使用吹風。但是由於小狗頭沒有吹風這個技能,所以只會執行幾個有限的操作。地圖回放時,出現一個神經病小狗頭。滿地圖亂走,走到一半突然就停下不動了。(因為正常遊戲里,風靈由於時間到了,所以消失了。不再有新的命令序列給它)。

大家都知道蝴蝶效應,war3的回放功能是一個很典型的例子。當遊戲錄像某一個點上出現偏差時,遊戲就再也回不來了。。。


沒想到這麼多贊,當初這樣答完全是因為看到大家都已經講了rep的本質,於是就補充一下當初自己是怎麼理解錄像中的隨機種子的。
再改一下吧,手機打字比較辛苦,鏈接也不好弄,望見諒。
首先正面回答答主的問題,為什麼rep會小?其他的答主也都給出了答案,在這裡尤為推薦楊浩的答案
http://www.zhihu.com/question/25431134/answer/30917935
在該答案中他給出了rep的描述文檔,如果大家可以看懂那個的話可以直接跳過我的簡單舉例子答案。
下面我同樣是以舉例子的角度正面回答題主的問題。rep文件不是傳統意義上的錄像,話劇中的「劇本」這個實際生活中的概念和它更接近。每當玩家們看錄像時,遊戲內的模型、數值、演算法等資源就被調動,相當於話劇演員穿戴服裝道具在舞台上重新演了一遍。相對於把整部話劇拍下來的視頻文件大小而言,話劇的劇本的文本量則必然會小得多。而至於有的朋友提問為什麼rep在播放時會出錯,與原先的實際情況不一致?大家可以這樣理解,劇本在印製或派發時出現了缺頁或污損,演員們看不懂不會演了。在遊戲中類似道理的應用就是用即時演算替代cg。

下面是原答案,只說了隨機種子部分。
=================================
補充一下,在理解rep只是存儲操作指令和單位狀態後,我小時候還一直不清楚幾率相關的東西是怎麼存進rep的,比如攻擊力在魔獸中是個範圍而不像在星際中是個確定數值,劍聖/dh這刀是否暴擊/被閃避,坡下打坡上是不是miss,直到我接觸了偽隨機數。直到現在和別人解釋偽隨機數時我都用星際魔獸rep里的暴擊作為材料。

粘貼評論中的舉例:

為簡化,假設劍聖暴擊率是10%,2倍暴擊,而平砍傷害是10-20,劍聖砍了一刀,實際傷害30(15*2),第二刀坡下砍坡上,miss了。如果在rep中直接儲存暴擊30,第二刀miss也是可以的,但是這樣顯然要把劍聖一局遊戲中的每一刀都要存下來,較為佔用空間。而rep中採用的做法是,魔獸遊戲中生成了一個偽隨機數序列,這個序列在遊戲中,不在rep里,但是rep播放時可以調用。例如取0-1的均勻分布,比如0.753、0.500、0.988、0.132、0.781、0.646………均勻分布即為在0-1中取到這些數中的每一個概率是一致的),然後在rep中記錄隨機數種子(隨機數開始的序列位置)。例如本rep種子為1,即從0.753開始。劍聖第一刀坡下砍坡上,命中率70%,可以等價於偽隨機數值大於0.3即命中,而0.753大於0.3,故命中。下面實際攻擊取10+(20-10)*隨機數,此處為0.5,故攻擊為15。下面計算暴擊,和命中類似,隨機數大於0.9即為暴擊,此處為0.988,滿足,故最終傷害為30。第二刀由於0.132小於0.3,故miss。作為rep,只需要存儲劍聖的坐標、命令和種子數1,就能再現這兩刀。此外其他遊戲里的掉寶率也是這樣的,例如暗黑。那個哥布林在你決定殺他的一剎那,他掉什麼已經確定了,所以叫偽隨機。
ps:我們打wow時說組了個黑手,這個CD就被他黑了,是有道理的。

關於更真實更複雜的實際情況,牽扯到概率的補償,不會永遠讓你感到黑手沒法玩(例如最近wow中好運幣roll裝備若沒roll到則幾率越來越高)。請參考評論中zy RSN的說明。

對於近戰坡下砍坡上不會miss的問題,我搞錯了,答題時也忽略了這個事實。那大家把例子想成DOTA裡帶水晶劍的遠程英雄(不帶金箍棒克敵機先)吧。

雖說有點走題,不過關於魔獸世界中的掉落問題,確實如評論中所說,是在第一個人進入副本時根據掉落表生成的。不過我想表達的意思沒有變,隨機的事物實際上往往是不那麼隨機的。至於掉落表怎麼做,實際掉落生成方式怎麼設計,這個水很深,超出了我認知範圍,還是請專業的數值人員來回答吧。


正如前面兩位所說,其實不是視頻本身而是事件

可以參考這個 http://w3g.deepnode.de/files/w3g_format.txt


我猜一個,因為下的不是視頻文件,而是劇情腳本。要看時讓遊戲主程序運行下就行了


魔獸的錄像記錄的是這種東西:

………………
1:00,從 OOO 工廠造了一個兵,位置 ……,方向 ……
1:01,玩家 XXX 選擇了兵 OOO
1:02,玩家 XXX 對兵 OOO 下令攻擊 XXX
………………
1:20,兵 OOO 受到攻擊,掛了
………………

然後,如果某些事件可以通過計算算出,就不寫它。


除了樓上所說的,還有一點很重要,就是對於隨機事件記錄了隨機的種子,以保證隨機序列一致(比如AC在比賽中一次攻擊是3,每次播放錄像時必須是3)


你沒發現你放錄像的時候要有這張圖才可以嗎?


目前的項目(策略遊戲)也實現了錄像回放機制,幾個要點:
1、記錄玩家的操作命令,而不是視頻。這樣數據量可以很小,一場戰鬥只有幾k。
2、記錄下達命令的幀編號而不是時間,比如在戰鬥開始的第幾幀下達了什麼指令。分離邏輯和渲染的Update,戰鬥時遊戲邏輯按幀推進而不是按時間推進,這樣才能做到精確回放。
3、戰鬥開始時生成隨機種子記錄下來,回放時設置該種子,保證隨機函數生成的偽隨機數列一致。


很多年前我開始打星際時,也思考過這個問題。因為再之前玩帝國2,需要在遊戲開始前勾上遊戲錄像才會有,而星際是打完後才提示是否保存,而且文件體積比帝國的小很多。雖然都是老遊戲了,但後者的設計明顯優於前者。

咦跑題了。其實同為暴雪出品,魔獸的模式跟星際是雷同的。RTS,何謂即時戰略?就是你作為commander下達指令(滑鼠鍵盤操作集),電腦執行其中的有效部分。比如農民a坐標是(3,7),某礦坐標是(9,5),那你遊戲開始第3秒時左鍵單擊(3,7)再右鍵單擊(9,5),農民這一刻就會跑去採礦。這一類指令明確而沒有二義性,所以在初始地圖一樣的條件下,執行同樣的指令,結果是一定的,勝負亦然。

印證想法的一個是戰鬥結束後選項不叫save video而是save replay,但這裡的replay不僅是重玩的意思,還是重新演算。由於該文件已經把所有玩家的所有指令帶上時間戳記錄了下來,所以放錄像時可以無損回放整個戰鬥過程,跟玩的時候一模一樣,區別只在於一個是你在操作,一個是電腦根據保存在rep文件里的指令集去操作。

另一個是不知道題主有沒用過類似SCtools里apm/eapm分析器的小工具。它只要讀取rep文件就可以統計出這一場里所有玩家的峰值apm和平均apm等數據,也說明了rep里存的是鍵鼠操作。比如01:01:03 (3,7) left down或者01:01:04 "p"這樣的格式。一場戰鬥也就幾萬條這樣的數據,不佔多少空間。rep里還存了起始地圖數據,而這個也沒多大。

所以比起真正錄像里一幀一幀記錄所有像素點,這種遊戲的「錄像」文件也就小多了。

以上純屬apm88的星際老菜鳥瞎扯。


具體的很多人都說過了,我來做個不見得準確但是十分好懂的比方吧

如圖是一截自動鋼琴的紙帶。
我們都知道一首鋼琴曲,錄成音頻,佔用的空間是很大的,如同錄像視頻。
但是這自動鋼琴的紙帶,上面的信息量顯然十分匱乏,比之磁帶CD和音頻文件都要少的多。
但是照樣可以精確的復原一首鋼琴曲,前提是要有鋼琴。
鋼琴=遊戲本體
Rep文件=紙帶
遊戲過程中的行為=紙帶的孔同理還有midi格式音樂


感覺樓上兩位還沒讀懂題主的意思。
題主的意思大概是魔獸爭霸自帶的遊戲錄像功能。
我覺得,因為這種錄像不是直接錄畫面,而是錄下這局遊戲的數據。所以100多K的文件裡面記錄的是你的遊戲數據,讀取的時候,就直接讀取這些數據,然後用遊戲自帶的功能播放。


你說的是rep吧,rep是一個腳本文件,記錄了「什麼時間發生了什麼事情」,然後你看到的東西,基本都是根據這個腳本,遊戲給你復盤,實時重新演繹了一遍的,而不是錄視頻。
這就造成同一個遊戲,不同版本的rep文件格式可能不兼容。或者你用了改過的客戶端,比如星際高AI版,放原版的rep,也許也能放,但可能就根本無法復盤。又或者你玩war3的時候調了秘技,然後錄的rep回放也會出問題。


打個比方,這就類似於你已經有了一家完整的劇院,裡面可以搭建各種不同舞台(地圖文件),並配備了全部演員(人類劇組、獸人劇組、亡靈劇組、精靈劇組以及中立劇組),這些東西都已經存在於你的電腦上了,就是那個幾百兆的魔獸遊戲。

當你給它們一個名為「木瓜大戰.rep」的劇本後:

- LOADING畫面,燈光,音效,Action!
- 幾分幾秒時生命之樹開始變第N個小精靈,幾分幾秒編號9527的苦工帶給獸人大廳一捆木頭。
- 幾分幾秒時探路的小精靈來到了舞台(地圖)上的某個坐標,幾分幾秒時劍聖的大刀向某野怪的頭上砍去。
- 幾分幾秒時惡魔獵手斬殺獸人步兵一枚,獸人步兵表演慘叫倒地的一幕後打卡下班。
- 幾分幾秒時木的動物園大軍殺入瓜的基地,「瓜」不敵眾果斷GG,劇本結束。

所以,答主下載的幾百K的錄像,本質上就是一個類似劇本的文件,而其他的東西統統都在魔獸爭霸的遊戲之中了,這也就是為什麼它需要進入遊戲才能看,而不是用QQ影音看的原因...


rep只用記錄關鍵的一些數據,比如在任意時刻每個人的位置,狀態。這些數據是非常小的。

你認為的大,是全程錄視頻。

視頻可以無需遊戲播放,但是rep要將抽象的數據還原,必須依賴遊戲客戶端


我在2013年用Java寫過一個War3錄像解析器(開源在GitHub上),也寫過一系列相關博客,算是比較了解War3錄像w3g格式了,今天有空正好來回答一下這個問題。

Java WAR3錄像解析器源代碼GitHub:wucao/jw3gparser

使用方法:

public class Test {

public static void main(String[] args) throws IOException, W3GException, DataFormatException {

Replay replay = new Replay(new File("d:/wucao/Desktop/151020_[UD]LuciferLNMS_VS_[NE]checkuncle_Amazonia_RN.w3g")); // 這裡可以替換成你的魔獸錄像文件

Header header = replay.getHeader();
System.out.println("版本:1." + header.getVersionNumber() + "." + header.getBuildNumber());
long duration = header.getDuration();
System.out.println("時長:" + convertMillisecondToString(duration));

UncompressedData uncompressedData = replay.getUncompressedData();
System.out.println("遊戲名稱:" + uncompressedData.getGameName());
System.out.println("遊戲創建者:" + uncompressedData.getCreaterName());
System.out.println("遊戲地圖:" + uncompressedData.getMap());

List& list = uncompressedData.getPlayerList();
for(Player player : list) {
System.out.println("---玩家" + player.getPlayerId() + "---");
System.out.println("玩家名稱:" + player.getPlayerName());
if(player.isHost()) {
System.out.println("是否主機:主機");
} else {
System.out.println("是否主機:否");
}
System.out.println("遊戲時間:" + convertMillisecondToString(player.getPlayTime()));
System.out.println("操作次數:" + player.getAction());
System.out.println("APM:" + player.getAction() * 60000 / player.getPlayTime());
if(!player.isObserverOrReferee()) {
System.out.println("玩家隊伍:" + (player.getTeamNumber() + 1));
switch(player.getRace()) {
case HUMAN:
System.out.println("玩家種族:人族");
break;
case ORC:
System.out.println("玩家種族:獸族");
break;
case NIGHT_ELF:
System.out.println("玩家種族:暗夜精靈");
break;
case UNDEAD:
System.out.println("玩家種族:不死族");
break;
case RANDOM:
System.out.println("玩家種族:隨機");
break;
}
switch(player.getColor()) {
case RED:
System.out.println("玩家顏色:紅");
break;
case BLUE:
System.out.println("玩家顏色:藍");
break;
case CYAN:
System.out.println("玩家顏色:青");
break;
case PURPLE:
System.out.println("玩家顏色:紫");
break;
case YELLOW:
System.out.println("玩家顏色:黃");
break;
case ORANGE:
System.out.println("玩家顏色:橘");
break;
case GREEN:
System.out.println("玩家顏色:綠");
break;
case PINK:
System.out.println("玩家顏色:粉");
break;
case GRAY:
System.out.println("玩家顏色:灰");
break;
case LIGHT_BLUE:
System.out.println("玩家顏色:淺藍");
break;
case DARK_GREEN:
System.out.println("玩家顏色:深綠");
break;
case BROWN:
System.out.println("玩家顏色:棕");
break;
}
System.out.println("障礙(血量):" + player.getHandicap() + "%");
if(player.isComputer()) {
System.out.println("是否電腦玩家:電腦玩家");
switch (player.getAiStrength())
{
case EASY:
System.out.println("電腦難度:簡單的");
break;
case NORMAL:
System.out.println("電腦難度:中等難度的");
break;
case INSANE:
System.out.println("電腦難度:令人發狂的");
break;
}
} else {
System.out.println("是否電腦玩家:否");
}
} else {
System.out.println("玩家隊伍:裁判或觀看者");
}

}

List& chatList = uncompressedData.getReplayData().getChatList();
for(ChatMessage chatMessage : chatList) {
String chatString = "[" + convertMillisecondToString(chatMessage.getTime()) + "]";
chatString += chatMessage.getFrom().getPlayerName() + " 對 ";
switch ((int)chatMessage.getMode()) {
case 0:
chatString += "所有人";
break;
case 1:
chatString += "隊伍";
break;
case 2:
chatString += "裁判或觀看者";
break;
default:
chatString += chatMessage.getTo().getPlayerName();
}
chatString += " 說:" + chatMessage.getMessage();
System.out.println(chatString);
}

}

private static String convertMillisecondToString(long millisecond) {
long second = (millisecond / 1000) % 60;
long minite = (millisecond / 1000) / 60;
if (second &< 10) { return minite + ":0" + second; } else { return minite + ":" + second; } } }

解析結果輸出:

版本:1.26.6059
時長:24:53
遊戲名稱:WCA01
遊戲創建者:A.1st_LawLiet
遊戲地圖:MapsDownload(2)Amazonia.w3x
---玩家1---
玩家名稱:A.1st_LawLiet
是否主機:主機
遊戲時間:24:32
操作次數:0
APM:0
玩家隊伍:裁判或觀看者
---玩家2---
玩家名稱:checkuncle
是否主機:否
遊戲時間:24:31
操作次數:5831
APM:237
玩家隊伍:2
玩家種族:暗夜精靈
玩家顏色:紅
障礙(血量):100%
是否電腦玩家:否
---玩家3---
玩家名稱:LuciferLNMS
是否主機:否
遊戲時間:24:31
操作次數:7816
APM:318
玩家隊伍:1
玩家種族:不死族
玩家顏色:灰
障礙(血量):100%
是否電腦玩家:否
---玩家4---
玩家名稱:WCA_SEA_OB2
是否主機:否
遊戲時間:24:53
操作次數:0
APM:0
玩家隊伍:裁判或觀看者
---玩家5---
玩家名稱:wca_sea_ob1
是否主機:否
遊戲時間:24:32
操作次數:0
APM:0
玩家隊伍:裁判或觀看者
[0:09]checkuncle 對 所有人 說:All rights reserved by Blizzard
[0:10]checkuncle 對 所有人 說:w3g files released by www.Replays.Net.
[0:36]LuciferLNMS 對 所有人 說:gl
[0:38]checkuncle 對 所有人 說:gl
[24:30]checkuncle 對 所有人 說:gg
[24:43]checkuncle 對 所有人 說:For more replays, plz visit www.Replays.Net

相關博客:
Java解析魔獸爭霸3錄像W3G文件(一):Header - 叉叉哥的BLOG - 博客頻道 - CSDN.NET
Java解析魔獸爭霸3錄像W3G文件(二):壓縮數據塊解壓合併 - 叉叉哥的BLOG - 博客頻道 - CSDN.NET
Java解析魔獸爭霸3錄像W3G文件(三):解析遊戲開始前的信息 - 叉叉哥的BLOG - 博客頻道 - CSDN.NET
Java解析魔獸爭霸3錄像W3G文件(四):解析遊戲進行時的信息 - 叉叉哥的BLOG - 博客頻道 - CSDN.NET
Java解析魔獸爭霸3錄像W3G文件(五):Action和APM計算 - 叉叉哥的BLOG - 博客頻道 - CSDN.NET

只要了解w3g文件結構,你完全可以用你喜歡的其他語言再寫一個w3g解析器。

==============================================

簡單回答就是:

War3錄像並不是一個視頻文件,你只能在War3遊戲中觀看,其他各種播放器例如XX影音、快播都播放不了,War3錄像中所有的場景、人物、動畫實際上都在War3遊戲中,而不是錄像中。

War3錄像中只記錄了玩家的各種操作,例如什麼單位移動到哪個位置(X,Y坐標)、玩家開始建造某個單位等(APM分析工具也是通過這些玩家行為和遊戲時長分析出來的),這些數據本身並不大。

另外w3g通過zlib壓縮過。

==============================================

下面簡單介紹一下一個w3g文件包含哪些內容,限於篇幅,只簡單舉幾個栗子:

Header部分
這是每個w3g文件最前面的部分,固定是前68個位元組,包含以下信息:
0~28位元組(28個位元組):固定的字元串"Warcraft III recorded gamex1A"。
29~32位元組(4個位元組):Header部分的總位元組數,對於1.07版本及之後,是68(0x44),對於1.06版本及之前是64(0x40)。
33~36位元組(4個位元組):壓縮數據塊的壓縮數據總位元組數,即解壓前。
37~40位元組(4個位元組):錄像版本標識(0表示1.06版本及之前版本,1表示1.07版本及之後版本)。
41~44位元組(4個位元組):壓縮數據塊解壓縮後的總位元組數。
45~48位元組(4個位元組):壓縮數據塊的個數。
49~52位元組(4個位元組):一個字元串標識,"WAR3"表示非冰封王座,"W3XP"表示冰封王座。
53~56位元組(4個位元組):版本號(例如24即是1.24版本)。
57~58位元組(2個位元組):構建號(build number)。
59~60位元組(2個位元組):0x0000表示單人遊戲,0x8000(十進位32768)表示多人遊戲。
61~64位元組(4個位元組):錄像時長(毫秒數),需要注意的是,這個時長不包括遊戲中暫停的時長。
65~68位元組(4個位元組):Header部分CRC32校驗碼(包含這四個位元組但是要都設為0)。

可以使用EditPlus的Hex Viewer方式打開w3g文件查看Header部分:

壓縮數據塊(compressed data block)
除了Header部分,接下來的所有數據都是一個個的zlib壓縮的數據塊,每個壓縮資料庫包含8位元組的頭部和解壓後8192位元組的壓縮數據。針對這塊要做的是將數據解壓後合併起來:

合併得到的原始數據,包含一些遊戲開始前的數據,和遊戲進行中的數據。

遊戲開始前的數據
如有哪些玩家、什麼種族、遊戲的地圖、配置等,下圖中的這些配置都是保存在錄像的這個部分:

在這個部分,每個玩家會有一個編號,即playerId,玩家是保存在槽位(Slot)中的,例如上圖就是四個槽位。每個Slot佔9個位元組:

1位元組:對應的玩家ID,電腦玩家是0x00。
1位元組:地圖下載百分比(一般都是100)。
1位元組:Slot狀態,0x00空的,0x01關閉著的,0x02使用中的。
1位元組:是否是電腦玩家,0x00非電腦玩家,0x01電腦玩家。
1位元組:隊伍,0~11分別表示隊伍1到隊伍12,12表示裁判或觀看者。
1位元組:顏色,0紅1藍2青3紫4黃5橘黃6綠7粉8灰9淺藍10深綠11棕12裁判或觀看者
1位元組:種族,0x01/0x41人族,0x02/0x42獸族,0x04/0x44暗夜精靈,0x08/0x48不死族,0x20/0x60隨機。
1位元組:電腦難度,0x00簡單的,0x01中等難度的,0x02令人發狂的。
1位元組:障礙(也就是血量百分比),0x32,0x3C,0x46,0x50,0x5A,0x64之一,分別表示50%到100%。


例如一條Slot信息的位元組碼(8進位表示):01 64 02 00 00 03 42 01 64

01:玩家ID是1

64:轉化成10進位就是100

02:有玩家

00:非電腦玩家

00:隊伍1

03:紫色

42:獸族

01:中等難度的(這個對非電腦玩家就沒有意義)

64:100%血量

遊戲進行中的數據
這一部分就算是核心內容了,這裡記錄了玩家的操作、聊天等信息。

例如一條聊天數據的位元組碼:20 01 08 00 20 00 00 00 00 67 67 00
20(1位元組):數據塊ID,固定為0x20;
01(2位元組):發聊天的玩家ID是1;
08 00(3~4位元組):剩餘數據的位元組數,也就是後面還剩8個位元組結束,注意這個是小位元組序(Little-Endian),也就是和通常所使用的大位元組序(Big-Endian)的反過來的,08 00轉換成大位元組序就是 00 08,也即是8;
20(5位元組):flag不用管;
00 00 00 00(6~9位元組):聊天模式,0x00:對所有玩家,0x01:對隊友,0x02:對裁判或觀看者,0x03或大於0x03:對指定玩家。這裡表示對所有人說;
67 67(10~n+3位元組):聊天內容,查看ASCII碼錶可以查到8進位"67"對應字母"g",也就是該玩家打出了"gg";
00(最後1個位元組):這是固定的結束字元;

除了聊天信息,還有TimeSlot數據塊用於記錄玩家操作,每個TimeSlot包含一個時長(一般100毫秒左右)以及在這段時間內玩家發生的操作。
舉一個最簡單的操作,玩家選擇編隊:1f 08 00 6d 00 01 03 00 18 03 03
1f:表示這是一個TimeSlot
08 00:剩餘8位元組
6d 00:TimeSlot時長,小位元組序,轉成10進位是109,表示109毫秒
03 00:剩餘3個位元組,小位元組序;
01:玩家ID
18:表示這是一個選擇編隊的操作;
03:選擇的隊伍編號;
03:未知;
這塊數據就完整的表示了某個玩家的一次選擇編隊操作。

==============================================

參考文檔:

http://w3g.deepnode.de/files/w3g_format.txt

http://w3g.deepnode.de/files/w3g_actions.txt


你,知道MIDI不?


這種遊戲都是按狀態機實現的,例如有:stand, move, attack, spell1, spell2, 這種狀態機,狀態機是互斥的,意思就是說我在某個時刻點只能處於一種狀態,所以我只需要記錄時間點和狀態機就可以了。沒有具體反解war3的rep,根據我自己做錄像的經驗。


錄像文件你就當它是劇本,播放的時候燈光道具美工啥的各路英雄照劇本來即可。


以下內容純屬瞎猜!
題主看的是魔獸爭霸的錄像,不是視頻,這就是答案!
魔獸爭霸的錄像保存的並不是視頻信息,而是一些用戶行為(建築,攻擊,路線,買賣物品等),當你觀看「錄像」的時候,平台將這些數據讀出並進行「播放」,就形成了你看到的畫面。
因為魔獸爭霸所有的遊戲模型(英雄,建築,森林,草地……)都是後台構建好的,所以只需要加上具體的操作命令就可以得到想要的畫面。換句話說,你所謂的幾百kb的錄像只是錄像的一個部分,在它後面還有整個遊戲平台。
據此可以推斷,如果你會編輯那幾百kb的文件,那麼你完全可以「導演」一場完美的魔獸爭霸戰役!
胡說八道,心裡不安了~~


推薦閱讀:

什麼叫打擊音效怎麼和人聲音效區別?
是不是服務端編程剛開始都得從寫業務開始?
想要自己做一款遊戲,需要學習哪些知識?
為什麼遊戲里的鏡頭虛化「尤其是近景人物」總看起來不太自然?
遊戲界有什麼經典至理名言?

TAG:遊戲 | 程序員 | 遊戲開發 | 錄像 | 魔獸系列 |