Help us understand the problem. What is going on with this article?

Scratch 3 Extension の作り方

GamePad Extension を作る

先の投稿で、Scratch 3.0用のMIDI Extension の使い方を紹介しました。このページでは、Web APIを使ったExtensionの作り方を説明します。例に取るのは GamePad APIを使ったGamepad Extension です。

なお、作り方は、Scratch Japan Wiki Scratch_3.0の拡張機能を作ってみよう を参考にさせていただきました。

準備

Windows10 home 32bit で開発しています。
node が必要になりますので、インストールしておきます。
 私の環境には、node v8.16.0 がインストールされています。
MITのGithub から2つのリポジトリをクローンします。

> git clone --depth 1 https://github.com/llk/scratch-vm.git
> git clone --depth 1 https://github.com/llk/scratch-gui.git

アイコンの準備

Extension を読み出すアイコン2つ準備します。

  • 600x370
  • 80x80

それぞれ下のように表示されます。80x80 他にも使われているかもしれません。(不明)

image.png

ファイル名をそれぞれ、

  • gamepadext.png
  • gamepadextmin.png

としました。gamepadというホルダーを作って、この2つのファイルを中に保存します。

scratch-gui\src\lib\libraries\extensions\gamepad

このextensions フォルダーには、もともと付属しているExtensionのアイコンも入っています。

index.jsxの編集

追加したアイコンのファイルをindex.jsxに登録します。

scratch-gui\src\lib\libraries\extensions\index.jsx

ファイルの先頭に、import している行が並んでいますので、いずれかに以下2行を追加します。

index.jsx
import gamepadIconURL from './gamepad/gamepadext.png';
import gamepadInsetIconURL from './gamepad/gamepadextmin.png';

export default [

の中に以下の情報を追加します。

index.jsx
    {
        name: (
            <FormattedMessage
                defaultMessage="GamePad"
                description="Name for the 'GamePad' extension"
                id="gui.extension.gamepad.name"
            />
        ),
        extensionId: 'gamepad',
        iconURL: gamepadIconURL,
        insetIconURL: gamepadInsetIconURL,
        description: (
            <FormattedMessage
                defaultMessage="using GamePad"
                description="Description for the 'GamePad' extension"
                id="gui.extension.gamepad.description"
            />
        ),
        featured: true
    },

ブロックアイコン

ブロックの左隅に表示するアイコンを作成します。

image.png

Scratchのペイントエディター(コスチュームの描画)を使って、ベクターモードで40x40 のアイコンを作製します。

image.png

描画をグループ化して、svg形式で保存します。

image.png

アイコンを右クリックし、「書き出し」を選択すると、ローカルにsvgファイルが保存できます。

image.png

保存した後は、ここなどでbase64形式に変換します。data:image/svg+xml;base64,で始まる文字列をコピーしておきます。

Extension 本体のプログラム

scratch3_gamepadフォルダーを作成します。

scratch-vm\src\extensions\scratch3_gamepad

このフォルダーに、index.jsを作成します。

index.js
const ArgumentType = require('../../extension-support/argument-type');
const BlockType = require('../../extension-support/block-type');
const Cast = require('../../util/cast');
const log = require('../../util/log');
const formatMessage = require('format-message');

/**
 * Icon svg to be displayed at the left edge of each extension block, encoded as a data URI.
 * @type {string}
 */
// eslint-disable-next-line max-len
const blockIconURI = 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHdp...
dGFydCIgc3R5bGU9Im1peC1ibGVuZC1tb2RlOiBub3JtYWwiPjx0c3BhbiB4PSIwIiBkeT0iMCI+R1A8L3RzcGFuPjwvdGV4dD48L2c+PC9nPjwvc3ZnPg==';

/**
 * Icon svg to be displayed in the category menu, encoded as a data URI.
 * @type {string}
 */
// eslint-disable-next-line max-len
const menuIconURI = 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHdp...
dGFydCIgc3R5bGU9Im1peC1ibGVuZC1tb2RlOiBub3JtYWwiPjx0c3BhbiB4PSIwIiBkeT0iMCI+R1A8L3RzcGFuPjwvdGV4dD48L2c+PC9nPjwvc3ZnPg==';

blockIconURIとmenuIconURIは中身同じものにしました。menuIconURIは、次の絵のように左端のメニューに表示されます。

image.png

GamePad API の追加

index.jsにGamePad APIを起動するプログラムを追加します。

index.js
var mPad=null;

function mStartGamePad()
{
    window.requestAnimationFrame(mStartGamePad);
    var gamepad_info = '';
    var gamepads = navigator.getGamepads();
    var gamepad_num =gamepads.length;
    mPad = new Array(gamepad_num);

    for (var i=0; i<gamepad_num; i++) {
        if(gamepads[i]!=null) mPad[i] = gamepads[i];
    }
}

ブロックの追加

index.jsに、ここでは、ゲームパッド右側のXYABの4つのボタンを、HAT BLOCK で検知するブロック4つを追加しています。

index.js
class Scratch3GamePad {

    constructor (runtime) {
        /**
         * The runtime instantiating this block package.
         * @type {Runtime}
         */
        this.runtime = runtime;

        window.requestAnimationFrame(mStartGamePad);

        //this._onTargetCreated = this._onTargetCreated.bind(this);
        //this.runtime.on('targetWasCreated', this._onTargetCreated);
    }

    /**
     * @returns {object} metadata for this extension and its blocks.
     */
    getInfo () {
        return {
            id: 'gamepad',

            name: formatMessage({
                id: 'Game Pad for Scratch3',
                default: 'Game Pad',
                description: 'Label for the game pad extension category'
            }),

            menuIconURI: menuIconURI,
            blockIconURI: blockIconURI,

            blocks: [
                {
                    opcode: 's_X_Button',
                    text: 'X Button',
                    blockType: BlockType.HAT,
                },
                {
                    opcode: 's_Y_Button',
                    text: 'Y Button',
                    blockType: BlockType.HAT,
                },
                {
                    opcode: 's_A_Button',
                    text: 'A Button',
                    blockType: BlockType.HAT,
                },
                {
                    opcode: 's_B_Button',
                    text: 'B Button',
                    blockType: BlockType.HAT,
                },

            ],
            menus: {
            }
        };
    }

/* ================================ */
// BUTTON X- Y- A- B-
    s_X_Button() {
        return mPad[0].buttons[2].pressed;
    };

    s_Y_Button() {
        return mPad[0].buttons[3].pressed;
    };

    s_A_Button() {
        return mPad[0].buttons[0].pressed;
    };

    s_B_Button() {
        return mPad[0].buttons[1].pressed;
    };

}
module.exports = Scratch3GamePad;

Exmansion Manager の修正

scratch-vm\src\extension-support\extension-manager.js

に1行追加します。

expansion-manager.js
    gamepad: () => require('../extensions/scratch3_gamepad')

使用例

image.png

ローカルでの実行

制作したExtenshionをローカルで実行するには、コンソールで次のように立ち上げます。
ディレクトリはscratch-vmに居るものとします。

scratch-vm > npm rm -g scratch-vm
scratch-vm > npm i
scratch-vm > npm link
scratch-vm > cd ..\scratch-gui
scratch-gui > npm i
scratch-gui > npm link scratch-vm
scratch-gui > npm start

これで、Scratchがローカルサーバで起動します。
ウェッブブラウザーで http://localhost:8601 にアクセスすると、Scratchを試すことができます。

アプリケーション

このExtensionはGuthub URLで使えます。お試し下さい。
私は、Playstationのゲームパッドをアダプターを介してUSBでPCにつないでいます。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away