概述
在原版Minecraft中,投掷物包括鸡蛋、雪球、末影珍珠、药水、附魔之瓶等,这些投掷物都有一些共同的特点:
- 运动模型简单,大多只需要考虑到重力因素,碰到实体或者方块上时随即消失并产生效果
- 渲染模型类似,渲染模型都是一个物品,而且不同角度看到的物品总是面向观察者的
- 生成方式固定,初速度大多是投掷生物的面朝方向
新的投掷物和注册
Minecraft的所有投掷物,都实现了IProjectile
接口,并提供了一个名为EntityThrowable
的类的部分实现。这里我们仿照鸡蛋,在包com.github.ustc_zzzz.fmltutor.entity
下新建一个文件EntityGoldenEgg.java
:
src/main/java/com/github/ustc_zzzz/fmltutor/entity/EntityGoldenEgg.java:
package com.github.ustc_zzzz.fmltutor.entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.projectile.EntityThrowable;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.world.World;
public class EntityGoldenEgg extends EntityThrowable
{
public EntityGoldenEgg(World worldIn)
{
super(worldIn);
}
public EntityGoldenEgg(World worldIn, EntityLivingBase throwerIn)
{
super(worldIn, throwerIn);
}
public EntityGoldenEgg(World worldIn, double x, double y, double z)
{
super(worldIn, x, y, z);
}
@Override
protected void onImpact(MovingObjectPosition movingObjectPosition)
{
// TODO
}
}
作为一个EntityThrowable
类的子类,首先我们要覆写三个构造方法。剩下那个名为onImpact
的方法会在投掷物碰到实体或者方块上时调用。
不过我们现在把目光移开,放到下面三个方法上来:
getVelocity
描述的是投掷物的初速度,默认为1.5getInaccuracy
描述的是投掷物的投掷方向不确定度,默认为0getGravityVelocity
描述的是投掷物的重力加速度,默认为0.03,和实际生活中的重力加速度(约为0.0245)差不多
通过对这三个方法的覆写,我们就可以设置这三个量,进而改变投掷物的一些固有属性。
这里我们实现了onImpact
的方法,作者为了演示,在这里做了一个简单的把砸中的鸡替换成黄金鸡的实现:
src/main/java/com/github/ustc_zzzz/fmltutor/entity/EntityGoldenEgg.java(部分):
@Override
protected void onImpact(MovingObjectPosition movingObjectPosition)
{
if (!this.worldObj.isRemote)
{
if (movingObjectPosition.entityHit instanceof EntityChicken)
{
EntityChicken originalChicken = (EntityChicken) movingObjectPosition.entityHit;
EntityGoldenChicken goldenChicken = new EntityGoldenChicken(this.worldObj);
goldenChicken.setGrowingAge(originalChicken.getGrowingAge());
goldenChicken.setLocationAndAngles(originalChicken.posX, originalChicken.posY, originalChicken.posZ,
originalChicken.rotationYaw, originalChicken.rotationPitch);
originalChicken.setDead();
this.worldObj.spawnEntityInWorld(goldenChicken);
}
else
{
this.worldObj.spawnEntityInWorld(new EntityItem(this.worldObj, this.posX, this.posY, this.posZ,
new ItemStack(ItemLoader.goldenEgg)));
}
this.setDead();
}
}
然后我们注册这个投掷物实体:
src/main/java/com/github/ustc_zzzz/fmltutor/entity/EntityLoader.java(部分):
public EntityLoader()
{
registerEntity(EntityGoldenChicken.class, "GoldenChicken", 80, 3, true);
registerEntityEgg(EntityGoldenChicken.class, 0xffff66, 0x660000);
registerEntitySpawn(EntityGoldenChicken.class, 8, 2, 4, EnumCreatureType.CREATURE, BiomeGenBase.plains,
BiomeGenBase.desert);
registerEntity(EntityGoldenEgg.class, "GoldenEgg", 64, 10, true);
}
投掷物渲染
RenderSnowball
类是所有投掷物的渲染通用类,其构造方法如下:
public RenderSnowball(RenderManager renderManagerIn, Item item, RenderItem renderItem) {...}
第一个参数和生物渲染一样,这里没有什么好说的,第二个参数表示的就是渲染用的该物品,第三个参数比较固定,使用Minecraft.getMinecraft().getRenderItem()
就可以了。
我们先在包com.github.ustc_zzzz.fmltutor.client.entity.render
下新建一个RenderGoldenEgg
类:
src/main/java/com/github/ustc_zzzz/fmltutor/client/entity/render/RenderGoldenEgg.java:
package com.github.ustc_zzzz.fmltutor.client.entity.render;
import com.github.ustc_zzzz.fmltutor.entity.EntityGoldenEgg;
import com.github.ustc_zzzz.fmltutor.item.ItemLoader;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.entity.RenderSnowball;
public class RenderGoldenEgg extends RenderSnowball<EntityGoldenEgg>
{
public RenderGoldenEgg(RenderManager renderManagerIn)
{
super(renderManagerIn, ItemLoader.goldenEgg, Minecraft.getMinecraft().getRenderItem());
}
}
然后我们注册:
src/main/java/com/github/ustc_zzzz/fmltutor/entity/EntityLoader.java(部分):
@SideOnly(Side.CLIENT)
public static void registerRenders()
{
registerEntityRender(EntityGoldenChicken.class, RenderGoldenChicken.class);
registerEntityRender(EntityGoldenEgg.class, RenderGoldenEgg.class);
}
投掷物生成
我们注意到,EntityThrowable
类有一个构造方法不太平凡:
public EntityThrowable(World worldIn, EntityLivingBase throwerIn) {...}
这个构造方法的第二个参数传入了一种实体,这是怎么回事呢?
其实这种实体确定的就是这个即将被扔出去的投掷物的位置,还有初速度方向,我们覆写ItemGoldenEgg
的onItemRightClick
方法,让它的行为和一个普通的鸡蛋类似,即右键扔出对应的实体:
src/main/java/com/github/ustc_zzzz/fmltutor/item/ItemGoldenEgg.java(部分):
@Override
public ItemStack onItemRightClick(ItemStack itemStackIn, World worldIn, EntityPlayer playerIn)
{
if (!playerIn.capabilities.isCreativeMode)
{
--itemStackIn.stackSize;
}
if (!worldIn.isRemote)
{
worldIn.spawnEntityInWorld(new EntityGoldenEgg(worldIn, playerIn));
}
return itemStackIn;
}
打开游戏试试吧~