1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > Minecraft 1.12.2模组开发(五十五) 动画生物实体

Minecraft 1.12.2模组开发(五十五) 动画生物实体

时间:2021-06-04 15:09:41

相关推荐

Minecraft 1.12.2模组开发(五十五) 动画生物实体

1.16.5动画生物实体教程

1.18.2动画生物实体教程

效果展示效果展示效果展示

今天我们尝试在1.12.2中添加一个能够做各种动作的生物实体,由于1.12.2和1.16以上的版本在代码接口上有较大区别,所以和往期教程的内容可能不太一样。

1.首先,为了实现这些效果,我们需要首先使用到geckolib模组,可遗憾的是geckolib目前已经不支持1.12.2的开发了,所以我们可以使用一个开发包进行开发1.12.2-geckolib开发包下载地址:

下载后并导入到Idea中,下图中红色方框里的就是我们的geckolib动画制作库了:

2.我们在blockbench中制作一个实体并配套制作其动画文件,相关教程参考Minecraft 模组动画制作教程:

之后我们导出相对应的geo模型文件和animation动画文件:

3.模型制作完成,接下来需要制作生物实体类,在entities包中新建一个我们的实体类WhiplashEntity,继承自僵尸类:

WhiplashEntity.java

package com.fred.jianghun.entities;import javax.annotation.Nullable;import com.fred.jianghun.software.bernie.geckolib3.core.IAnimatable;import com.fred.jianghun.software.bernie.geckolib3.core.IAnimationTickable;import com.fred.jianghun.software.bernie.geckolib3.core.PlayState;import com.fred.jianghun.software.bernie.geckolib3.core.builder.AnimationBuilder;import com.fred.jianghun.software.bernie.geckolib3.core.controller.AnimationController;import com.fred.jianghun.software.bernie.geckolib3.core.event.predicate.AnimationEvent;import com.fred.jianghun.software.bernie.geckolib3.core.manager.AnimationData;import com.fred.jianghun.software.bernie.geckolib3.core.manager.AnimationFactory;import ibxm.Player;import net.minecraft.entity.Entity;import net.minecraft.entity.EntityLivingBase;import net.minecraft.entity.IEntityLivingData;import net.minecraft.entity.SharedMonsterAttributes;import net.minecraft.entity.ai.*;import net.minecraft.entity.monster.EntityIronGolem;import net.minecraft.entity.monster.EntityPigZombie;import net.minecraft.entity.monster.EntityZombie;import net.minecraft.entity.passive.EntityVillager;import net.minecraft.entity.player.EntityPlayer;import net.minecraft.nbt.NBTTagCompound;import work.datasync.DataParameter;import work.datasync.DataSerializers;import work.datasync.EntityDataManager;import net.minecraft.world.World;import java.util.Random;public class WhiplashEntity extends EntityZombie implements IAnimatable, IAnimationTickable {//public static Server config = DoomConfig.SERVER;public static final DataParameter<Integer> STATE = EntityDataManager.createKey(DemonEntity.class,DataSerializers.VARINT);private AnimationFactory factory = new AnimationFactory(this);protected int attackTimer;public WhiplashEntity(World worldIn) {super(worldIn);this.dataManager.register(STATE, Integer.valueOf(0));this.attackTimer=15;}@Overridepublic void applyEntityAttributes() {super.applyEntityAttributes();this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(30.0D);this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(8.0D);this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.25D);this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(25.0D);this.getEntityAttribute(SharedMonsterAttributes.KNOCKBACK_RESISTANCE).setBaseValue(0.0D);}public int getAttckingState() {return this.dataManager.get(STATE);}public void setAttackingState(int time) {this.dataManager.set(STATE, time);}//@Override//protected void defineSynchedData() {//super.defineSynchedData();//this.dataManager.define(STATE, 0);//}//设置该生物平时走路、站立、死亡的动画private <E extends IAnimatable> PlayState predicate(AnimationEvent<E> event) {if (event.isMoving()) {event.getController().setAnimation(new AnimationBuilder().addAnimation("walking", true));return PlayState.CONTINUE;}if ((this.dead || this.getHealth() < 0.01 || this.isDead)) {event.getController().setAnimation(new AnimationBuilder().addAnimation("death", false));return PlayState.CONTINUE;}event.getController().setAnimation(new AnimationBuilder().addAnimation("idle", true));return PlayState.CONTINUE;}//设置该生物两种攻击动画private <E extends IAnimatable> PlayState predicate1(AnimationEvent<E> event) {if (!event.isMoving() && this.dataManager.get(STATE) == 1&& !(this.dead || this.getHealth() < 0.01 || this.isDead)) {event.getController().setAnimation(new AnimationBuilder().playOnce("attacking"));return PlayState.CONTINUE;}if (event.isMoving() && this.dataManager.get(STATE) == 2&& !(this.dead || this.getHealth() < 0.01 || this.isDead)) {event.getController().setAnimation(new AnimationBuilder().playOnce("attacking_moving"));return PlayState.CONTINUE;}else{event.getController().setAnimation(new AnimationBuilder().addAnimation("attacking", true));}return PlayState.STOP;}@Overridepublic void registerControllers(AnimationData data) {data.addAnimationController(new AnimationController<WhiplashEntity>(this, "controller", 2, this::predicate));data.addAnimationController(new AnimationController<WhiplashEntity>(this, "controller1", 2, this::predicate1));}//对该生物的攻击状态进行判断@Overridepublic void onLivingUpdate(){if(this.attackTimer>=0){EntityLivingBase livingentity = this.getAttackTarget();if (livingentity!=null && this.canEntityBeSeen(livingentity)) {World world = this.world;this.attackTimer--;this.getNavigator().tryMoveToEntityLiving(livingentity, 1.5D);System.out.println(this.attackTimer);if (this.attackTimer == 5 && this.dataManager.get(STATE)==Integer.valueOf(0)) {//如果该生物血量介于[22,30]或者[8,16]就设置其攻击状态为2,反之为1if ((this.getHealth() < 30F && this.getHealth() > 22F) ||(this.getHealth() < 16F && this.getHealth() > 8F))this.setAttackingState(2);else {this.setAttackingState(1);}}}}else{//没有发现敌人时就将攻击状态清空this.setAttackingState(0);this.attackTimer = 15;}super.onLivingUpdate();}@Overridepublic AnimationFactory getFactory() {return this.factory;}//@Override//protected void tickDeath() {//++this.deathTime;//if (this.deathTime == 60) {//this.remove();//this.dropExperience();//}//}//@Override//public IPacket<?> getAddEntityPacket() {//return NetworkHooks.getEntitySpawningPacket(this);//}//生物AI设置@Overrideprotected void initEntityAI() {this.tasks.addTask(0, new EntityAISwimming(this));this.tasks.addTask(2, new EntityAIZombieAttack(this, 1.0D, false));this.tasks.addTask(5, new EntityAIMoveTowardsRestriction(this, 1.0D));this.tasks.addTask(7, new EntityAIWanderAvoidWater(this, 1.0D));this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));this.tasks.addTask(8, new EntityAILookIdle(this));this.applyEntityAI();}//生物攻击目标设置(主动攻击哪些目标)protected void applyEntityAI() {//this.targetSelector.addGoal(4, new DemonAttackGoal(this, 1.0D, false, 1));//this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, PlayerEntity.class, true));//this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillagerEntity.class, false));//this.targetSelector.addGoal(1, (new HurtByTargetGoal(this).setAlertOthers()));this.tasks.addTask(6, new EntityAIMoveThroughVillage(this, 1.0D, false));this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, new Class[] {EntityPigZombie.class}));this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, true));this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityVillager.class, false));this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityIronGolem.class, true));}@Overridepublic void readEntityFromNBT(NBTTagCompound compound) {super.readEntityFromNBT(compound);}//@Nullable//@Override//public IEntityLivingData finalizeSpawn(IServerWorld worldIn, DifficultyInstance difficultyIn, SpawnReason reason,// @Nullable ILivingEntityData spawnDataIn, @Nullable CompoundNBT dataTag) {//spawnDataIn = super.finalizeSpawn(worldIn, difficultyIn, reason, spawnDataIn, dataTag);//return spawnDataIn;//}////@Override//public boolean isBaby() {//return false;//}protected boolean shouldDrown() {return false;}protected boolean shouldBurnInDay() {return false;}@Overridepublic void tick() {}@Overridepublic int tickTimer() {return 0;}}

4.新建生物实体模型文件WhiplashModel类:

WhiplashModel.java

package com.fred.jianghun.entities.model;import com.fred.jianghun.Main;import com.fred.jianghun.entities.WhiplashEntity;import com.fred.jianghun.software.bernie.geckolib3.model.AnimatedGeoModel;import net.minecraft.util.ResourceLocation;public class WhiplashModel extends AnimatedGeoModel<WhiplashEntity> {//指定geo模型文件地址@Overridepublic ResourceLocation getModelLocation(WhiplashEntity object) {return new ResourceLocation(Main.MODID, "geo/whiplash.geo.json");}//指定贴图文件地址@Overridepublic ResourceLocation getTextureLocation(WhiplashEntity object) {return new ResourceLocation(Main.MODID, "textures/entity/whiplash.png");}//指定动画文件地址@Overridepublic ResourceLocation getAnimationFileLocation(WhiplashEntity object) {return new ResourceLocation(Main.MODID, "animations/whiplash.animation.json");}}

5.新建模型渲染类WhiplashRender。

WhiplashRender.java

package com.fred.jianghun.entities.render;import com.fred.jianghun.entities.WhiplashEntity;import com.fred.jianghun.entities.model.BikeModel;import com.fred.jianghun.entities.model.WhiplashModel;import com.fred.jianghun.software.bernie.geckolib3.renderers.geo.GeoEntityRenderer;import net.minecraft.client.renderer.entity.RenderManager;import net.minecraft.util.ResourceLocation;public class WhiplashRender extends GeoEntityRenderer<WhiplashEntity> {//将我们上一步中的模型传入其中public WhiplashRender(RenderManager renderManager) {super(renderManager, new WhiplashModel());}@Overrideprotected float getDeathMaxRotation(WhiplashEntity entityLivingBaseIn) {return 0.0F;}}

RenderHandler中将我们的渲染文件进行注册:

RenderHandler.java

package com.fred.jianghun.init;import com.fred.jianghun.entities.WhiplashEntity;import com.fred.jianghun.entities.render.WhiplashRender;import net.minecraftforge.fml.client.registry.RenderingRegistry;public class RenderHandler {public static void registerEntityRenders() {//模型渲染文件注册RenderingRegistry.registerEntityRenderingHandler(WhiplashEntity.class, WhiplashRender::new);}}

6.在EntityInit中将我们的生物实体进行注册:

EntityInit.java

package com.fred.jianghun.init;import com.fred.jianghun.Main;import com.fred.jianghun.entities.WhiplashEntity;import net.minecraft.entity.Entity;import net.minecraft.util.ResourceLocation;import net.minecraft.util.datafix.DataFixer;import net.mon.registry.EntityRegistry;public class EntityInit {private static int ENTITY_NEXT_ID = 1;public static void registerEntities() {registerEntity("whiplash", WhiplashEntity.class, ENTITY_NEXT_ID, 30, 2330893, 16144);DataFixer datafixer = new DataFixer(1343);}private static void registerEntity(String name, Class<? extends Entity> entity, int id, int range, int color1, int color2){EntityRegistry.registerModEntity(new ResourceLocation(Main.MODID + ":" + name),entity,name,id,Main.instance,range,1,true,color1, color2);ENTITY_NEXT_ID++;}}

RegistryHandler中将我们的EntityInit类和RenderHandler类进行注册:

RegistryHandler.java

package com.fred.jianghun.init;import com.fred.jianghun.utils.IhasModel;import net.minecraft.block.Block;import net.minecraft.item.Item;import net.minecraftforge.client.event.ModelRegistryEvent;import net.minecraftforge.event.RegistryEvent;import net.mon.Mod;import net.mon.event.FMLPreInitializationEvent;import net.mon.eventhandler.SubscribeEvent;@Mod.EventBusSubscriberpublic class RegistryHandler {@SubscribeEventpublic static void onItemRegister(RegistryEvent.Register<Item> event){event.getRegistry().registerAll(ItemInit.ITEMS.toArray(new Item[0]));}@SubscribeEventpublic static void onBlockRegister(RegistryEvent.Register<Block> event) {event.getRegistry().registerAll(BlockInit.BLOCKS.toArray(new Block[0]));//TileEntityHandler.registerTileEntities();}@SubscribeEventpublic static void onModelRegister(ModelRegistryEvent event){for(Item item: ItemInit.ITEMS){if(item instanceof IhasModel){((IhasModel)item).registerModels();}}for(Block block : BlockInit.BLOCKS){if (block instanceof IhasModel){((IhasModel)block).registerModels();}}//将RenderHandler类进行注册RenderHandler.registerEntityRenders();}public static void preInitRegistries(FMLPreInitializationEvent event){//将EntityInit类进行注册EntityInit.registerEntities();}}

7.在项目主类中的preInit和init类中添加一些代码:

Main.java

import com.fred.jianghun.init.RegistryHandler;import com.fred.jianghun.proxy.ProxyBase;import com.fred.jianghun.software.bernie.geckolib3.resource.ResourceListener;import com.fred.jianghun.tabs.ItemTab;import net.minecraft.creativetab.CreativeTabs;import net.minecraft.init.Blocks;import net.mon.FMLCommonHandler;import net.mon.Mod;import net.mon.Mod.EventHandler;import net.mon.SidedProxy;import net.mon.event.FMLInitializationEvent;import net.mon.event.FMLPreInitializationEvent;import net.minecraftforge.fml.relauncher.Side;import net.minecraftforge.fml.relauncher.SideOnly;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;import java.util.concurrent.FutureTask;@Mod(modid = Main.MODID, name = Main.NAME, version = Main.VERSION)public class Main{public static final String MODID = "jianghun";public static final String NAME = "Jiang Hun";public static final String VERSION = "1.0";public static final String CLIENT_PROXY = "com.fred.jianghun.proxy.ClientProxy";public static final String SERVER_PROXY = "com.fred.jianghun.proxy.ServerProxy";public static boolean hasInitialized;public static final Logger LOGGER = LogManager.getLogger();@Mod.Instancepublic static Main instance;@SidedProxy(clientSide = CLIENT_PROXY,serverSide = SERVER_PROXY)public static ProxyBase proxy;@EventHandlerpublic void preInit(FMLPreInitializationEvent event) {//注册机初始化RegistryHandler.preInitRegistries(event);}@EventHandlerpublic void init(FMLInitializationEvent event){//Geckolib初始化代码,很重要!initialize();}public static CreativeTabs ITEM_TAB = new ItemTab();public static void initialize() {if (!hasInitialized) {FMLCommonHandler.callFuture(new FutureTask<>(() -> {if (FMLCommonHandler.instance().getSide() == Side.CLIENT) {doOnlyOnClient();}}, null));}hasInitialized = true;}@SideOnly(Side.CLIENT)private static void doOnlyOnClient() {ResourceListener.registerReloadListener();}}

8.代码部分结束,来到资源包制作环节

在resources\assets\你的modid中的lang包中的en_us.lang添加刷生物实体英文名称:

en_us.lang

entity.whiplash.name=Whiplash

zh_cn.lang中添加中文名称:

zh_cn.lang

entity.whiplash.name=尖刺

在textures\entity中添加生物实体的皮肤贴图:

在animations和geo中分别添加我们的动画和模型文件:

9.保存所有文件 -> 进行测试:

异形大战铁血战士(幻视)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。