那們我們今天呢,就用自定義AI的功能來做一隻孤僻的貓吧!
我們先把需要的檔案先建立好,一共有:
com.ithome.mymod.entities.LonerCat
: 孤僻貓實體類別。com.ithome.mymod.ai.EntityAILoner
: 自定義的AI工作,用來控制孤僻貓的行為。在LonerCat
這個檔案內,我們會繼承現有的EntityOcelot
類別,並且自訂我們自己的AI行為:
LonerCat
繼承EntityOcelot
後,會跳出紅色底線要我們建立建構子方法:
public class LonerCat extends EntityOcelot {
public LonerCat(World worldIn) {
super(worldIn);
// 設置AI
setupUI();
}
}
private void setupUI() {
this.tasks.taskEntries.clear();
this.targetTasks.taskEntries.clear();
// 自定義的AI工作
tasks.addTask(0, new EntityAILoner(this));
}
// 孤僻貓的類別ID
public static final String name = "LonerCat";
// 是否為第一次與其它實體碰撞
public static AtomicBoolean firstHit = new AtomicBoolean(true);
// 與這個實體碰撞的玩家
public static EntityPlayer thePlayer;
EntityPlayer
與是否為第一次碰撞;在這個EntityOcelot
類別內,有一個onCollideWithPlayer
方法可以供我們覆寫並且定義自己的動作:
@Override
public void onCollideWithPlayer(EntityPlayer player) {
// 是第一次被碰撞 (第一個參數先判斷為true後,就透過第二個參數將這個firstHit更改為false)
if(firstHit.compareAndSet(true, false)) {
// 將AI工作內的判斷變數改為true
EntityAILoner.isHit = true;
// 設定玩家物件
thePlayer = player;
}
}
在EntityAILoner
這個類別中,我們需要繼承EntityAIBase
這個類別,並且實作方法:
EntityAIBase
:
public class EntityAILoner extends EntityAIBase {
}
// 定義實體的物件
private final EntityAnimal animal;
// 用來判斷是否需要執行這個AI工作
public static boolean isHit = false;
// 判斷碰撞的時間,避免太頻繁執行
public static long timer;
public EntityAILoner(EntityAnimal entity) {
this.animal = entity;
// 7可以與大部分的AI工作同時發生
setMutexBits(7);
}
shouldExecute
方法:
@Override
public boolean shouldExecute() {
// 如果碰撞了,開始執行AI工作
if(isHit) {
// 將該變數設定為false等待下次碰撞發生
isHit = false;
return true;
} else {
// 其餘狀況都不執行AI工作
return false;
}
}
startExecuting
方法:
@Override
public void startExecuting() {
// 往碰撞的玩家送出隨機的訊息
LonerCat.thePlayer.addChatComponentMessage(new ChatComponentText(
EnumChatFormatting.RED + messages.get(new Random().nextInt(messages.size()))
));
// 設定執行時間
timer = System.currentTimeMillis();
}
continueExecuting
方法:
@Override
public boolean continueExecuting() {
// 若當前時間與執行時間相差在2秒內,就繼續這個AI工作來避免下一輪的觸發 (避免太頻繁)
if(System.currentTimeMillis() - timer < 2 * 1000) {
return true;
} else {
// 此次AI工作完成,讓LonerCat實體可以開始下一次的碰撞判斷事件了
LonerCat.firstHit.compareAndSet(false, true);
return false;
}
}
private static List<String> messages = new ArrayList<String>();
static {
messages.add("Don't touch me!");
messages.add("Mew~~~~~~~");
messages.add("Are you alone?");
messages.add("Do you wanna be a cat?");
messages.add("What does the fox say?");
}
最後一步驟,來到MyMod
類別中,在preInit
這個方法內需要註冊我們的自定義實體LonerCat
:
@EventHandler
public void preInit(FMLPreInitializationEvent event) {
int availableId = 1;
while (EntityList.getClassFromID(availableId) != null) {
availableId++;
}
EntityRegistry.registerGlobalEntityID(EntityScalePig.class, EntityScalePig.name, availableId);
// 註冊LonerCat類別,找一個可以用的ID給它
while (EntityList.getClassFromID(availableId) != null) {
availableId++;
}
EntityRegistry.registerGlobalEntityID(LonerCat.class, LonerCat.name, availableId);
...(略)
前半段是我們俄羅斯豬的註冊,在後面加上孤僻貓的註冊。
好了,至此你已經完成一個簡單的自定義AI工作,到遊戲內你可以透過:
/summon LonerCat ~2 ~ ~
來產生我們的孤僻貓,然後嘗試去碰牠看看會產生什麼事吧!