@yushimatenjinです。PlayCanvasのコードエディターに付属されているリンターが、JSHintという古いものでなおかつカスタマイズができなかったので、gulp-playcanvas
playcanvas-node
playcanvas-cli
と3つのライブラリを作りました。gulpのpluginを作ったのでその知見の共有をさせていただきます。
問題
PlayCanvasを使う上で気になった点が付属のコードエディターのLintが古く具体的には
- constを使うと黄色くなる
- セミコロンを入れないと、赤くエラーが出る
この状況だったので自分のエディターを使って開発をしたい欲が出てきました。
作ったプラグイン
npmのパッケージとして公開いたしましたので下記のコマンドでインストールできます。
yarn add gulp-playcanvas
ローカル側のgulpfile.jsはwatch
をして、トランスパイルしたものをPlayCanvasにREST APIを使用してアップロードしています。
gulpfile.jsファイル
const gulp = require("gulp");
const playcanvas = require("gulp-playcanvas");
const pcOptions = require("./playcanvas.json");
const pug = require("gulp-pug");
const sass = require("gulp-sass");
gulp.task("pug", () => {
return gulp
.src(["src/**/*.pug", "!src/**/_*.pug"])
.pipe(pug())
.pipe(gulp.dest("dist/"))
.pipe(playcanvas(pcOptions));
});
gulp.task("js", () => {
return gulp
.src(["src/**/*.js", "!src/**/_*.js"])
.pipe(gulp.dest("dist/"))
.pipe(playcanvas(pcOptions));
});
gulp.task("sass", () => {
return gulp
.src("src/**/*.+(scss|sass)")
.pipe(sass())
.pipe(gulp.dest("dist/"))
.pipe(playcanvas(pcOptions));
});
gulp.task("watch", function() {
gulp.watch(["src/**/*.pug", "!src/**/_*.pug"], gulp.task("pug"));
gulp.watch(["src/**/*.js", "!src/**/_*.js"], gulp.task("js"));
gulp.watch("src/**/*.+(scss|sass)", gulp.task("sass"));
});
gulp.task("default", gulp.parallel("watch"));
パッケージのインストール後、playcanvas.json
という設定ファイルを同じディレクトリに置き、yarn gulp
コマンドで監視対象をwatch
しておきファイルの中身に変更があった場合に同期をする形で動きます。
{
"accessToken": "",
"scenes": [],
"projectId": "",
"branchId": "",
"projectName": "",
"remotePath": ""
}
動かした結果
6月に2Dゲームを作るというハンズオンをやるのですが、その資料を触ってたらHMR的な動きができたという動画です。 x4倍 pic.twitter.com/vMHhrCkHkj
— はが (@Mxcn3) 2019年5月30日
Hot Reload + ローカルのeslint + prettier
で開発ができるのでかなり快適になりました。
タスクは4つの動きをします。
1. 監視
コードの変更をwatch ソースコードの変更を検知しタスクを実行
gulp.task("watch", function() {
gulp.watch(["src/**/*.pug", "!src/**/_*.pug"], gulp.task("pug"));
gulp.watch(["src/**/*.js", "!src/**/_*.js"], gulp.task("js"));
gulp.watch("src/**/*.+(scss|sass)", gulp.task("sass"));
});
この部分ですね、pug
, js
, sass
に変更があった場合にそれぞれのタスクを実行します。
2. ビルド & 3. アップロード
PugやSassなどをHTML, CSSへ変換し、REST APIを使用しビルドしたコードをアップロードします
const pug = require("gulp-pug");
/*
gulp.task("pug", () => {
return gulp
.src(["src/**/*.pug", "!src/**/_*.pug"])
.pipe(pug())
.pipe(gulp.dest("dist/"))
------------自作のプラグインを実行------------------
.pipe(playcanvas(pcOptions));
------------自作のプラグインを実行--------------------
});
*/
https://github.com/yushimatenjin/gulp-playcanvas/blob/master/index.js#L1
Gulpのプラグインの中身はストリームで流れてくるファイルの情報を使用してアップロードしています。
オプションの渡し方などは、gulp-ftpを参考にしました。
const PlayCanvas = require("playcanvas-node").default;
const through = require("through2");
const gutil = require("gulp-util");
const path = require("path");
module.exports = options =>
through.obj(function(file, enc, callback) {
if (file.isNull()) {
return callback(null, file);
}
if (file.isStream()) {
return cb(
new gutil.PluginError("gulp-playcanvas", "Streaming not supported")
);
}
const playcanvas = new PlayCanvas(options);
playcanvas.updateAssets(
options.remotePath,
path.basename(file.path),
file.path
);
return callback(null, file);
});
1行目でplaycanvas-nodeという自作のライブラリを読み込んでいるのですが、このライブラリを作ったことで、APIとのやり取りをシンプルに書けてとてもよかったです。
参考リンク
PlayCanvas.jp
PlayCanvas/Engine
playcanvas-node
playcanvas-gulp