• <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>

            李錦俊(mybios)的blog

            游戲開發 C++ Cocos2d-x OpenGL DirectX 數學 計算機圖形學 SQL Server

              C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
              86 Posts :: 0 Stories :: 370 Comments :: 0 Trackbacks

            公告

            QQ:30743734
            EMain:mybios@qq.com

            常用鏈接

            留言簿(16)

            我參與的團隊

            最新隨筆

            搜索

            •  

            積分與排名

            • 積分 - 370223
            • 排名 - 67

            最新評論

            閱讀排行榜

            評論排行榜

            注意:本文純屬是本人從研究魔獸爭霸III地圖編輯器的過程中的一種猜想,所以,不當之處,還請高手指出。謝謝!

              魔獸爭霸III我以前玩得比較多,也聽說他的地圖編輯器非常牛X,以前也曾經想編輯個地圖出來。但是,限于當時得水平問題,沒有成功。直到最近在研究如何制作游戲的時候,打開魔獸爭霸III的地圖編輯器來看,突然有一種擴然開朗的感覺!哦!原來地圖編輯器是這樣出來的!閑話不多說!馬上進入正題!

              魔獸爭霸III的地圖編輯器使用了一個文件來代表一個地圖,地圖里包含了什么東西?我無從得知,但是,從他的編輯器上看,看到編輯器能對地圖修改的東西,就可以大概猜想到有哪些東西。仔細看地圖編輯器,看到有那么幾個模塊:地形編輯器、開關編輯器、聲音編輯器、物體編輯器、戰役編輯器、AI編輯器、物體管理器、輸入管理器。我把我的理解逐一說來。

              1.地形編輯器
                主要用來編輯地形,例如某個地方擺放什么地形,什么地方擺放什么物體、英雄、燈光等等東西。那么,這些東西在地圖文件中我想是以數據的形式來存放的,而不是腳本!因為,我測試過,放了一個英雄到地圖中,然后導出腳本,但是腳本里沒有任何關于這個英雄的資料!那就證明了是用某種格式保存在地圖文件中。整個地形都是這么存放。

              2.開關編輯器
                開關編輯器,也就是觸發事件編輯器。這個東西在地圖編輯器中比較的高級,人們都說魔獸爭霸III的地圖編輯器是萬能編輯器,很大的原因就是因為有了這個東西!這個東西是如何實現的呢?說起來很簡單!就是腳本實現!我分析了一下,一個觸發器,分成三個部分:發生事件、觸發條件、執行動作。那么三個東西在腳本中和程序中是如何實現?
                讓我在編輯器中新建一個觸發器解釋一下。新建一個觸發器,叫做TestTrigger,在這個觸發器下新建一個事件“玩家 - 玩家1 (紅色) leaves the game”,新建一個條件“TRUE 等于TRUE”,新建一個動作“Do nothing”。然后導出腳本,看看腳本如何:
            //===========================================================================
            // 
            // 只是另外一張魔獸爭霸III的地圖
            // 
            //   Warcraft III map script
            //   Generated by the Warcraft III World Editor
            //   Date: Sat Nov 18 23:35:12 2006
            //   Map Author: 李錦俊
            // 
            //===========================================================================

            //***************************************************************************
            //*
            //*  Global Variables
            //*  全局變量
            //***************************************************************************

            globals
                
            // Generated
                
            //  我們的觸發器保存成一個全局變量了!!
                trigger                 gg_trg_TestTrigger         = null
            endglobals

            function InitGlobals takes nothing returns nothing
            endfunction

            //***************************************************************************
            //*
            //*  Triggers
            //*  觸發器!
            //***************************************************************************

            //===========================================================================
            // Trigger: TestTrigger 我們的觸發器的觸發條件
            //===========================================================================
            function Trig_TestTrigger_Conditions takes nothing returns boolean
                
            // 如果true == true ?? 不正是我們設置的“TRUE等于TRUE”嗎
                if ( not ( true == true ) ) then
                    
            return false
                endif
                
            return true
            endfunction

            // 我們的觸發器的執行動作!!
            function Trig_TestTrigger_Actions takes nothing returns nothing
                
            // DoNothing ?? 不正是我們設置的“Do nothing”嗎?
                call DoNothing(  )
            endfunction

            //===========================================================================
            // 初始化我們的觸發器
            function InitTrig_TestTrigger takes nothing returns nothing
                
            // 創建一個觸發器,保存在一個全局變量里
                set gg_trg_TestTrigger = CreateTrigger(  )
                
                
            // 看這個英文的函數名。。我翻譯一下應該是“觸發器:注冊玩家單位簡單事件”
                
            // 再看看參數
                
            // 第一個參數是我們的觸發器的全局變量
                
            // 第二個參數是Player(0)啊,不就是我們設置的“玩家1”嗎?(語言上從0開始,顯示上從1開始,習慣了)。
                
            // 第三個參數EVENT_PLAYER_UNIT_DEATH,翻譯一下應該是“玩家單位死亡事件”,哈哈!很明顯又是我們設置的
                call TriggerRegisterPlayerUnitEventSimple( gg_trg_TestTrigger, Player(0), EVENT_PLAYER_UNIT_DEATH )

                
            // 翻譯:“觸發器:添加觸發條件”,然后參數就是上面那個觸發條件的函數,函數里就是我們設置的條件
                call TriggerAddCondition( gg_trg_TestTrigger, Condition( function Trig_TestTrigger_Conditions ) )

                
            // 翻譯:“觸發器:添加執行動作”,然后參數就是上面那個執行動作的函數,函數里就是我們設置的動作!
                call TriggerAddAction( gg_trg_TestTrigger, function Trig_TestTrigger_Actions )
            endfunction

            //===========================================================================
            // 地圖初始化的時候都會調用這個函數初始化所有自定義的觸發器,當然也有我們的觸發器了。InitTrig_TestTrigger不就是剛才那個函數了嗎
            function InitCustomTriggers takes nothing returns nothing
                call InitTrig_TestTrigger(  )
            endfunction

            //***************************************************************************
            //*
            //*  Main Initialization
            //*  main啊!這么熟悉!一定是此腳本文件的入口函數了!在C++主程序中調用的!(我暫且認為WarCraftIII是用C++寫的了)
            //***************************************************************************

            //===========================================================================
            function main takes nothing returns nothing
                call SetCameraBounds( 
            -3328.0 + GetCameraMargin(CAMERA_MARGIN_LEFT), -3584.0 + GetCameraMargin(CAMERA_MARGIN_BOTTOM), 3328.0 - GetCameraMargin(CAMERA_MARGIN_RIGHT), 3072.0 - GetCameraMargin(CAMERA_MARGIN_TOP), -3328.0 + GetCameraMargin(CAMERA_MARGIN_LEFT), 3072.0 - GetCameraMargin(CAMERA_MARGIN_TOP), 3328.0 - GetCameraMargin(CAMERA_MARGIN_RIGHT), -3584.0 + GetCameraMargin(CAMERA_MARGIN_BOTTOM) )
                call SetDayNightModels( 
            "Environment\\DNC\\DNCLordaeron\\DNCLordaeronTerrain\\DNCLordaeronTerrain.mdl""Environment\\DNC\\DNCLordaeron\\DNCLordaeronUnit\\DNCLordaeronUnit.mdl" )
                call NewSoundEnvironment( 
            "Default" )
                call SetAmbientDaySound( 
            "LordaeronSummerDay" )
                call SetAmbientNightSound( 
            "LordaeronSummerNight" )
                call SetMapMusic( 
            "Music"true0 )
                call InitBlizzard(  )
                call InitGlobals(  )
                
            // 上面執行的這幾個函數主要是設置一些環境變量,什么攝像頭、日晝幾何模型、背景音樂等等
                
            // 這個函數就是初始化我們的觸發器啊!
                call InitCustomTriggers(  )
            endfunction

            //***************************************************************************
            //*
            //*  Map Configuration
            //*  地圖配置,估計也是在C++主程序中調用的!
            //***************************************************************************

            function config takes nothing returns nothing
                call SetMapName( 
            "只是另外一張魔獸爭霸III的地圖" )
                call SetMapDescription( 
            "沒有描述" )
                call SetPlayers( 
            1 )
                call SetTeams( 
            1 )
                call SetGamePlacement( MAP_PLACEMENT_USE_MAP_SETTINGS )

                call DefineStartLocation( 
            0-1409.3219.2 )

                
            // Player setup
                call InitCustomPlayerSlots(  )
                call SetPlayerSlotAvailable( Player(
            0), MAP_CONTROL_USER )
                call InitGenericPlayerSlots(  )
            endfunction

              我加的注釋里已經寫得很清楚了,很明顯我們在地圖編輯器里面設置的所有觸發器的東西,都會以一種腳本的形式生成,然后程序在根據地圖數據初始化地圖之后調用這個腳本的main函數和config函數。在游戲進行過程中,TriggerRegister開頭的函數注冊了一些事件開端,簡單的實現就是維護一個列表而已。然后游戲進行到這個事件的時候(例如剛才的例子里是TriggerRegisterPlayerUnitEventSimple,則玩家單位發生一些簡單事件的時候就會執行),就遍歷這個列表的每一個元素調用他們用TriggerAddCondition注冊的條件,如果為true,則執行TriggerAddAction函數的內容!觸發器的實現原理基本上就是這樣了!當然,真正實現起來還是有很多東西要做的,例如要有很多很多的函數要綁定到腳本引擎中!

              3.聲音編輯器
                這個我沒研究過啊,待續....

              4.物體編輯器
                里面就是所有單位、建筑物、物品(簡稱Items吧,中文翻譯過來就變味了,呵呵!)的一些屬性設置,這些屬性都是以數據的形式保存在地圖中的,程序運行的時候就以這些數據來基礎運行起來,例如某某英雄聲明值是多少云云....

              5.戰役編輯器
                沒搞過,不多作評論

              6.AI編輯器
                我只知道AI不是腳本引擎實現的!他只是一些數據,至于為何不用腳本來實現?我想應該還是執行效率問題吧!(猜想而已...)

              7.物體管理器
                用來管理場景上出現的物體,也是數據保存。

              8.輸入管理器
                實現一個簡單的單文件系統,就是說在一個地圖文件里包含多個附件進去,例如:模型、貼圖等等。那么就可以實現一個自定義的東西了(例如自定義一個以我的形象做出來的英雄!哈哈!)。然后程序可以直接調用這個模型。

              另外,說說C++程序中應該如何導入綁定函數到腳本中,綁定的方法很多文章都有說,我的BLOG上LUA那部分也有幾篇這樣的文章。我現在要說的是應該綁定什么函數進去腳本引擎中。我覺得,腳本引擎主要是實現一些速度要求不高,但是邏輯性又極強的代碼。那么,相反,對速度要求高,邏輯性比較固定的,就不應該寫到腳本引擎中。
              舉幾個應該在腳本中實現的例子:注冊觸發器、觸發器的執行條件、觸發器執行的事件、地圖初始化之后應該設置的信息(例如攝像機的位置,Load一些東西),這些東西都是邏輯性比較強,也就是說變化是比較大的,如果用數據來驅動,估計很難驅動得了(就好像,N個條件組合,還有邏輯判斷的東西,如何能用數據來表示?例如:3D中的可編程流水線(Shader腳本驅動)就有很多固定流水線(渲染狀態數據驅動)無法實現的)。
              舉幾個不應該在腳本中實現的例子:尋路算法、讀取文件等等需要比較多系統資源的操作。AI,是一個特例,他執行速度要求比較高,但是他的邏輯性又比較強。暴雪公司的選擇是速度,那么他們就需要作一個比較龐大的數據來驅動這些AI(這里編程估計比較復雜了)。我還沒學過AI的算法呢,只知道復雜。不多作評論了,還請高手們給指點指點。
              舉了幾個比較有代表意義的例子。簡單的說,就是應該把一些固定功能的函數盡量用C++來實現,然后綁定到腳本引擎中,然后由腳本引擎來實現相應的邏輯。

              好了,大的東西基本上都說完了。好像也沒說什么,主要就是分析了腳本的實現了。可能說得不明白啊,大家回帖討論一下。

              PS:第一次寫這種文章,寫得不好請見諒!

            如果本文對你的開發有所幫助,并且你手頭恰好有零錢。

            不如打賞我一杯咖啡,鼓勵我繼續分享優秀的文章。




            posted on 2006-11-19 00:20 李錦俊(mybios) 閱讀(8925) 評論(9)  編輯 收藏 引用 所屬分類: C++LUA

            Feedback

            # re: 【原創】魔獸爭霸III 地圖編輯器原理(關鍵是腳本) 2006-11-28 16:16 沒仔細看
            摟主繼續努力  回復  更多評論
              

            # re: 【原創】魔獸爭霸III 地圖編輯器原理(關鍵是腳本) 2006-11-28 22:28 李錦俊
            謝謝支持  回復  更多評論
              

            # 我最近也在研究魔獸地圖編輯器的腳本實現 2007-07-23 11:10 goodboy
            受益匪淺,希望樓主多發布一些相關的文章。  回復  更多評論
              

            # re: 【原創】魔獸爭霸III 地圖編輯器原理(關鍵是腳本)[未登錄] 2007-08-08 09:21 初學者
            殺死敵人單位(非中立敵對)后怎樣能獲得金錢?(請各位幫忙)  回復  更多評論
              

            # re: 【原創】魔獸爭霸III 地圖編輯器原理(關鍵是腳本) 2007-08-20 08:24 jj
            不錯不錯!!o稀飯^_^  回復  更多評論
              

            # re: 【原創】魔獸爭霸III 地圖編輯器原理(關鍵是腳本)[未登錄] 2008-02-10 17:10 QQ
            怎樣用魔獸地圖編輯器把一個不是英雄的單位變成英雄 說說吧  回復  更多評論
              

            # re: 【原創】魔獸爭霸III 地圖編輯器原理(關鍵是腳本) 2008-02-14 11:27 #
            這個把單位變英雄我會,只要調模形,聲音,圖標和武器聲音。單位就能變英雄了。  回復  更多評論
              

            # re: 【原創】魔獸爭霸III 地圖編輯器原理(關鍵是腳本) 2008-02-14 11:29 接上
            補充下:改的單位要是英雄才行!  回復  更多評論
              

            # re: 【原創】魔獸爭霸III 地圖編輯器原理(關鍵是腳本) 2009-03-03 10:21 peerincle
            加油啊~~
            期待著你的最新研究成果~  回復  更多評論
              

            色老头网站久久网| 一本久久精品一区二区| 综合人妻久久一区二区精品| 99久久99久久精品国产片果冻| 一本大道久久香蕉成人网| 久久精品国产乱子伦| 久久久精品波多野结衣| 97久久婷婷五月综合色d啪蜜芽 | 久久亚洲AV成人无码电影| 国产精品成人99久久久久91gav| 一本色综合久久| 99久久中文字幕| 久久久久久伊人高潮影院| 国产99精品久久| 久久久久精品国产亚洲AV无码| 久久九九亚洲精品| 99久久久国产精品免费无卡顿| 久久精品国产日本波多野结衣| 久久久中文字幕| 久久久无码一区二区三区| 久久午夜羞羞影院免费观看| 久久久久久久国产免费看| 久久精品国产99国产电影网 | 午夜精品久久久内射近拍高清| 欧美日韩中文字幕久久伊人| 伊人久久大香线蕉av不变影院| 久久久久亚洲AV成人网人人网站 | 99精品久久精品一区二区| 久久久久99精品成人片| 丁香久久婷婷国产午夜视频| 国产精品视频久久久| 无码AV波多野结衣久久| 91久久精品91久久性色| 亚洲AV日韩精品久久久久久 | 久久青青草原综合伊人| 国产成人无码久久久精品一| 久久综合狠狠综合久久综合88| 无码久久精品国产亚洲Av影片 | 国产香蕉久久精品综合网| 久久久精品国产免大香伊 | 久久夜色精品国产|