Posted November 27, 20177 yr I am here with another question. My Entity / Projectile class is down below. I already managed to simulate gravity and decaying my entity after falling onto the ground, however I have no clue on how to use the Motion variables. Does someone know how Minecraft uses them? I already looked up the arrow class, but didn't really understand the process. As an example, I want to shoot my entity into a specified direction, starting at fast Speed and then slowing down. package net.zeldadungeons.init.entity.projectile; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.IProjectile; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.projectile.EntityArrow; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import net.minecraftforge.client.event.sound.SoundEvent; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import net.zeldadungeons.util.Log; public class EntitySlingshotPellet extends Entity implements IProjectile { private Entity shootingEntity; private boolean inGround; private int ticksInGround; private int ticksInAir; public EntitySlingshotPellet(World worldIn) { super(worldIn); this.setSize(0.5F, 0.5F); } public EntitySlingshotPellet(World worldIn, double x, double y, double z) { this(worldIn); this.setPosition(x, y, z); } public EntitySlingshotPellet(World worldIn, EntityLivingBase shooter) { this(worldIn, shooter.posX, shooter.posY + (double)shooter.getEyeHeight() - 0.10000000149011612D, shooter.posZ); this.shootingEntity = shooter; } public void onUpdate() { super.onUpdate(); BlockPos blockpos = new BlockPos(this.posX, this.posY, this.posZ); IBlockState iblockstate = this.world.getBlockState(blockpos); Block block = iblockstate.getBlock(); if (iblockstate.getMaterial() != Material.AIR) { AxisAlignedBB axisalignedbb = iblockstate.getCollisionBoundingBox(this.world, blockpos); if (axisalignedbb != Block.NULL_AABB && axisalignedbb.offset(blockpos).contains(new Vec3d(this.posX, this.posY, this.posZ))) { this.inGround = true; } } if (this.inGround) { int j = block.getMetaFromState(iblockstate); if (!this.world.collidesWithAnyBlock(this.getEntityBoundingBox().grow(0.05D))) { this.inGround = false; this.motionX *= (double)(this.rand.nextFloat() * 0.2F); this.motionY *= (double)(this.rand.nextFloat() * 0.2F); this.motionZ *= (double)(this.rand.nextFloat() * 0.2F); this.ticksInGround = 0; this.ticksInAir = 0; } else { ++this.ticksInGround; this.doBlockCollisions(); } } else { this.posY = posY - 0.4D; ticksInAir++; } if (this.ticksInGround >= 10) { this.setDead(); this.world.spawnParticle(EnumParticleTypes.BLOCK_CRACK, this.posX, this.posY+0.5D, this.posZ, 1.0D, 0.0D, 1.0D, 10); } this.setPosition(posX, posY, posZ); } @SideOnly(Side.CLIENT) @Override public boolean isInRangeToRenderDist(double distance) { double d0 = this.getEntityBoundingBox().getAverageEdgeLength() * 10.0D; if (Double.isNaN(d0)) { d0 = 1.0D; } d0 = d0 * 64.0D * getRenderDistanceWeight(); return distance < d0 * d0; } @Override public void setThrowableHeading(double x, double y, double z, float velocity, float inaccuracy) { } @Override protected void entityInit() { } @Override protected void readEntityFromNBT(NBTTagCompound compound) { } @Override protected void writeEntityToNBT(NBTTagCompound compound) { } } Edited November 27, 20177 yr by ArmamentHaki
November 27, 20177 yr Position is position. Motion is velocity, the first derivative of position. Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable. If you think this is the case, JUST REPORT ME. Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice. Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked. DO NOT PM ME WITH PROBLEMS. No help will be given.
November 27, 20177 yr Author 53 minutes ago, Draco18s said: Position is position. Motion is velocity, the first derivative of position. All right. So basically, the xmotion shows how fast an entity moves into direction x. If a Position was calculated by x*x, the motion would be 2x?
November 28, 20177 yr It doesn't show, it is. Motion is used to modify position. Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable. If you think this is the case, JUST REPORT ME. Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice. Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked. DO NOT PM ME WITH PROBLEMS. No help will be given.
November 28, 20177 yr Author Ok so what I planned to do is get rotationYaw and rotation Pitch from the EntityPlayer that shoots my projectile, just like EntityArrow does. However, I dont understand the calculations that are then used by Minecraft. My plan was to always make the projectile move 0.5 Blocks every tick but in every possible direction. The problem is that motionX and motionY already define how fast it goes, so depending on how the player is rotated, the projectile will go faster or slower. I had an idea on how to solve this: motionX*motionX + motionY*motionY would have to be 0.25, basically the sentence of pythagoras. But how can I relate my roationPitch and my rotationYaw to motion? Using sinus may work.. Also, is MathHelper.sqrt the function that gets the root of a value? I am not that good with english mathematical expressions
November 28, 20177 yr 7 minutes ago, ArmamentHaki said: but in every possible direction That makes no sense. 7 minutes ago, ArmamentHaki said: I had an idea on how to solve this: motionX*motionX + motionY*motionY This does not help you. 7 minutes ago, ArmamentHaki said: But how can I relate my roationPitch and my rotationYaw to motion? Using sinus may work This is correct. Rotation is an angle, motion is a direction. Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable. If you think this is the case, JUST REPORT ME. Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice. Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked. DO NOT PM ME WITH PROBLEMS. No help will be given.
November 28, 20177 yr Author 17 minutes ago, Draco18s said: That makes no sense. This does not help you. This is correct. Rotation is an angle, motion is a direction. By every possible direction, I meant that the projectile acts like an arrow that can be shot in every direction and acts the same. And if I used motionX*motionX+motionY*motionY = 0.25 it should be useful as it would show that the actual way which is taken by the Entity is 0.5 Blocks long, wouldn't it?
November 28, 20177 yr 1 hour ago, ArmamentHaki said: if I used motionX*motionX+motionY*motionY = 0.25 it should be useful as it would show that the actual way which is taken by the Entity is 0.5 Blocks long motionX*motionX+motionY*motionY = 0.25 is a circle: http://www.wolframalpha.com/input/?i=x*x+%2B+y*y+%3D+0.25 That is, there are infinitely many values of motionX and motionY that satisfy that equation. Sure, it tells you that the speed that the entity is taking, but that's not useful here. Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable. If you think this is the case, JUST REPORT ME. Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice. Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked. DO NOT PM ME WITH PROBLEMS. No help will be given.
November 28, 20177 yr Author 27 minutes ago, Draco18s said: motionX*motionX+motionY*motionY = 0.25 is a circle: http://www.wolframalpha.com/input/?i=x*x+%2B+y*y+%3D+0.25 That is, there are infinitely many values of motionX and motionY that satisfy that equation. Sure, it tells you that the speed that the entity is taking, but that's not useful here. Thanks for the Explanation. I have now found a working way to shoot my projectile in a direction. However, when I do this, the Position is only updated around every ten blocks which makes it look like it is teleporting. It only updates the Position every 1 or 2 seconds, and when it does, the entity is already gone. I tried it with smaller velocity, but that just has the same effect only that it doesn't teleport as far. Here is my class: package net.zeldadungeons.init.entity.projectile; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.IProjectile; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.projectile.EntityArrow; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import net.minecraftforge.client.event.sound.SoundEvent; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import net.zeldadungeons.util.Log; public class EntitySlingshotPellet extends Entity implements IProjectile { private Entity shootingEntity; private boolean inGround; private int ticksInGround; private int ticksInAir; public EntitySlingshotPellet(World worldIn) { super(worldIn); this.setSize(0.5F, 0.5F); } public EntitySlingshotPellet(World worldIn, double x, double y, double z) { this(worldIn); this.setPosition(x, y, z); } public EntitySlingshotPellet(World worldIn, EntityLivingBase shooter) { this(worldIn, shooter.posX, shooter.posY + (double)shooter.getEyeHeight() - 0.10000000149011612D, shooter.posZ); this.shootingEntity = shooter; //throws Entity towards a direction this.setAim(shooter, shooter.rotationPitch, shooter.rotationYaw, 1F, 1F, 0); } public void setAim(Entity shooter, float pitch, float yaw, float p_184547_4_, float velocity, float inaccuracy) { //yaw and pitch are converted into motion values float f = -MathHelper.sin(yaw * 0.017453292F) * MathHelper.cos(pitch * 0.017453292F); float f1 = -MathHelper.sin(pitch * 0.017453292F); float f2 = MathHelper.cos(yaw * 0.017453292F) * MathHelper.cos(pitch * 0.017453292F); this.setThrowableHeading((double)f, (double)f1, (double)f2, velocity, inaccuracy); this.motionX += shooter.motionX; this.motionZ += shooter.motionZ; if (!shooter.onGround) { this.motionY += shooter.motionY; } Log.getLogger().info("setAim " + f + " " + f1 + " " + f2); } public void onUpdate() { super.onUpdate(); //test whether the Entity is touching the Ground BlockPos blockpos = new BlockPos(this.posX, this.posY, this.posZ); IBlockState iblockstate = this.world.getBlockState(blockpos); Block block = iblockstate.getBlock(); if (iblockstate.getMaterial() != Material.AIR) { AxisAlignedBB axisalignedbb = iblockstate.getCollisionBoundingBox(this.world, blockpos); if (axisalignedbb != Block.NULL_AABB && axisalignedbb.offset(blockpos).contains(new Vec3d(this.posX, this.posY, this.posZ))) { //if in Ground, the entity won't move anymore this.inGround = true; motionX = 0; motionY = 0; motionZ = 0; int j = block.getMetaFromState(iblockstate); if (!this.world.collidesWithAnyBlock(this.getEntityBoundingBox().grow(0.05D))) { this.inGround = false; this.ticksInGround = 0; this.ticksInAir = 0; } else { ++this.ticksInGround; this.doBlockCollisions(); } } } //increases the time in air counter if(!this.inGround) { ticksInAir++; } //updates entities position, is executed every tick posX += motionX; posY += motionY; posZ += motionZ; //sets the position this.setPosition(posX, posY, posZ); Log.getLogger().info((int)posX + " " + (int)posY + " " + (int)posZ + " " + motionX + " "+ motionY + " " + motionZ); this.removeEntity(); } public void removeEntity() { //responsible for removing the entity after it hits the ground if (this.ticksInGround >= 10) { this.setDead(); this.world.spawnParticle(EnumParticleTypes.BLOCK_CRACK, this.posX, this.posY+0.5D, this.posZ, 1.0D, 0.0D, 1.0D, 10); } } @SideOnly(Side.CLIENT) @Override public boolean isInRangeToRenderDist(double distance) { double d0 = this.getEntityBoundingBox().getAverageEdgeLength() * 10.0D; if (Double.isNaN(d0)) { d0 = 1.0D; } d0 = d0 * 64.0D * getRenderDistanceWeight(); return distance < d0 * d0; } @Override public void setThrowableHeading(double x, double y, double z, float velocity, float inaccuracy) { float f = MathHelper.sqrt(x*x + y*y + z*z); x = x / (double)f; y = y / (double)f; z = z / (double)f; //velocity is added this.motionX = x*velocity; this.motionY = y*velocity; this.motionZ = z*velocity; Log.getLogger().info("throw " + f + " " + x + " " + y + " " + z); } @Override protected void entityInit() { } @Override protected void readEntityFromNBT(NBTTagCompound compound) { } @Override protected void writeEntityToNBT(NBTTagCompound compound) { } } Edit:This seem to be some kind of Client-Server side error as on the server, the position is updated properly, the position updates every 20 ticks on the client Edited November 28, 20177 yr by ArmamentHaki
November 28, 20177 yr That is not a motion problem. That is a entity tracking frequency problem. Show where you register your entity. Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable. If you think this is the case, JUST REPORT ME. Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice. Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked. DO NOT PM ME WITH PROBLEMS. No help will be given.
November 29, 20177 yr Author 6 hours ago, Draco18s said: That is not a motion problem. That is a entity tracking frequency problem. Show where you register your entity. I was only tracking every 20 ticks. It does work now. Edited November 29, 20177 yr by ArmamentHaki
December 2, 20177 yr Author My Entity still keeps moving a tiny bit weird when I throw it. I am not sure if ist normal or due to its small Rendering size, but sometimes when I throw it, it moves up or down by a small distance. public void onUpdate() { super.onUpdate(); BlockPos blockpos = new BlockPos(this.posX, this.posY, this.posZ); IBlockState iblockstate = this.world.getBlockState(blockpos); Block block = iblockstate.getBlock(); if (iblockstate.getMaterial() != Material.AIR) { AxisAlignedBB axisalignedbb = iblockstate.getCollisionBoundingBox(this.world, blockpos); if (axisalignedbb != Block.NULL_AABB && axisalignedbb.offset(blockpos).contains(new Vec3d(this.posX, this.posY, this.posZ))) { this.inGround = true; motionX = 0; motionY = 0; motionZ = 0; int j = block.getMetaFromState(iblockstate); if (!this.world.collidesWithAnyBlock(this.getEntityBoundingBox().grow(0.05D))) { this.inGround = false; this.ticksInGround = 0; this.ticksInAir = 0; } else { ++this.ticksInGround; this.doBlockCollisions(); } } } double j = 0; if (!this.inGround) { ticksInAir++; } this.posX += this.motionX; this.posY += this.motionY; this.posZ += this.motionZ; float f1 = 0.99F; this.motionX *= (double) f1; this.motionY *= (double) f1; this.motionZ *= (double) f1; this.motionY -= 0.05000000074505806D; this.updatePos(posX, posY, posZ); this.removeEntity(); } public void updatePos(double d1, double d2, double d3) { this.setPosition(d1, d2, d3); } public void removeEntity() { if (this.ticksInGround >= 10) { this.setDead(); this.world.spawnParticle(EnumParticleTypes.BLOCK_CRACK, this.posX, this.posY + 0.5D, this.posZ, 1.0D, 0.0D, 1.0D, 10); } }
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.