2015年10月26日 星期一

光暈路亞程式範例

光暈路亞是一個讓「光暈戰記」的玩家可以自己設計程式(使用Lua語言)控制自己的角色在戰場上和別的玩家戰鬥比拚,看看誰設計的人工智慧比較厲害。(詳情)
光暈路亞API >>

以下提供一些常用功能的程式範例供初學者參考:

使用近武能力
if me.mp == 100 then
  if me.currentWeaponInfo.isCloseWeapon then
    me.triggerMouseDown()
  elseif me.nextWeaponInfo.isCloseWeapon then
    me.triggerKeyboard("q")
  end
elseif me.action == "charge" and me.mp == 0 then
  me.triggerMouseUp()
end
解釋:
首先處理當氣是滿的時候,如果手上的是近武器就按滑鼠集氣,否則看看另一手是不是近武,是的話就按q換武器。
接著處理目前動作是正在集氣的時候,此時若mp==0表示集氣完畢,那就放開滑鼠發動技能。

沒有敵人時持槍並檢查彈匣
if me:getAimTarget() == nil then
  if me.currentWeaponInfo.isCloseWeapon then
    if me.nextWeaponInfo.isRangedWeapon then
      me.triggerKeyboard("q")
    end
  elseif me.magazine.available < me.magazine.size then
    me.triggerKeyboard("r")
  end
end
解釋:
沒有在戰鬥狀態時,手持槍類武器可能是大部分狀況下比較合理的選擇。首先檢查目前是不是沒有在瞄準狀態(通常進入戰鬥後會把主要目標設為AimTarget,以持續瞄準)。
如果目前手上拿的是近身武器,然後另一手是遠程武器,就按Q換武器。
否則的話(即手上拿的是遠程武器),檢查如果剩餘子彈量沒到最大狀彈量(即彈匣沒滿),那麼就按R補彈匣。

戰鬥籃球基本款
if me.currentWeaponInfo.type == "戰鬥籃球" then
  goal = game.elecsport:getMyTeam().goal
  if me.pos:distanceTo(goal.pos) < 5 then
    me.turnTo(goal.pos)
    me.triggerMouse()
  else
    me.moveTo(goal)
  end
else
  ball = me.findClosestItem("戰鬥籃球")
  if ball then
    if ball.loc == me.loc then
      me.triggerKeyboard("space")
    else
      me.moveTo(ball)
    end
  end
end
解釋:
首先處理手上拿的是戰鬥籃球的情況。
先取得我們要得分的籃框物件,然後檢查如果籃框距離夠近就把滑鼠位置放在框上(me.turnTo),然後按滑鼠射球。
然後處理手上沒有籃球的情況。
先取得籃球的物件,如果找到籃球的話,檢查如果我正站在籃球所在的格子,就按空白鍵(space)撿球,不然就向球的位置移動過去。

搶旗戰基本款
myTeam = game.elecsport:getMyTeam()

if me:getFlagsCount() == 0 then
  flag = me.findClosestItem(myTeam.color.."旗幟")
  if flag then
    if flag.loc == me.loc then
      me.triggerKeyboard("space")
    else
      me.moveTo(flag)
    end
  end
else
  if me.loc == myTeam.goal.loc then
    me.triggerKeyboard("space")
  else
    me.moveTo(myTeam.goal.loc)
  end
end
解釋:
首先取得我方陣營的物件。 然後先處理身上沒有背著旗子的狀況。
沒旗子時先找到最靠近的旗子,找旗子時,因為紅隊要找紅旗,藍隊要找藍旗,所以使用me.fineClosestItem所給的道具名要用隊伍顏色加上"旗幟"才會找到正確的物件。
在Lua語言中,要把兩個字串連在一起的方式是用兩個點 .. ,如這裏所示範的 myTeam.color.."旗幟"。
找到旗子後,如果正位在旗子的同一格就按空白鍵撿旗子,否則就向旗子走過去。
接著處理身上正背著旗子的狀況。 如果我目前的位置正在我方得分的目標格(myTeam.goal.loc),就按空白鍵放旗得分,否則就向目標格子走去。

整理路亞程式檔
require "sys.game"
require "brain"

if game.mode == "電競比賽" then
  esMode = game.elecsport:getRule("競賽規則")
  if esMode == "搶旗戰" then
    dofile("flag.lua")
  elseif esMode == "戰鬥籃球" then
    dofile("basketball.lua")
  elseif esMode == "攻城戰" then
    dofile("tower.lua")
  else
    dofile("fight.lua")
  end
else
  dofile("fight.lua")
end
解釋:
想要讓你的路亞精通各種模式,就要好好整理一下你的路亞程式檔案。
在main.lua裏我們就不做任何實際的戰鬥處理,只針對不同的遊戲模式,指派執行不同的路亞檔案。
這裏值得一提的是第一行的require "brain",這個指令會去執行brain.lua這個檔案,作用和 dofile("brain.lua") 很像,但由於使用require執行路亞檔案,這個檔案的內容實際上只會被執行一次,接下來雖然持續require這個檔案,但裏面的指令和程式都不會被再次執行,所以這個require很適合用來做個人需要的各種初始化的設定。

接收並回應友軍暗號
for i,event in ipairs(game.events) do
  if event.type == "talk" then
    if not event.playerInfo.isEnemy and event.text == "敵人在我這" then
      me.moveTo(event.playerInfo)
    end
  end
end
解釋:
最外層的for迴圈是用來檢查所有事件(game.events),如果發現有一個事件是看到有人說話(talk),那再檢查說話的人是不是友軍(not enemy)且說話內容為"敵人在我這",如果檢查通過,那就立刻移動到友軍所在的位置。
電競比賽中,最重要的就是團隊合作,使用路亞也能達到團隊合作的效果,只要使用me.talk()就可以傳達訊息給隊友知道。
以上範例只是示範如何接收隊友訊息,實用上還要因應不同的臨場狀況改變回應方式,例如若是收到訊息時正好是和敵人交戰中,那麼可能馬上拋開戰鬥去支援友軍會有點危險。

推動南極冰環島的冰塊
ice = game.findClosest(me, game.findDevices("可推石塊"))
if ice then
  pushLocs = ice:findPushMoveLocs("down")
  if #pushLocs > 0 then
    pushLoc = pushLocs[1]
    if me.loc == pushLoc then
      me.triggerKeyboardDown("s")
    else
      me.moveTo(pushLoc)
    end
  end
end
解釋:
首先找到最近的冰塊。
如果找到ice,則尋找可以往下推的格子(這個範例只舉往下推的例子,路亞設計師可以依需要改變尋找推冰塊的格子)。
如果找到格子的數量大於0,並取第一個做為我們推冰塊的格子(pushLoc)。
接下來判斷我們的角色是否在這個格子上,如果在pushLoc上就按住S鍵不放往下推。
如果還沒到pushLoc這個格子上,就控制角色往pushLoc走去。

5 則留言: