2020年7月28日火曜日

小さな子でも使える「かんたんタイマー」を作った

小さな子でも使える「かんたんタイマー」を作りました。 タイマーアプリは星の数ほどありそうですが、実用上なかなか良いものがない+必要だったので、作りました。 かんたんタイマー の特徴は、小学1年生でもすぐに使えるところです。



(1) まず iPhone/Android などにも標準でタイマーアプリ (時計アプリ) が入っているので、違いを説明しないといけません。 標準のタイマーアプリはどれもスライダー式なのですが、これ小学1年生などに使わせると使い勝手が悪いのです。 たとえば「5分間でこれをやってみよう」などと言って、設定させようとしても、設定に時間が掛かってしまいます。

スライダーが微妙にずれたりで、設定させるのに凄く時間が掛かります。 また時間の設定に慣れても、指定の時間からちょっと時間を増やそうとか、発想が豊かで邪念を持ってしまいがちです。 集中力の足りない子ほどタイマーを使うのは効果的なのですが、タイマーの設定に気を取られては元も子もありません。

こういった話は実際やってみないと気づきにくい問題ですが、標準タイマーのようなスライダー式ではなく、「分」だけを指定する数字入力にしたほうがずっと良いです。 「2分30秒でこれをやる」とかいった指定をすることは滅多にないので、「秒」は四捨五入してしまえば良いと思います。 細かいことは一切考えさせないようにして、3秒で設定して、スタートできるタイマーを目指しました。


(2) もう1つのポイントはタイマーの計測中に画面を消さない設定をできるようにしたところです。 標準タイマーは時間が経つと暗転したり画面ロックが掛かりがちなのですが、時間を測ってやってもらう以上、常駐してすぐに時間を見れたほうがいいです。


いい加減に作れば20行程度でできるタイマーアプリですが、細かなことを突き詰めていくと、考えることがたくさんあります。 やはり PWA でアプリ化したいし、音がない時はバイブレーションしたいし、色々作っていたら、気付けば 350行くらい。 プログラミング初心者の素振り用としても良さそうなので、MIT ライセンスで コードも公開 しています。

2020年7月19日日曜日

タイピングゲーム: ハゲ打を作った

タイピングゲームには寿司打や皿打など素晴らしいサイトはあるのですが、Flash に依存していたり、WebGL もいくつかの制約があります。 使いやすくてひねりの効いたゲームを探していましたが、現状ではないため、作ってみました。



ハゲ打 は、愛らしいハゲAA たちと一緒にタイピングを学べるサイトです。 ハゲAA 自体がネタの宝庫なので、シンプルな割には結構面白いんじゃないかな。 タイピングをできるようになって、可愛いハゲにたくさん出会いましょう (適当)

実装のポイントとしては、(1) 既存のタイピングゲームはどれもロード時間が長すぎるので、とにかく軽量にしました。 タブレットでやろうとすると凄い時間掛かるんですよねえ。 PWA で作ってるので、オフラインでも楽しめます。 (2) ふりがなを付けて小学1年生から楽しめるようにしました。 こども翻訳 で作ったオレオレ形態素解析器を使おうかとも思ったのですが、軽量にしたかったのでこれも直打ち。 (3) あとは飽きないように問題をたくさん用意です。 コアコードはパパっとできたけど、問題作りは単調なこともあって 1 週間くらい掛かった気がする。 合計 1000 問を超えたのでひとまず公開ですが、もう少し増やしたいと思っています。 1500 問くらいまではいけるかな?

作っていて思いましたが、タイピングゲームのコアコードは HTML/CSS/JavaScript 含めて 500 行くらいしかないので、初歩的なモックを作る練習をした後に最初に作る中物題材としても良いかも知れません。 たった 500 行の割には、作ろうとするとドキュメントを読む力や細々としたテクニックが必要で、練習にうってつけの気がする。 ということで MIT ライセンス で コードも公開 しています。

2020年7月4日土曜日

フリゲ紹介: 天翔のマーキナリエ

天翔のマーキナリエ は、RPGアツマールで公開されているアクション探索RPG。



特別な機械人形《マーキナリエ》のアイリスと、主人である技師マリアとともに絶海の孤島で「願いを叶える秘宝」を探す物語。 マリアはアイリスのカスタマイズやストーリーに参加するくらいで、戦闘には参加しません。 主にアイリスを操作してプレイします。



剣と魔法剣、ダッシュやアイテムを駆使して、ゼルダちっくなアクション探索RPGが楽しめます (下)。 魔法はなく完全に物理でシステムはかなりシンプルです。 ぬるぬる動いて、サクサククリアでき、クリアまで2時間くらいでしたが、シンプルに面白くて一気にクリアしてしまいました。



グラや操作性も凄いクオリティでアクションゲームの完成度も凄く高いだけでなく、なんとフルボイスという力の入りようです。 私は基本的にフルボイスはかなり苦手で、それは納得のいかないボイスのほうが多いからです。 ただ、天翔のマーキナリエはボイスのほうも力が入っていて、違和感はほとんど感じませんでした。

ちなみに作者様の紹介動画はこちら。



フリゲのアクション探索アクションRPG もここまで来たか、と感じる作品です。 気持ちの良いプレイのできる作品として、とてもおすすめ。

フリゲ紹介: Argus

ストーリー重視の長編 RPG は、あまりやらなくなってしまっていますが、やはり長編であればあるほど、心に残るものをやりたい。

最近たまたま Twitter で見つけた、宗教戦争と哲学をテーマにした中世欧風ダークファンタジー Argus は、ストーリー重視の RPG として「深さ」のある、とても良い作品でした。 宗教戦争に巻き込まれた一介の騎士キアラが、王子カレルのもとで宗教戦争に終止符を打つまでの物語です。 プレイ時間は 16~17時間ほどです。



序盤では王子カレルの師デヴィッドを軍師とするための探索、そして戦争に勝つための「不思議な力」を手に入れる事から話が始まります (下)。 この序中盤の宗教戦争も面白いですが、最終盤で戦争の真相に近付くにつれ、とても深みのある物語になってきます。

序盤からずっと謎の多かった「不思議な力」に対して、他の作品では見られないような鋭い切込みをしている。 正直ここまで深い話にもってくのは読めなかった。 最終盤の 4-5 時間くらいの物語が特に面白くて「これ完全にネフェイストな物語じゃん!」と思いながらプレイしていました。 あまり深くは語れませんが…かなり深いです。 市販のゲームでは絶対に味わえない深いストーリーで、やはりフリゲはいいものだと感じさせられます。



最近、難易度が選べるようになったらしいのですが、最初は難易度を下げずにもプレイしてみました。 ただ「難易度: 普通」は敵の一撃一撃が重くて、相当キツかった。ファミコン難度に耐性がある人も苦しむかも。 「難易度: 簡単」にするとサクサクプレイの難易度になります。 長編ものはやや低難易度のほうが安定するのかも知れません。 私は「難易度: 簡単」にしてから非常に楽しめました。

難易度の話は置いておくとして、その他の部分は凄く良い。 ロマサガっぽいマップ移動システム (左下) で雰囲気がありますし、顔グラもカッコいい (右下)。 かなり力の入った作品なことは間違いないです。



戦闘システムや探索マップはシンプルですが、敵キャラや BGM などはほとんどすべて自作のようで、力が入っています (左下)。 そして自らに向けられる「まなざし」から力を得る「エンゲージ」という面白いシステムを用意しています (右下)。 このエンゲージの仕組みもストーリーに深く関わってきて、凄く深くまで考えて作られている。



深みのあるストーリーの RPG をやりたい人は、プレイしてみて欲しい作品です。

2020年7月1日水曜日

Node.js の CGI で画像を添付したメールを送る

以前、CGI + Python で画像を添付したメールを送る という記事を書いたけど、たぶん Python の CGI の問題で 16KB 以上の画像ファイルの処理が難しい問題が出たため (後述)、Node.js で書き直してみました。


var express = require('express');
var app = express();
var multer = require('multer');
var upload = multer();


var https = require('https');
var fs = require('fs');
var serverOptions = {
  key:  fs.readFileSync('ssl/cert.key'),
  cert: fs.readFileSync('ssl/cert.crt'),
};
var port = 8888;


var mailer = require('nodemailer');
var mailerOptions = {
  service: 'Gmail',
  auth: {
    user: 'foo@bar.com',
    pass: 'password',
    port: 'port',
  }
};
var mailOptions = {
  from: 'foo@bar.com',
  to: 'to',
  subject: 'タイトル',
  text: 'text',
  attachments: [{ filename: 'hoge.png', content: 'content' }],
};

function sendEmail(req, emails) {
  var [lastName, firstName] = req.body.name.split(' ');
  mailOptions.to = req.body.email;
  mailOptions.text = `${lastName}さん、こんにちは。`;
  mailOptions.attachments[0].content = req.file.buffer;

  var smtp = mailer.createTransport(mailerOptions);
  smtp.sendMail(mailOptions, function(err) {
    if (err) console.log(err);
    smtp.close();
  });
}


app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use('/', express.static('public'));
app.post('/send', upload.single('img'), (req, res) => {
  sendEmail(req, emails);
  res.send('ok');
});
var server = https.createServer(serverOptions, app);
server.listen(port);
// app.listen(port);
クエリパラメータで、 name = [氏名] & to = [送信先] & img = [画像データ] を CGI 経由で POST で受け取り、Gmail でメール送信する例です。 画像データは、<input type="file"> や canvas.toBlob() を FormData.append() すると良いでしょう。 画像は昔なら base64 化して送ってましたが、今は canvas.toBlob() が良いです。 ちなみに Gmail でこのスクリプトを動かすためには、Google アカウントの セキュリティ設定 から、アプリパスワードの設定が必要です。


冒頭で述べた Python の CGI の問題ですが、私も正確にはわかってません。 症状としては画像が16KB を超えるとデータがカットされてしまい、画像が一部分しか送れない問題が見つかりました。 つい最近まで普通に動いていたのでまったく理由がわからず、途方に暮れました。 私のコードのバグではなく、OpenSSL か CGI の実装の問題とは思いますが、正直あまり深入りしたくない…。 Python の CGI ってデバッグが面倒で、サーバと CGI が分離していてデバッグしにくいし、OpenSSL のオプションがごった煮だし、使っている人少なそうな問題があります。 上記のコードを見てもわかるように、Node.js だと超いい感じに書けるので、よくできていると思います。 今後 CGI を書く人は Node.js がおすすめ。