說點純乾貨吧。我本來還想蓄勢鋪墊的。

人對未知的內容都很恐慌。就比如說,我打算復刻一下仙劍奇俠傳的源碼。也就是純c版本的sdlpal的源碼。我要翻譯成c++,lua+qt的版本。

你說,這麼多文件,凡是帶h的c的,cpp的,都是要處理的。

這個遊戲我玩過,但是到了至於怎麼製造的時候,都是摸石頭過河的感覺。我從game_main函數開始,一路順藤摸瓜,先從菜單著手

原理就是現學現用,很多函數,我不懂,我就改數字,改流程。我在屏幕上面加字。不懂的部分,就暫時使用c語言的原版。說白了就是跳過不懂的部分,去進行其他部分內容。

我原來好大喜功,上來就要搞懂數據結構和演算法,結果現實教育了我。慢慢的我改成了順藤摸瓜。

在主循環裡面有一個start frame函數。

而在start frame函數中,分兩部分函數,一部分是gameupdate,這個是核心部分,我們這些新手,是不能上來就動它的。那麼柿子挑軟的捏,就處理下面的那些各種窗口操作。

因為這些東西所見即所得,所有源碼雖然看不懂,但是我們可以通過修改坐標,就知道,這段代碼寫的是什麼地方的圖。

今天主要講的就是鬥爭經驗和方法。

目標就是先翻譯成lua的腳本,這樣的話,修改起來就容易了,光是lua+sdl,是不行的,缺少編輯器。所以要把sdl換成qt,借qt的東風。最終做成仙劍數據可視化編輯器。

流程由寫死的代碼,更換成行為樹。現在的行為樹都有圖形化工具。

今天剩下的時間,我要做

對就是 從物品到裝備選項,

再到裝備整個過程。

在play。c中,調用部分其實很少

這個翻譯起來很簡單,下面的兩個menu函數,可都是大傢伙。待我下一篇慢慢到來。

翻譯過來了。PAL_EquipItemMenuV2(d,select_opt) 真的好長

local functionName=PAL_EquipItemMenuV2
class_t[functionName]=function(self,d,small_env)
local t =small_env or {}
local wItem=t.wItem

local palcommon=d.palcommon
local util=d.util
local bit=d.bit
-------------------------
local fpBALL=d.fpBALL
local fpFBP=d.fpFBP
local g_InputState=d.g_InputState
-----------------------------
local gpScreen=d.gpScreen
local gpGlobals=d.gpGlobals
local gameData=gpGlobals:getGameData()
local playerRoles=gameData:getPlayerRoles()
local rgParty =gpGlobals:getParty()
gpGlobals.wLastUnequippedItem=wItem
--------------------------------
local bg_w,bg_h=d.bg_w,d.bg_h
local size=bg_w*bg_h
bufBackground=ByteVector(size)
palcommon:MKFDecompressChunk(bufBackground,size, EQUIPMENU_BACKGROUND_FBPNUM,fpFBP)

local bufImage=ByteVector(2048)
--------------------------------
local iCurrentPlayer=0
local bSelectedColor = MENUITEM_COLOR_SELECTED_FIRST
local dwColorChangeTime = lua_GetTicks() + (600 / MENUITEM_COLOR_SELECTED_TOTALNUM)
------------------------------------------------------------------------------------
local dwKeyPress
-------------------------
local dst,item,obj
local w,item_id,text,curr_flag
local bColor

while true do
wItem=gpGlobals.wLastUnequippedItem
item =gameData:getObject(wItem):getItem()

palcommon:FBPBlitToSurface(bufBackground,gpScreen)
dst=palcommon:MKFReadChunk(bufImage, 2048,item.wBitmap,fpBALL)
if dst>0 then
palcommon:RLEBlitToSurface(bufImage,gpScreen,palcommon:pal_XY(16,16))
end

--VIDEO_UpdateScreen(nil)
--print(stop)
--util:delay(1000000000)

obj=rgParty:at(iCurrentPlayer)
w=obj.wPlayerRole
for i=0,MAX_PLAYER_EQUIPMENTS do
item_id=playerRoles:getEquipmentItem(i,w)
if item_id ==0 then
else
text=PAL_GetWord(item_id)
PAL_DrawText(text,palcommon:pal_XY(130,11+i*22),MENUITEM_COLOR, TRUE, FALSE)
end
end

----------------------------
PAL_DrawNumber(PAL_GetPlayerAttackStrength(w), 4, palcommon:pal_XY(260, 14),
kNumColorCyan, kNumAlignRight)
PAL_DrawNumber(PAL_GetPlayerMagicStrength(w), 4, palcommon:pal_XY(260, 36),
kNumColorCyan, kNumAlignRight)
PAL_DrawNumber(PAL_GetPlayerDefense(w), 4, palcommon:pal_XY(260, 58),
kNumColorCyan, kNumAlignRight)
PAL_DrawNumber(PAL_GetPlayerDexterity(w), 4, palcommon:pal_XY(260, 80),
kNumColorCyan, kNumAlignRight)
PAL_DrawNumber(PAL_GetPlayerFleeRate(w), 4, palcommon:pal_XY(260, 102),
kNumColorCyan, kNumAlignRight)
-----------------------------------
PAL_CreateBox(palcommon:pal_XY(2, 95), gpGlobals.wMaxPartyMemberIndex, 2, 0, FALSE)

-----------------------------
for i=0,gpGlobals.wMaxPartyMemberIndex do

obj=rgParty:at(i)
w=obj.wPlayerRole
curr_flag =bit.lshift(kItemFlagEquipableByPlayerRole_First,w)

if iCurrentPlayer==i then --curr select
if bit.band(item.wFlags,curr_flag ) ==0 then
bColor=MENUITEM_COLOR_SELECTED_INACTIVE
else
bColor=bSelectedColor
end
else
if bit.band(item.wFlags,curr_flag ) ==0 then
bColor=MENUITEM_COLOR_INACTIVE
else
bColor=MENUITEM_COLOR
end

end
PAL_DrawText(PAL_GetWord(playerRoles:get_rgwName(w)),
palcommon:pal_XY(15, 108 + 18 * i), bColor, TRUE, FALSE);
end

-- draw select equip item name and count
if wItem==0 then
else
PAL_DrawText(PAL_GetWord(wItem), palcommon:pal_XY(5, 70),
MENUITEM_COLOR_CONFIRMED, TRUE, FALSE);
PAL_DrawNumber(PAL_GetItemAmount(wItem), 2, palcommon:pal_XY(65, 73),
kNumColorCyan, kNumAlignRight);
end
--update
VIDEO_UpdateScreen(nil)
--accept input
PAL_ClearKeyState()
util:delay(1)
local item,obj,curr_flag
print(run in PAL_EquipItemMenuV20001)
while true do
--print(run in PAL_EquipItemMenuV20002)

PAL_ProcessEvent()
--print(run in PAL_EquipItemMenuV200021,dwColorChangeTime)
--change the highlight color
if lua_GetTicks()>dwColorChangeTime then
if bSelectedColor+1 >=
(MENUITEM_COLOR_SELECTED_FIRST + MENUITEM_COLOR_SELECTED_TOTALNUM) then
bSelectedColor=MENUITEM_COLOR_SELECTED_FIRST
else
bSelectedColor=bSelectedColor+1
end
dwColorChangeTime=lua_GetTicks()+ (600 / MENUITEM_COLOR_SELECTED_TOTALNUM)
--Redraw the selected item if needed.
w=rgParty:at(iCurrentPlayer).wPlayerRole
item=gameData:getObject(wItem):getItem()
curr_flag=bit.lshift(kItemFlagEquipableByPlayerRole_First,w)
if bit.band(item.wFlags,curr_flag ) ==0 then
else
PAL_DrawText(PAL_GetWord(playerRoles:get_rgwName(w)),
palcommon:pal_XY(15, 108 + 18 * iCurrentPlayer), bSelectedColor, TRUE, TRUE)

end
end
--print(run in PAL_EquipItemMenuV200022)
if g_InputState.dwKeyPress==0 then
else
print(run in PAL_EquipItemMenuV200024)
break
end
-- print(run in PAL_EquipItemMenuV200023)
util:delay(1)
end
print(run in PAL_EquipItemMenuV20007)
--print(stop)
--util:delay(1000000000)
if wItem==0 then
return
end
print(run in PAL_EquipItemMenuV20008)
dwKeyPress=g_InputState.dwKeyPress
if bit.band(dwKeyPress,bit.bor(kKeyUp ,kKeyLeft ) )~=0 then
iCurrentPlayer=iCurrentPlayer-1
if iCurrentPlayer<0 then
iCurrentPlayer=0
end
print(run in PAL_EquipItemMenuV20009)
elseif bit.band(dwKeyPress,bit.bor(kKeyDown ,kKeyRight ) )~=0 then
iCurrentPlayer=iCurrentPlayer+1
if iCurrentPlayer> gpGlobals.wMaxPartyMemberIndex then
iCurrentPlayer=gpGlobals.wMaxPartyMemberIndex
end
print(run in PAL_EquipItemMenuV200010)

elseif bit.band(dwKeyPress,kKeyMenu )~=0 then
print(run in PAL_EquipItemMenuV200011)
return
elseif bit.band(dwKeyPress,kKeySearch )~=0 then
print(run in PAL_EquipItemMenuV200012)
obj=rgParty:at(iCurrentPlayer)
item=gameData:getObject(wItem):getItem()
w=obj.wPlayerRole
curr_flag=bit.lshift(kItemFlagEquipableByPlayerRole_First,w)
print(run in PAL_EquipItemMenuV200013)
if bit.band(item.wFlags,curr_flag ) ==0 then
else
print(run in PAL_EquipItemMenuV200014)
item.wScriptOnEquip=PAL_RunTriggerScript(
item.wScriptOnEquip,
obj.wPlayerRole
)

end

end

end

end

畫背景的代碼

上圖,裝備是這麼畫的

目標裝備人物,高亮部分代碼

這段代碼就翻譯完畢了。

預告,下一篇翻譯的函數。

更新 PAL_PlayerStatusV2 函數部分的翻譯。

local functionName=PAL_PlayerStatusV2
class_t[functionName]=function(self,d,small_env)
local t =small_env or {}
local wItem=t.wItem

local palcommon=d.palcommon
local util=d.util
local bit=d.bit
-------------------------
local fpBALL=d.fpBALL
local fpFBP=d.fpFBP
local fpRGM=d.fpRGM
local g_InputState=d.g_InputState
-----------------------------
local gpScreen=d.gpScreen
local gpSpriteUI=d.gpSpriteUI
local gpGlobals=d.gpGlobals
local gameData=gpGlobals:getGameData()
local playerRoles=gameData:getPlayerRoles()
local rgParty =gpGlobals:getParty()
local exp =gpGlobals:getExp()

--------------------------------------------------------
local rgEquipPos={ {190, 0}, {248, 40}, {252, 102}, {202, 134}, {142, 142}, {82, 126} }

local bg_w,bg_h=d.bg_w,d.bg_h
local size=bg_w*bg_h
bufBackground=ByteVector(size)
--STATUS_BACKGROUND_FBPNUM
palcommon:MKFDecompressChunk(bufBackground,size, EQUIPMENU_BACKGROUND_FBPNUM,fpFBP)

local bufImage=ByteVector(16384) --role image
--------------------------------
local wMaxPartyMemberIndex=gpGlobals.wMaxPartyMemberIndex
local iCurrent = 0

local obj,item,value,level,pos
local curr_exp,ok
local w
while (iCurrent>=0 and iCurrent<= wMaxPartyMemberIndex ) do
obj=rgParty:at(iCurrent)
iPlayerRole =obj.wPlayerRole
--draw bg

palcommon:FBPBlitToSurface(bufBackground,gpScreen)
--exp,level,hp,mp ...
PAL_DrawText(PAL_GetWord(STATUS_LABEL_EXP),palcommon:pal_XY(6, 6), MENUITEM_COLOR, TRUE, FALSE)
PAL_DrawText(PAL_GetWord(STATUS_LABEL_LEVEL),palcommon:pal_XY(6, 32), MENUITEM_COLOR, TRUE, FALSE)
PAL_DrawText(PAL_GetWord(STATUS_LABEL_HP),palcommon:pal_XY(6, 54), MENUITEM_COLOR, TRUE, FALSE)
PAL_DrawText(PAL_GetWord(STATUS_LABEL_MP),palcommon:pal_XY(6, 76), MENUITEM_COLOR, TRUE, FALSE)
PAL_DrawText(PAL_GetWord(STATUS_LABEL_ATTACKPOWER),palcommon:pal_XY(6, 98), MENUITEM_COLOR, TRUE, FALSE)
PAL_DrawText(PAL_GetWord(STATUS_LABEL_MAGICPOWER),palcommon:pal_XY(6, 118), MENUITEM_COLOR, TRUE, FALSE)
PAL_DrawText(PAL_GetWord(STATUS_LABEL_RESISTANCE),palcommon:pal_XY(6, 138), MENUITEM_COLOR, TRUE, FALSE)
PAL_DrawText(PAL_GetWord(STATUS_LABEL_DEXTERITY),palcommon:pal_XY(6, 158), MENUITEM_COLOR, TRUE, FALSE)
PAL_DrawText(PAL_GetWord(STATUS_LABEL_FLEERATE),palcommon:pal_XY(6, 178), MENUITEM_COLOR, TRUE, FALSE)
-- player name
PAL_DrawText(PAL_GetWord(playerRoles:get_rgwName(iPlayerRole)),
palcommon:pal_XY(110, 8), MENUITEM_COLOR_CONFIRMED, TRUE, FALSE)
----------------------------------
curr_exp =exp:getExpItem("rgPrimaryExp",iPlayerRole)
PAL_DrawNumber(curr_exp.wExp, 5,palcommon:pal_XY(58, 6), kNumColorYellow, kNumAlignRight);
level=playerRoles:get_rgwLevel(iPlayerRole)
value =gameData:getLevelUpExp(level)
PAL_DrawNumber(value ,5, palcommon:pal_XY(58, 15), kNumColorCyan, kNumAlignRight);
PAL_DrawNumber(level, 2,palcommon:pal_XY(54, 35), kNumColorYellow, kNumAlignRight);

palcommon:pal_RLEBlitToSurface(
palcommon:pal_SpriteGetFrame(gpSpriteUI, SPRITENUM_SLASH),
gpScreen,
palcommon:pal_XY(65,58)
)
palcommon:pal_RLEBlitToSurface(
palcommon:pal_SpriteGetFrame(gpSpriteUI, SPRITENUM_SLASH),
gpScreen,palcommon:pal_XY(65, 80))

PAL_DrawNumber(playerRoles:get_rgwHP(iPlayerRole), 4, palcommon:pal_XY(42, 56),
kNumColorYellow, kNumAlignRight);
PAL_DrawNumber(playerRoles:get_rgwMaxHP(iPlayerRole), 4, palcommon:pal_XY(63, 61),
kNumColorBlue, kNumAlignRight);
PAL_DrawNumber(playerRoles:get_rgwMP(iPlayerRole), 4, palcommon:pal_XY(42, 78),
kNumColorYellow, kNumAlignRight);
PAL_DrawNumber(playerRoles:get_rgwMaxMP(iPlayerRole), 4, palcommon:pal_XY(63, 83),
kNumColorBlue, kNumAlignRight);

PAL_DrawNumber(PAL_GetPlayerAttackStrength(iPlayerRole), 4,
palcommon:pal_XY(42, 102), kNumColorYellow, kNumAlignRight);
PAL_DrawNumber(PAL_GetPlayerMagicStrength(iPlayerRole), 4,
palcommon:pal_XY(42, 122), kNumColorYellow, kNumAlignRight);
PAL_DrawNumber(PAL_GetPlayerDefense(iPlayerRole), 4,
palcommon:pal_XY(42, 142), kNumColorYellow, kNumAlignRight);
PAL_DrawNumber(PAL_GetPlayerDexterity(iPlayerRole), 4,
palcommon:pal_XY(42, 162), kNumColorYellow, kNumAlignRight);
PAL_DrawNumber(PAL_GetPlayerFleeRate(iPlayerRole), 4,
palcommon:pal_XY(42, 182), kNumColorYellow, kNumAlignRight);

for i=0,MAX_PLAYER_EQUIPMENTS-1 do
w=playerRoles:getEquipmentItem(i,iPlayerRole)
if w==0 then
else
item=gameData:getObject(w):getItem()
ok=palcommon:MKFReadChunk(bufImage,16384,item.wBitmap,fpBALL)
if ok>0 then
pos =rgEquipPos[i+1]
--draw image
palcommon:RLEBlitToSurface(bufImage,gpScreen,palcommon:pal_XY(pos[1],pos[2]))
--draw text

PAL_DrawText(
PAL_GetWord(w),
palcommon:pal_XY(pos[1]+5,pos[2]+38),

STATUS_COLOR_EQUIPMENT,TRUE,FALSE
)

end
end
end
ok =palcommon:MKFReadChunk(bufImage,16384,playerRoles:get_rgwAvatar(iPlayerRole),fpRGM)
if ok > 0 then
palcommon:RLEBlitToSurface(bufImage, gpScreen, palcommon:pal_XY(110, 30))
end
---draw all poisons

y=58

for i=0,MAX_POISONS-1 do
w=gpGlobals:getPoisonStatusItem(i,iCurrent).wPoisonID
item=gameData:getObject(w):getPoison()
if w~=0 and item.wPoisonLevel<=3 then
PAL_DrawText(PAL_GetWord(w),palcommon:pal_XY(185, y),
item.wColor + 10, TRUE, FALSE)
-------
y =y+18
end
end

VIDEO_UpdateScreen(nil)
PAL_ClearKeyState()

while true do
util:delay(1)
--PAL_ProcessEvent()
-------------------------------------
dwKeyPress=g_InputState.dwKeyPress

if bit.band(dwKeyPress,kKeyMenu)~=0 then
iCurrent=-1
break
elseif bit.band(dwKeyPress,bit.bor( kKeyLeft,kKeyUp) ) ~=0 then
iCurrent=iCurrent-1
break
elseif bit.band(dwKeyPress,bit.bor(kKeyRight,kKeyDown,kKeySearch) )~=0 then
iCurrent=iCurrent+1
break
end
end

end

--VIDEO_UpdateScreen(nil)

end

更新PAL_SearchV2部分,這下 菜單操作的部分基本完成了。

local functionName=PAL_SearchV2
class_t[functionName]=function(self,d,small_env)
local item_menu_helper=d.item_menu_helper
local palcommon=d.palcommon
local menu_helper=d.menu_helper
local bit=d.bit
local util=d.util
local gpGlobals=d.gpGlobals
local gameData=gpGlobals:getGameData()
local rgParty=gpGlobals:getParty()
------------------------------
local rgPos={}
local x, y, xOffset, yOffset
local viewport,partyoffset =gpGlobals.viewport,gpGlobals.partyoffset
x=palcommon:get_X(viewport)+palcommon:get_X(partyoffset)
y=palcommon:get_Y(viewport)+palcommon:get_Y(partyoffset)

print(string.format("%x,%x,%x,%x",x,y,viewport,partyoffset))
local wPartyDirection=gpGlobals.wPartyDirection
--logic error
--if bit.bor(wPartyDirection,kDirNorth,kDirEast) FALSE then
if wPartyDirection==kDirNorth
or wPartyDirection==kDirEast then
xOffset=16
else
xOffset=-16
end
--logic error
--if bit.bor(wPartyDirection,kDirEast,kDirSouth)~=FALSE then
if wPartyDirection==kDirEast
or wPartyDirection==kDirSouth then
yOffset=8
else
yOffset=-8
end

rgPos[0] =palcommon:pal_XY(x,y)
--get 4 player pos in the party
for i=0,3 do
rgPos[i*3+1]=palcommon:pal_XY(x + xOffset, y + yOffset)
rgPos[i*3+2]=palcommon:pal_XY(x, y + yOffset * 2)
rgPos[i*3+3]=palcommon:pal_XY(x + xOffset, y)

x =x+ xOffset
y =y+ yOffset
end

-------------------
local pos
local dx, dy, dh
local ex, ey, eh
local p
--------------------
local wMaxPartyMemberIndex=gpGlobals.wMaxPartyMemberIndex
local wNumScene,wEventObjectIndex,curr_scene,next_scene
print(run PAL_SearchV2 004)
for i=0,12 do
pos =rgPos[i]
dx =math.floor( palcommon:get_X(pos)/32 )
dy =math.floor(palcommon:get_Y(pos)/16 )
if palcommon:get_X(pos)%32 ==0 then
dh=0
else dh=1
end

--loop through all event objects-----------------------------
wNumScene=gpGlobals.wNumScene
curr_scene=gameData:getScene(wNumScene-1)
next_scene=gameData:getScene(wNumScene)
--wEventObjectIndex=curr_scene.wEventObjectIndex

for k=curr_scene.wEventObjectIndex,
next_scene.wEventObjectIndex-1 do
---------------------------------------
p=gameData:getLprgEventObject(k)
ex=math.floor(p.x/32)
ey=math.floor(p.y/16)
if p.x%32 ~=0 then
eh=1
else eh=0
end
--[[
print(i,k,
(p.sState<=0),
(math.abs(dx - ex)<=0.5 ),
(math.abs(dy - ey)<=0.5) ,
dx,ex,dy,ey

)
]]
if (p.sState<=0) or
(p.wTriggerMode >= kTriggerTouchNear) or
(p.wTriggerMode * 6 - 4 < i ) or
(dx ~= ex) or
(dy ~= ey) or
(dh ~= eh) then
----------------------------------------------
else
print(run PAL_SearchV2 008)
if p.nSpriteFrames * 4 > p.wCurrentFrameNum then
p.wCurrentFrameNum=0
p.wDirection =(gpGlobals.wPartyDirection+2)%4
for l=0,wMaxPartyMemberIndex do
--All party members should face the event object
rgParty:at(l).wFrame =wPartyDirection*3

end
PAL_MakeScene()
VIDEO_UpdateScreen(nil)
end
--Execute the script
print(p.wTriggerScript=,p.wTriggerScript)
p.wTriggerScript = PAL_RunTriggerScript(p.wTriggerScript, k + 1)

--Clear inputs and delay for a short time
util:delay(50)
PAL_ClearKeyState()
print(run PAL_SearchV2 stop)
return
end

end
end
for i=0,12 do
pos=rgPos[i]
print(string.format("i=%d 0x%8x %d %d",i,rgPos[i],bit.band(pos,0xFFFF),
bit.band(bit.rshift(pos,16),0xFFFF ) ) )
end

end

預告。

這3個函數翻譯完了,主幹部分基本完事了,就需要具體細化了,

這個研究課題能不能進行下去,全靠你們了,希望多給我點口頭鼓勵啊,


推薦閱讀:
相关文章