概述

在原版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.5
  • getInaccuracy描述的是投掷物的投掷方向不确定度,默认为0
  • getGravityVelocity描述的是投掷物的重力加速度,默认为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) {...}

这个构造方法的第二个参数传入了一种实体,这是怎么回事呢?

其实这种实体确定的就是这个即将被扔出去的投掷物的位置,还有初速度方向,我们覆写ItemGoldenEggonItemRightClick方法,让它的行为和一个普通的鸡蛋类似,即右键扔出对应的实体:

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;
    }

打开游戏试试吧~

results matching ""

    No results matching ""