WGGの活動log

都内でゲーム開発だったりVRだったりをしてるかもしれないエンジニアです. WGGは「ワグ」と読みます

リプライで p5.js のプログラムを実行する TwitterBot を Raspberry Pi で作った話

Twitter Bot を作った話

ふと,↓こんなことを思いつきました

このツイートのうち,後者の方の仕組みでちょっと TwitterBot を作ったので,その仕組とかの話です

作ったbot

f:id:wgg00sh:20200725170613p:plain https://twitter.com/p5_bot

bot の遊び方

この bot が呟いてる, #p5js と付いているツイートを探します

このツイートに, $1 $2 のように $ から始まる文字があるので,その個数分数値を入力してリプライを送ります このツイートの場合, 3つですね

すると,元のプログラムから $1 $2 ... と書かれていた部分が,リプライで送った値に置き換わってプログラムが実行されます

続きを読む

パズドラWが終わるらしいので,結構プレイした自分の攻略情報とか纏めてみる

パズドラWが終わるというツイートが,パズドラ公式から発信されました

自分としては,パズドラ本編もパズドラWも (レーダーも) 同じくらい楽しんでいたので残念です
なので自分がプレイしたパズドラWの履歴をちょっと纏めてみたり, 少し攻略に関する情報とかを書いてみたいと思います

手持ち

f:id:wgg00sh:20200528202416p:plain
f:id:wgg00sh:20200528202428p:plain
f:id:wgg00sh:20200528202439p:plain

続きを読む

#つぶやきProcessing で限界までコードを圧縮する方法 (p5.js 編)

先日 (5/16), Processing Community Hangout Japan #01 というオンラインイベントがありました
その中で,#つぶやきProcessing についての話をしている方が居て,みんな1ツイートに収めるための文字数制限に苦労しているように感じたので,自分がやっているコード圧縮の手法をまとめて説明してみようと思います

www.youtube.com

#つぶやきProcessing について

以前書いた記事でも紹介したのですが, Twitter の1ツイートに収まる Processing のプログラムを書いて,実行結果と一緒にツイートする企画です
自分が以前作った作品を少し載せておきます


Processingでも, p5.js でも, Processing Python Mode でもどれでも大丈夫で (有利不利差はありそう), 最近は派生して #つぶやきGLSL なんてものもできてるらしいです


以前自分が書いた,つぶやきProcessing用の環境構築はこちら ↓

wgg.hatenablog.jp

プログラムを圧縮するために

ここから,圧縮技術について説明していきます.
今回,題材として 以前作ってみた以下の作品を圧縮する工程を紹介してみます

こちらのプログラムは 222文字で収まっています
Twitterでは, 半角文字だけで書けば280文字, #つぶやきProcessing のタグを付ければ 260文字ぐらい入ります
実際に書いてみればわかるのですが,文字数制限は非常に厳しく,中々満足に作ることができないです
その中で少しでも自分の表現を増やすために,あらゆる手段を使って文字数を減らしていきます

t=0,draw=e=>{t++||(createCanvas(w=900,w),w/=2,blendMode(DIFFERENCE),m=translate),clear(),m(w,w),f=e=>{if(e--<1)return;let r=3;for(;r-- >0;)push(),rotate(TAU/3*r+t/800),m(4e4/t+t*t/2e3,0),circle(0,0,t+200),f(e),pop()},f(3)}

圧縮前のソースコードは以下のようになります (507文字)
(ただし,以下のコードは元々書いたものを圧縮して↑のコードにしたわけではなく,この記事を書くために圧縮していない想定のコードを書き直しています)


function recursiveDraw(recursiveCount) {
  recursiveCount--
  if(recursiveCount<=-1){
    return
  }

  for(let i=0;i<3;i++){
    push()
    rotate(PI*2/3*i+frameCount/800)
    translate(40000/frameCount+frameCount*frameCount/2000,0)
    ellipse(0,0,frameCount+200,frameCount+200)
    recursiveDraw(recursiveCount)
    pop()
  }
}

function setup() {
  createCanvas(900,900)
}

function draw() {
  blendMode(BLEND)
  background(0)
  blendMode(DIFFERENCE)
  translate(width/2,height/2)

  recursiveDraw(3)
}

minify してみる

まずはソースコードを短くするには minifyツールを使って短縮してみるのが一番楽だと思います
以下のようなサイトやツールを利用して,ソースコードを意味をそのままで文字数を減らすことができます

javascript-minifier.com
www.npmjs.com

自分は以前書いた記事で紹介しているように,プログラムを保存するたびに minify を実行して圧縮後の文字数を表示するようにしています

function recursiveDraw(e){if(!(--e<=-1))for(let r=0;r<3;r++)push(),rotate(2*PI/3*r+frameCo
unt/800),translate(4e4/frameCount+frameCount*frameCount/2e3,0),ellipse(0,0,frameCount+200,fram
eCount+200),recursiveDraw(e),pop()}function setup(){createCanvas(900,900)}function draw(){blen
dMode(BLEND),background(0),blendMode(DIFFERENCE),translate(width/2,height/2),recursiveDraw(3)}

結構短くなったはずですが,まだ372文字あり,1ツイートに収めるには遠いです
しかしながら,このminify で圧縮してくれる要素は意識せずに書くことができるので,活用していきます

minify で圧縮された要素

minifier がいい感じにやってくれた内容を,一応確認してみます

不要なスペースの削除

多くの場合プログラムを書くときにインデントを付けて構造を見やすくするのですが,minifier ではそれを全部消してくれます
(自分でインデント崩した状態でコーディングするのは辛いので,これを自動で任せられるのは助かる)

変数名の簡略化

recursiveCounte に省略されてたりと,基本的に全ての変数を1文字で書いてくれます
これを利用すれば,自分でコーディングする際には意味がわからない命名をせずに書き,最後に minify で1文字に圧縮する事ができます

数値の表記変更

元のコードには 400002000 といった数値を使用していましたが minify 後は 4e4, 2e3 と指数表記にしてくれます
他にも,今回のコードでは使用していませんが,絶対値1未満の少数を書く場合, 0.54 などの 0 を省略して .54 のように書くことができますが,これも自動で行ってくれます

minifier でやってくれない圧縮を自力でする

ここまでは minifier が自動でやってくれるので,自分は意識して書く必要がないです
ここからは, minifier に頼らず 多少コードの意味が変わったとしても文字数を減らす工夫を行っていきます

function の省略
function setup() {
  createCanvas(900,900)
}

これは,↓のように書き直せます

setup=_=>{
  createCanvas(900,900)
}

引数がある場合は,

function recursiveDraw(recursiveCount){
f=i=>{

のように書きます

複数回使用した関数名の省略

元のコードでは translate を2回使用していますが,同じ関数を2回以上使用する場合は,短縮できる可能性があります

translate(40000/frameCount+frameCount*frameCount/2000,0)
translate(width/2,height/2)

m=translate
m(40000/frameCount+frameCount*frameCount/2000,0)
m(width/2,height/2)

のようにすると,少し文字数を減らせます
名前の長い関数を2回以上使う場合に特に有効です

p5 組み込み変数の省略と, setup の排除

processing (p5.js) には,mouseX, frameCount, width, height など,予め使える変数がいくつかあります
この中で,自分はframeCount, width, height をいい感じに省略できる方法を用意しました

t=0
draw=_=>{
  if(!t++){
    createCanvas(w=900,w)
  }
}


この書き方をすると, width, height は全て w で表わすことができ,
frameCount は tで表せます
更に, function setup(){} が不要になるのでかなりの短縮になります

ellipseを使わない, circle を使う

p5.js では円を描く際には ellipse() を使用することが多いですが,最新の p5.js 1.0 からは楕円ではなく真円を描く場合に circle() 関数が使えるようになりました.
これは, ellipse() に引数を3つ指定した場合と同じ挙動なので1文字の短縮になります

同様に, rect() も square() という正方形に限定して描画する関数がありますが,こちらは逆に名前が長くなるので使ってないです

translate の活用

絵を画面の中心に描きたい場合は結構多いと思います
その際には,各描画命令で座標を画面の真ん中にするのではなく, 初めに translate(w/2,w/2) とすると,その後の描画命令の引数が簡潔になる場合があります.
width を頻繁に使用する場合は, setup() 内で w/=2 を実行しておくのも良さそうです

ループ処理を圧縮する
for(i=0;i<3;i++){
}

a
for 文はこの用に書くのが一般的だとは思いますが,以下のように書くと少し短縮できます(ただしカウンタがずれるので他の箇所で処理が変わってくる可能性があります)

for(i=0;i--<3;){
}
background(0) ではなく clear() を使う

動画ものの作品を作る場合に, draw の中で描画内容を初期化するために background(0)などを使うことは多いと思います
しかし, 背景色をcss で設定しておくと,clear() で代用することができます
(つぶやきProcessing として若干レギュレーション違反な気がしなくもないですが)

ただし,background(0,5) などを使った残像表現をする場合は clear() では完全に消えてしまうのでおそらくできないです

PI*2 を TAU にする

角度を使う場合, PI*2 で360度を表すことは多いですが, TAU という定数が用意されているのでそちらを使うと1文字減ります

終わりに

こんな感じに,自分が使ってるテクニックを色々上げてみました
他にもまだまだ工夫できると思うので,もっと情報共有してつぶやきProcessingの表現力を増やしていきたいです

自分流 「つぶやきProcessing」 の作業環境

#つぶやきProcessing について

前回 PCD Tokyo に参加して以来, 「つぶやきProcessing」 という活動を少し行っています

wgg.hatenablog.jp

つぶやきProcessingは,1ツイートにProcessingのプログラムと,実行結果を載せてツイートします

自分もこんな感じで何回か投稿しています



1ツイートにプログラムを収める必要があるという点から,度々文字数が足りないという問題に遭遇します
1ツイートは140文字( 半角なら280文字)で, そこにハッシュタグを付けるとなると大体 250文字くらいで作品1つを作る必要があります

というわけで,自分なりにこの問題を少しでもスマートに解決してみました

完成品

この動画です

この自作環境は,大体↓のような特徴を持っています

  • ファイルを保存するたびに実行結果が自動でリスタートされる
  • ファイルを保存するたびに,プログラムの圧縮 (minify) を行ってくれる
  • ファイルを保存するたびに,圧縮後の文字数を表示してくれる
  • (それなりに) 補完が効く

この環境を作ったことで,文字数制限に対してかなり書きやすくなりました

環境構築

使用言語

まず,使用するProcessingの種類ですが,完全に自分の好みで p5.jsを使っています

p5js.org

エディタ

テキストエディタは,先の動画では FVimを使っていましたが,基本的にエディタには依存していないのでVSCode でも Sublime でも NeoVim でも Atom でも何でも大丈夫だと思います

github.com

OS

OSはWindowsを使用していますが,Mac / Linux でも問題なく動作するはずです (最低限の依存を用意できれば)

ブラウザ

ブラウザもWebGLが動くなら多分何でもいいです (上の動画では Edge)

事前に用意したファイル

ローカルで動かす関係上,htmlとcssファイルは用意しています

<!-- index.html -->
<!doctype html>
<html lang="ja">

<head>
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, viewport-fit=cover" />
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" href="icon.png" />
  <link rel="stylesheet" href="./style.css">

  <script>
    window.addEventListener("touchstart", function (event) { event.preventDefault(); }, { passive: false });
    window.addEventListener("touchmove", function (event) { event.preventDefault(); }, { passive: false });
  </script>

  <title>つぶやきProcessing</title>
  <script src="js/p5.js"></script>
  <script src="js/main.js"></script>
</head>

<body>
</body>

</html>

一応スマホ対応していますが,そんな重要じゃないので,下の方で p5.js と, 自分で書く main.js を読み込んでいるだけです

// style.css
* {
  background: black;
}

.p5Canvas {
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  position: absolute;
}

こっちは画面中央にキャンバスを表示する設定です

npm 使う

多分ここがこの環境構築のメインです
node.jsnpm を使用しています

nodejs.org
www.npmjs.com

MacLinuxを使っている人は brew, apt, yum 等々で簡単に入れられると思います

npm のモジュール入れる

以下4つのモジュールを使用しています

npm install browser-sync
npm install onchange
npm install concurrently
npm install minify

package.json

↓みたいな感じです

{
  "name": "p5js",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "sync": "browser-sync start --server --files='./*.html, ./*.css'",
    "minify": "onchange ./js/main.js -- minify ./js/main.js",
    "min": "onchange ./js/main.js -- node ./js/minify.js",
    "start": "concurrently \"npm run sync\" \"npm run min\""
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "browser-sync": "^2.26.7",
    "concurrently": "^5.1.0",
    "minify": "^5.1.0",
    "onchange": "^6.1.0"
  }
}

使い方

ターミナルで, npm start を実行すると,ブラウザが開いてコーディングできるようになります
この状態で, main.js を変更して保存すれば,ブラウザが自動でリロードされソースコードの圧縮が行われます

補完について

ここはエディタごとに変わってくるので細かく説明しません
自分の場合, vim-lsp-settings をお借りしました
ただnodeモジュールとしてp5 をちゃんと使ってるわけではないので色々中途半端だったりします, 文字数詰めるためにはちょっと仕方ない...
他のエディタを使っている場合, 恐らく「〇〇(エディタ名) p5 補完」 とかで検索するとそれなりに出ると思います

github.com

終わりに

こんな感じで素敵な環境ができあがりました
一応以下のリポジトリに,僕が つぶやきProcessing で作ったものを,開発環境と一緒に公開しています

github.com

もし「同じ環境使いたい!」って方が居ましたら,すぐに始められる環境一式を別で公開するかもしれません

それでは,皆さんに良い Processing ライフを!