注目キーワード

【爽快】「自動で動くブロック」の作り方を解説 – ScriptAPIでゲーム制作【マイクラ統合版】

はじめに

マインクラフトを構成する最小要素といえば、ブロックです。これがこのゲームの核であり、中心的な存在です。

さて、このブロックはゲーム内では通常不動のものとして扱われます。これは動くことが前提とされるエンティティと対になる存在です。勿論、ピストンなどを用いて動かすことはできますが、多くのスペースを要する上、レッドストーン信号が必要だったりと、実用上些か不便です。

この記事では、ScriptAPI(プログラミングを用いてゲームシステムをいじる機能)を用いてこうしたブロックを簡単に動かす方法について解説します。ブロックを動かすことで、エレベーターや自動ドアはもちろん、テトリスを始めとするブロックゲームを作ることができるようになります。

Youtube動画

この記事の内容に関して解説したYoutube動画を作成しました。以下より視聴できます:

環境構築

ScriptAPIの環境構築がまだの人は、まずはこちらの記事をご覧いただくことをお勧めします。

本記事では、ScriptAPIを書くことができる環境を前提に解説します。

スクリプト

まず、ブロックを動かす関数(move_block)を定義します:

function move_block(block, direction){
    let new_position = {
        x: block.x + direction.x,
        y: block.y + direction.y,
        z: block.z + direction.z
    }
    if(block.dimension.getBlock(new_position).typeId != undefined){
        if(block.dimension.getBlock(new_position).typeId == "minecraft:air"){
            block.dimension.setBlockType(new_position,block.typeId);
            block.dimension.setBlockType({x:block.x,y:block.y,z:block.z},"minecraft:air");
        }
    }
}

これは、動かすブロックと方向(3次元ベクトル)を引数とします。基本的にはこの関数を用いることでブロックを動かすことができますが、関数の使用にあたってはブロッククラスの変数が必須です。

ブロックの指定は座標によって行うことが一般的ですが、今回はブロックを動かすという性質上、ブロックの座標が一意に定まらないことに加えて、わざわざブロックの座標を調べるのも手間です。従って、今回はプレイヤーの近くにあるブロックを動的に取得することにしましょう。次のような関数(get_blocks)を定義します:

function get_blocks(block_id,player,range){
    let blocks = [];
    let current_player_position = player.getHeadLocation();
    for(let x = Math.floor(current_player_position.x-range);x<=Math.floor(current_player_position.x+range);x++){
        for(let y = Math.floor(current_player_position.y-range);y<=Math.floor(current_player_position.y+range);y++){
            for(let z = Math.floor(current_player_position.z-range);z<=Math.floor(current_player_position.z+range);z++){
                let block = player.dimension.getBlock({x:x,y:y,z:z});
                if(block.typeId == block_id){
                    blocks.push(block);
                }
            }
        }
    }
    return blocks;
}

これは検索対象のブロックのidと基準となるプレイヤー、範囲の3つを引数としてそれらに合致するブロックのリストを返す関数です。ここではplayer.getHeadLocation()によって現在のプレイヤーの位置を取得しています。

さて、これらの関数を踏まえて、ブロックの移動を定義してみましょう。今回は例として動画のように「棒を持っていたら近くのダイアモンドブロックを一定方向に動かし、そうでなければ逆方向に動かす」というスクリプトを作っていきます:

server.system.runInterval(function(){
    for (const player of server.world.getAllPlayers()){
        let diamond_blocks = get_blocks("minecraft:diamond_block",player,10);
        let main_hand_item = player.getComponent("minecraft:inventory").container.getItem(player.selectedSlotIndex);
        if(main_hand_item != undefined){
            for(let i=0; i < diamond_blocks.length; i++){
                if(main_hand_item.typeId == "minecraft:stick"){
                    move_block(diamond_blocks[i], {x:1,y:0,z:0});
                }else{
                    move_block(diamond_blocks[i], {x:-1,y:0,z:0});
                }
            }
        }
    }
})

これによって、プレイヤーの意思に基づいてブロックを移動させることができます。今回は手に持っているアイテムを取得してそれを用いましたが、オリジナルアイテムの使用をトリガーしたり、プレイヤーの向いている方向を取得したりと様々なアプローチが考えられると思います。

まとめ

ブロックの移動自体は前述のようにピストンで簡単にできますし、コマンドでも可能です。しかし、こうした方法ではなく、あえてScriptAPIという方法をとったのは、ブロックの座標という情報を取得することなく柔軟に移動を達成できるからです。

今回紹介した方法を用いて自動ドアやブロックゲームなどが作れるかと思います。実際にやってみると楽しいので、皆さんも是非お試しください。こうした実践的な使い方については別途動画で取り上げるかもしれません。

おススメ記事

本サイトでは、他にもScriptAPIを用いた技術的な情報について発信しています。宜しければ、他の記事もご覧ください。

最新情報をチェックしよう!