3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

横国ゲーム制作部Advent Calendar 2022

Day 15

【MOD】向いている方向にワープする【Minecraft】

Posted at

MineraftのMODでワープするアイテムを追加するとする。Minecraftの世界はブロックで表現されているわけだが、これがワープ先の座標を決定することを難しくする。
ここでは、右クリックをするとワープするアイテムItemWarpStickを例にして説明する。

getYRot()を使う

Y軸を軸とした回転の角度を得られるメソッドgetYRotがあるので、それを使う方法である。理解しやすく、単純な方法である。

ItemWarpStick.java
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だったため、BlockPosVec3に変換するメソッドtoVec3を定義した。
あとは角度に応じてX軸方向Z軸方向にそれぞれ何ブロック移動させるかを決めている。getOnPosを使っている関係でaddの引数yを0にすると地面に埋まるので、1を入れる。
360で割った余りに対して360を足したり引いたりしているのは、getYRotで得られる値が-180~180と思いきやそうではないからである。Javaにおいて、負の数を正の数で割った余りは負の数になる。参考として、getYRotで得られた値をSystem.out.printlnで表示した結果を以下に示す。

ひたすら場合分けしているだけなので12方位にしかワープできない。場合分けをさらに細かくしていけばより高精度になるが、現実的ではない。

他にも

他にもベクトルや行列、四元数を用いたアプローチが考えられるが、気が向いたら後日取り上げる。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?