AIイラストのパジャマをそっと脱がせるミニゲーム
昨日思いつきで作った「AIイラストの尻を撫で撫でするミニゲーム(試作)」は正直失敗でございました。
尻の動かせる範囲が狭いし、広くしようにも1枚絵をカットしただけなので限界があるし、スマホの場合は大好きな尻を指で隠してしまうという致命的な欠陥が…。
そうだよ。よく考えたら、いつもおさわり系のエロゲをプレイしては、「マウスで操作している最中にシコれないんだが?」と真顔になっているのでした。マウス操作し続ける必要があるエロゲーはいかん!!
あ、でも、おさわり系のゲームでもお気に入りのあったな。
寝ている妹ちゃんにイタズラする系なのだけれど、AUTOプレイ等のシステム面が親切なのはもちろんのこと、イタズラがバレるにせよバレないにせよ、毎回のプレイ内容に応じて翌日の妹日記が更新され、それをコンプするのが面白いの。題材のわりに、いやこういう題材だからこそか、全体的に明るく、「昨日はひどい目に会いました。はぁまったくお兄ちゃんは仕方ないですね。もう少しだけ気が付かないようにしておこうと思います。」みたいなワリと軽い感じなのもグッド。絵柄は特に好きでも嫌いでもないのだけれど、妹ちゃんの性格がトニカクカワイイ。
というわけで(?)、そのゲームのワンシーン、ほんの触りをAIイラストで再現できないかな、と思いつきでやってみた。
パジャマをそっと脱がせるミニゲーム
おまわりさん、ぼくです。
あ、ズボンは脱がせないッス。
さっき紹介したエロゲのほうなら、もちろんズボンどころか本番までGOですけど、こちらはさっきAIイラストで出力して切り貼りしただけなので、左右の乳首を拝めたらおしまいッス。期待させたならすまないっす。
いや~、裸の状態にパジャマ着せるの大変で大変で。差分作るのに思いのほか時間かかっちゃったんですよね…。
…例によって投稿した後にスマホでテストしてるのだけれど、若干、スマホだと脱がす速度が遅い…かな? まぁ、今回は起きないモードを搭載しているので、動作が微妙な場合はそちらで。それより、PCと違って両手使えるので左右のパジャマを同時にガバっと出来るのはスマホの特権ですね。ちょっぴり感動。
ベース絵
よく見ると気がつくと思いますが、1枚目と2枚目のパジャマが違います。
いつもなら、上半身だけ黒塗りマスクして、Inpaintでパジャマ生成させるので、マスクしていないズボン部分は変わらないのですが、今回Inpaintが全然うまくいかなくて、仕方ないので全体を生成しなおしました。だから顔も違う。
上のパジャマだけ切り取って使えば良いかと思ったのですが、体型もびっみょーに違いまして服が合わない。仕方ないので画像編集ソフトで拡大縮小を繰り返して、なんとかサイズ調整しました。
Prompt
下記プロンプトが共通。
1girl,loli,flat chest,short brown hair
,closed eyes
,sleeping on bed
,upper body, from above
上半身裸で、パジャマのズボンだけ履いている絵は、上のプロンプトに「pink pajamas pants only」を追加して生成。
パジャマは来ているけど、半脱ぎになっている絵は「pink pajamas unbuttoned」を追加して生成。
気が付かれそうになったときの顔用に「red eyes, surprised face」を追加して生成。以上の3枚です。
切り取りパーツ
参考までに(何の?)切り取ったパジャマ。
体型に合わなかった部分はGIMPのケージ変形ツールで修正しました。Live2Dとかのデフォーマーみたいなものです。
こういう変形処理をJavaScriptで簡単にできたら、スカートの揺れアニメとか作りやすいと思うんがなぁ。画像加工のプログラミング知識が足りないので勉強中です。
技術解説
JavaScript初心者用の解説ですが、基本は前回の記事でやったマウス/タッチ操作の応用なので、主にパジャマの縮小処理部分についてだけ触れておきます。
中級者以上の人はHTMLソースを見ればすぐわかるでしょう。
document.getElementById('clothe_right').addEventListener('pointermove', function () {
if (!right_drag_flg) return;
document.getElementById('base2').style.display = 'none';
if ((event.clientX - right_drag_clientX) > 0) {
right_move++;
} else if ((event.clientX - right_drag_clientX) < 0) {
right_move--;
}
this.style.transform = 'translateX('+right_move/2+'%) scaleX('+(1 - right_move/100)+')';
if (right_move > 28) right_move = 28;
if (right_move < 0) right_move = 0;
right_drag_clientX = event.clientX;
});
長くなるので実際のコードよりも短く端折っていますが、大事なのはここだけ。
pointerdownイベント発生時に、マウスカーソル位置をright_drag_clientXに保存してあるので、マウスが動いたときにプラス(右)方向なのかマイナス(左)方向なのか判定しているだけ。
変数名にやたらrightが付いてるのは右側パジャマ用っていう意味。ほとんど同じコードを左パジャマ用にも書いている。
1ドット動くごとに、横方向のスケール(縮尺)を(1 - [移動量]/100)、つまり1%小さくしています。最大はハードコーディングしてあるとおり、28。つまり28%。scaleXでいうなら、scaleX(0.72)になるまで縮小します。それ以上だと違和感あるから、というだけの理由。決してオナニー(072)だからという理由ではない。たぶん。
縮小すると、当然X座標もズレてくるので、translateXにも同様の処理。といっても動かす量は半分で良い。なぜならscaleXは要素の中心を基準として縮小されるから。そいやtransform-originとかで変形の基準点変えても良かったかな? 次に機会があったら考えてみることにする。
まとめ
おまわりさん、ぼくです。













