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 net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.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.minecraftforge.fml.common.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.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;@Mod.EventBusSubscriber
public 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.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.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.保存所有文件 -> 进行测试:

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

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

  1. Minecraft 1.12.2模组开发(四十五) 水火两用船

    今天我们在MC中实现一艘可以在水中和岩浆中滑行的船 本期教程之前可以先复习一下生物实体教程,会比较好理解一些. 1.船是一种生物实体,所以我们首先要制作船的模型,这里直接使用了原版的船模型,当然你也可 ...

  2. Minecraft 1.12.2模组开发(二十) 导出模组

    模组制作完成后,我们就可以将其导出成为.jar文件,进行发布,供全世界的玩家进行下载游玩了 1.进入模组开发的文件夹 -> 起动cmd控制台 2.输入构建指令等待其构建模组 Windows系统: ...

  3. Minecraft 1.12.2模组开发(三十九) 反应器(TileEntity方块实体)

    说到方块实体(TileEntity),可以理解为一种功能性方块,比如熔炉,箱子,附魔台等. 我们今天来做一个类似于熔炉的反应器 熔炉逻辑: 放入燃料-> 放入物品 -> 获取产出物品 1. ...

  4. Minecraft 1.12.2模组开发(四十九) 维度空间

    1.18.2维度空间教程 1.16.5维度空间教程 我们今天在1.12.2的模组中实现一个自定义维度的生成: 1.在Java包的init包中新建一个InitDimension类注册我们所有的维度: I ...

  5. Minecraft 1.12.2模组开发(四十) buff效果(Potion Effect)

    今天我们在1.12.2的模组中尝试实现几种特殊的buff效果 1.在开发包中新建potion包 -> potion包中新建一个BaseSimplePotion类作为我们药水效果的基类: Base ...

  6. Minecraft 1.16.5模组开发(三十二) 自定义投掷物品实体

    如果你了解过之前我们的实体开发教程,那么本次的教程会相对比较好理解. Minecraft 1.12.2模组开发(七) 实体(魔改Zombie) 我们本次将参考雪球在MC中制作一个属于我们自己的可投掷实 ...

  7. Minecraft 1.16.5模组开发(三十八) 3D盔甲(新)

    Minecraft升级到1.16.5后,3D盔甲的制作方法也跟之前版本稍有不同(主要在第二步.第四步),建议先复习一下往期教程: Minecraft 1.12.2模组开发(三十七) 3D盔甲 1.在b ...

  8. Minecraft 1.12.2模组开发(一) 配置ForgeMDK环境

    我的世界1.12.2 IDEA开发包构建教程已出,更加方便快捷~ 1.12.2Forge模组开发 配置ForgeMDK环境 开发环境:eclipse 1. 我的世界模组开发首先需要配置Forge MD ...

  9. Minecraft 1.16.5模组开发(四十八) 传送门

    Minecraft 1.18.2模组 传送门教程 我们今天在模组中实现一个传送门,让我们可以传送到自己的维度中.(文末附数据包下载链接) 1.在src\main\resources\data中新建一个 ...

  10. Minecraft 1.12.2模组开发(五) 合成配方(有序合成,无序合成)

    方块创建好了之后就需要进行合成来增加游戏的趣味性了,我们本次对合成配方进行讲解 解释:有序合成 & 无序合成 钻石镐必须按照这样的次序进行摆放,为有序合成 钻石锄只要材料够,这两种摆法都可以合 ...

最新文章

  1. 再见,谷歌!再见,算法!
  2. [导入]WindowsXp的两个问题:
  3. Java高级编程细节-动态代理-进阶高级开发必学技能
  4. 信息学奥赛一本通C++语言——1049:晶晶赴约会
  5. 拼多多开除即将拿到股票的安全大佬;虾米音乐将永久关停;GitHub 解禁伊朗开发者使用权
  6. TIOBE 7月编程语言排行:各大城市程序员的工资状况又又又涨了
  7. MapReduce框架下的FP Growth算法概述
  8. java怎么根据编号修改数据类型_Java中怎么根据不同的输入数据类型调用不同的方法呢?...
  9. 成功破解电信限制路由器方法
  10. 多元相关性分析_SPSS分析问卷数据的流程------一篇带你学会SPSS
  11. 索爱小蜜蜂扩音器怎么样啊~
  12. 计算机监理培训计划,监理人员培训计划书.doc
  13. Linux隧道isatap(sit模式)
  14. 企业微信有权限查看通讯录吗?
  15. PDF转PPT怎么转?一键完成格式转换,太方便了
  16. WCF 项目应用连载[4] - 自定义配置 扩展ServiceHost - LServiceHost
  17. powerShell、cmd中命令使用Mysql
  18. 看了 Google 大神 Jeff Dean 的传说,我拜服了~
  19. 深度学习(四):卷积神经网络(CNN)模型结构,前向传播算法和反向传播算法介绍。
  20. 【分享】关闭科学上网后网络连接故障

热门文章

  1. 再次哀悼吧!最佳夸浏览器同步 Xmarks 宣布终止服务
  2. 曲线运动与万有引力公式_万有引力的本质【2019版】
  3. 11gR2 RAC vip和network资源的依赖性与频繁failover
  4. 生物与环境 —— 生命的力量
  5. aws saa aws sap认证助理专业架构师sap考试经验
  6. 第1060期AI100_机器学习日报(2017-08-13)
  7. Android开放root权限
  8. 零延迟!海康大华宇视网络监控摄像头RTSP浏览器网页无插件播放终极解决方案
  9. 在东钿第一次早会分享励志小故事。
  10. java reader类子类_Java之InputStreamReader类的实现