MineraftのMODでワープするアイテムを追加するとする。Minecraftの世界はブロックで表現されているわけだが、これがワープ先の座標を決定することを難しくする。
ここでは、右クリックをするとワープするアイテムItemWarpStick
を例にして説明する。
getYRot()を使う
Y軸を軸とした回転の角度を得られるメソッドgetYRot
があるので、それを使う方法である。理解しやすく、単純な方法である。
public class ItemWarpStick extends Item {
public ItemWarpStick() {
super(new Item.Properties().tab(CreativeModeTab.TAB_COMBAT));
}
public Vec3 toVec3(BlockPos pos) {
return new Vec3(pos.getX(), pos.getY(), pos.getZ());
}
@Override
public InteractionResultHolder<ItemStack> use(Level level, Player playerIn, InteractionHand handIn) {
BlockPos pos = playerIn.getOnPos();
float YRot = playerIn.getYRot() % 360;
if (YRot > 180) {
YRot -= 360;
}
if (YRot < -180) {
YRot += 360;
}
if (YRot <= 15.0f && YRot > -15.0f) {
playerIn.setPos(toVec3(pos).add(0, 1, 3));
} else if (YRot <= 45.0f && YRot > 15.0f) {
playerIn.setPos(toVec3(pos).add(-1, 1, 2));
} else if (YRot <= 75.0f && YRot > 45.0f) {
playerIn.setPos(toVec3(pos).add(-2, 1, 1));
} else if (YRot <= 105.0f && YRot > 75.0f) {
playerIn.setPos(toVec3(pos).add(-3, 1, 0));
} else if (YRot <= 135.0f && YRot > 105.0f) {
playerIn.setPos(toVec3(pos).add(-2, 1, -1));
} else if (YRot <= 165.0f && YRot > 135.0f) {
playerIn.setPos(toVec3(pos).add(-1, 1, -2));
} else if (YRot <= -135.0f && YRot > -165.0f) {
playerIn.setPos(toVec3(pos).add(0, 1, -3));
} else if (YRot <= -105.0f && YRot > -135.0f) {
playerIn.setPos(toVec3(pos).add(1, 1, -2));
} else if (YRot <= -75.0f && YRot > -105.0f) {
playerIn.setPos(toVec3(pos).add(2, 1, -1));
} else if (YRot <= -45.0f && YRot > -75.0f) {
playerIn.setPos(toVec3(pos).add(3, 1, 0));
} else if (YRot <= -15.0f && YRot > -45.0f) {
playerIn.setPos(toVec3(pos).add(2, 1, 1));
} else {
playerIn.setPos(toVec3(pos).add(1, 1, 2));
}
return super.use(level, playerIn, handIn);
}
}
getOnPos
を使うことでプレイヤーが立っているブロックのBlockPos
が取得できる。setPos
を使ってワープさせる際に引数がVec3
だったため、BlockPos
をVec3
に変換するメソッドtoVec3
を定義した。
あとは角度に応じてX軸方向Z軸方向にそれぞれ何ブロック移動させるかを決めている。getOnPos
を使っている関係でadd
の引数yを0にすると地面に埋まるので、1を入れる。
360で割った余りに対して360を足したり引いたりしているのは、getYRot
で得られる値が-180~180と思いきやそうではないからである。Javaにおいて、負の数を正の数で割った余りは負の数になる。参考として、getYRot
で得られた値をSystem.out.println
で表示した結果を以下に示す。
ひたすら場合分けしているだけなので12方位にしかワープできない。場合分けをさらに細かくしていけばより高精度になるが、現実的ではない。
他にも
他にもベクトルや行列、四元数を用いたアプローチが考えられるが、気が向いたら後日取り上げる。