キングダムが好きすぎて意志を受け継げる矛を作った話

この記事は、Tech KAYAC Advent Calendar 2020 の12日目の記事になります。

みなさん、こんにちは!技術部の入江です。普段はTonamelという大会運営サービスのフロントエンドエンジニアをやっています。TypeScript最高。

昨日は @mashiikeによる Amazon Athena + Google Colab で分析環境を作る話でした。便利そう。

さて、本題に入りますが、私は戦国時代が好きです。社内のSlackのアイコンも戦国武将の肖像画を拝借しております。 戦国時代の好きなところは、「パッションの強い個人が周りを巻き込み世界を変える。」そういうところにあると思います。

そんな戦国ファンな私が2020年一番熱いなと思ったのは、漫画キングダムです。

キングダム 58 (ヤングジャンプコミックスDIGITAL)

キングダム 58 (ヤングジャンプコミックスDIGITAL)

  • 作者:原泰久
  • 発売日: 2020/07/17
  • メディア: Kindle版

キングダムとは原泰久先生による中国の春秋戦国時代が舞台で、天下の大将軍を目指す信と後の始皇帝の嬴政が主人公の漫画です。ちなみに原泰久先生は私の大学の先輩です。

中でもエモかったエピソードは58巻の信と龐煖の一騎討ちです。この一騎討ちはかなり因縁の対決で、下に簡単な相関図を書いたので、ご確認ください。(他にももっとたくさんの仲間が龐煖に倒されました…) f:id:kiyoshidainagon:20201209091958j:plain

一騎討ち中に、龐煖が「お前は… お前はなぜ我が刃に抗える……」と言っているシーンがあるように、信は一人では戦っていません。失った仲間達の意思を背負って戦っています。その戦いで使っている武器が、過去、龐煖と戦い戦死した王騎将軍から受け継いだ矛なんですね。

読後、私は「自分も矛が欲しいな…」と思い、我が家にたまたま余った物干し竿があったのでちょっと頑張ってみました。

つくる

モデリング

AutodeskのFusion 360でモデリングしていきます

f:id:kiyoshidainagon:20201210212910p:plain

f:id:kiyoshidainagon:20201210220015p:plain

持ち手の棒の部分は物干し竿が140cmくらいだったので、それに合わせています。

出力する

f:id:kiyoshidainagon:20201210214132j:plain

3Dプリンターで出力します。 サイズの関係で4回に分けて出しました。後で合体させるために、穴を3Dモデルの中心に開けました。

完成

出力したパーツを繋ぎ合わせて、適当な塗料で塗って完成です。 (サイズ感を分かりやすくために1m定規を置いてます。) (赤いペンキが無かったので、物干し竿を塗るのは諦めました。)

f:id:kiyoshidainagon:20201210215352j:plain

物足りない

このままだとパンチが弱いというか、意思を受け取れている感が無かったので、どうしたものかと悩んでいたところ、我が家に先日MFT2020で買ったobniz入りのM5StickCを発見したので、それを使って盛ることにしました。

モデリングする

f:id:kiyoshidainagon:20201210230149p:plain

M5StickCをいい感じに入れるために、穴を開けて、液晶が表示できるように表面をくり抜きます。

コーディングする

以下のコードをObnizで動かしました。 Node.jsで動いています。

Node.jsにHTML5 Canvasは無いので、node-canvasを使用しました。 github.com

const { createCanvas } = require("canvas");
const Obniz = require("obniz");

const OBNIZ_ID = "xxxx-xxxx";

const INTERVAL = 10;
const STEP = 3;
const WIDTH = 160;
const HEIGHT = 80;

const obniz = new Obniz(OBNIZ_ID);

const canvas = createCanvas(WIDTH, HEIGHT);
const ctx = canvas.getContext("2d");

let counter = 0;
let posX = WIDTH;

const drawObniz = () => {
  obniz.display.draw(ctx);
};

// 180度回転させる M5StickCをはめてみたら逆だったので。
const rotate180deg = () => {
  ctx.translate(WIDTH / 2, HEIGHT / 2);
  ctx.rotate(Math.PI);
  ctx.translate((-1 * WIDTH) / 2, (-1 * HEIGHT) / 2);
};

// Canvasをリセット
const clearCanvas = () => {
  ctx.clearRect(0, 0, WIDTH, HEIGHT);
};

// フォントの設定
const setupFont = () => {
  ctx.fillStyle = "white";
  ctx.font = '30px "YuMincho"';
  ctx.textAlign = "left";
  ctx.textBaseline = "middle";
};

// テキストのアニメーション(右から左にループする)
const drawText = (counter) => {
  setupFont();

  const text = "ここにメッセージを入れる";
  const textWidth = ctx.measureText(text).width;

  posX = WIDTH - (counter % (WIDTH + textWidth));

  ctx.fillText(text, posX, HEIGHT / 2);
};

// ループ処理
const ticker = async () => {
  clearCanvas();
  counter += STEP;

  drawText(counter);

  drawObniz();

  // フリーズしないように待つ
  await obniz.pingWait();
  setTimeout(ticker, INTERVAL);
};

obniz.onconnect = async () => {
  // モノクロでいいので、色深度を下げる。
  obniz.display.setColorDepth(1);
  rotate180deg();
  ticker();
};

体験してみる

いざ、体験してみます。

f:id:kiyoshidainagon:20201210234852j:plain
矛を突きつけられた図

f:id:kiyoshidainagon:20201211002322g:plain

「ここの実装今日中にお願いします」

こういうちょっとしんどいなぁ…って依頼も武器に込められた意志だと思うと、「よーし、やってやるぞ!」って気分になりますね。

まとめ

いかがだったでしょうか?

Obnizですが、JSだけでセンサーやサーボモーターなど動かせるので、IoTに興味あるフロントエンドエンジニアの方にはオススメできる一品ですね。コロナ禍ですし、おうちでIoTをやるチャンス!

明日は期待の新卒フロントエンドエンジニアの@miyabinが発表してくれます!

お楽しみに〜。

ありがとうございました!