9×16 解説


だそうです

先日投稿した音MADについて、動画の解説をしたり制作経緯を書いたりしていきます。


解説

導入 黒塗り×原西

9×16

タイトル通り、これから9×16でやっていきますよ、と宣言しています。
同時に、これは黒塗り×原西の音MADですよ、とも宣言しています。
つまり右上は数字の16で「原西」を作っています… 遠目から見れば多分読めるはず…

屁+紹介 手文字+手話

手による表現

左上の手の形は手文字で平仮名「へ」を表します。ギャグ「屁」です。右上は口の前で👍を左右させる手話をしており、「紹介」の意味となります。
「屁」が一文字であること、ここではギャグが重なることから、手による言語表現で統一しました。この後の点字パートとの関連もあります。

早口言葉 漢点字+点字

漢点字

漢点字(こんなのがあるんですね)で「早口言葉」と書かれていて、それを指が読み取っています。

点字

尺が余ったので後半は点字で表現された早口言葉自体のアニメーションです。指が点字をスワップしたり押したり引いたり、点字が動いたり現れたりしています。
電子上のものを身体的に操作したい、という欲求があったりするので、この表現は気に入っています。

かなしみ モールス信号

モールス信号

右上の指が「かなしみ」のモールス信号を打っています。原曲が黒塗りなので、モールス信号は外せない手法でした。
原曲ではこの箇所で「U:・・ー」を発しているため、それに合わせて「U」を重ねています。また右下の改行マークは四回目では意味を為さないため、「ユ!」に改変しています。

おちゃらか 手旗信号

手旗信号

手旗信号で「おちゃらか」を表しています。ギャグが分割されているので分かりやすいよう、上にカウントの黒丸を付けています。

ねがい QWERTY配列

QWERTY配列

「ねがい」をローマ字表記でQWERTY配列のキーボードに入力しています。後の五十音表もそうですが、文字がその位置で決定される例です。
図形で文字書くの楽しいですね。

ジャンケン 絵文字

絵文字

絵文字で「ジャンケン」を表しています。✊✌✋(👌)とギャグの中で1番絵文字で表せそうだったのでこの組み合わせにしました。
絵文字って表意文字の究極ですよね。

あやす 五十音表

五十音表

五十音表の上で「あやす」を1文字ずつ追っています。「あ」「や」「す」の3文字では真仮名を用いています。図形で文字書くの楽しいですね2
一方で他の字は自分の手描きのひらがなを用いています。手描きツールとしての特性を反映させたいという理由からです。

ファイル名出すのちょっと怖いので黒塗り

次の「必殺技」へのシーンチェンジはkuronuriで鳴っている音を表しているつもりです。

必殺技 四角号碼

四角号碼

四角号碼で「必殺技」などを表しています。角のアイコン化はこのサイトを参考にしています。

使わなかったのもある

何となく元の字に見えなくもないの面白いですよねー
ポリゴンショック回避のため、このシーンだけ2色構成の制限を破ってしまっています。目歯は当て字で意味はないです。

どっち+とんち ハングル

ハングル

「どっち」「とんち」それぞれの音のハングル表記がアニメーションされています。偶然発音が近いギャグ名が並んでいたので、図形的な表音文字で一番身近なハングルで表現しました。
ハングルが歩いたり進化したりしてますね 可愛い~
「とんち」の音声ともよくマッチしていると思います。

股にT 文字種クイズ

「股にT」が文字種クイズ化しています。おそらく「漢あA」で一つに特定されるはずですが、見直してません…

空を見ろ! 音階

音階?????

画像の通りです、こじつけです。

? ?

ギャグ名「?」はそもそも記号なのでそのまま使いました。原西ギャグ大全には多くのギャグ「?」が存在することから、こちらも?を数多く(39個)描きました。

お祭り

このパートにはこれまでのような表現手法はあまりありません。ドットアニメーションで「お祭り」を表すというテーマで、omodakaのyosawya sanのMVに強く影響を受けています。

1/3
  • 祭りの妖怪(何故?)といえば提灯お化け

    • yosawya sanにおける妖成分を入れたかった

  • 祭りといえばお神輿

    • 人型たちにはハチマキを付けているつもりです

  • デコトラ(何故?)

2/3
  • デコトラ+電光掲示板

    • 「画面」を16×9の中に入れたいなと思っていて、結果このようになりました。駅のホームとか電車内とかの極小ドット文字ってほんとに凄いなーと常々思っていたので、「耳祭り」を書いて表示させました。

3/3
  • 鳥だ!飛行機だ!スーパーマンだ!

  • 右は黒塗り世界宛て書簡(足つき)ですね

  • 右から2番目はあれですね あれです

    • スーパーマンがいる辺りで流れる女性の声もあれです

蛇足

4/3

チョキがさようならの手話をして終わりです。

解説は以上です。
文字の表現方法ってこんなに沢山あるんだ!と驚いてもらえたなら、この動画を作った甲斐がありました。

以下は制作の経緯についてです。もしよければ是非

音声

この音MADを作り始めたきっかけは、何を隠そう、お皿タウンさんの「黒塗りギャグ大全」です。特に最初のセリフ合わせがとても印象的で、視聴後もずっと頭に残っていました。そのため再度聞こうと検索してみたのですが全く引っかからず、仕方なくうろ覚えでREAPER上で再現したものが後のプロジェクトファイルになりました。
お皿タウンさん、本当にありがとうございます。

新たにギャグを当てはめる上で、黒塗りの歌詞やリズムに合わせるように選んでいった覚えがあります。

映像作成中に書いたメモ

こんな感じで音声は去年の大晦日あたりには完成していました。
個人的にとても気に入っていて、スマホに入れて外で何度も聞いてました。

映像

一方で、どういった映像を付けるかのアイデアがなかなか思いつかず、長い間眠らせていました。このような映像にしようとアイデアが組み合わさったのは8月の頭で、そこから一気に制作し切りました。

テーマ

  • 基本図形を用い、アス比16:9の最小単位16×9で動画を構成する

    • このアイデアは主に、TDC展2024にてInstitute of Designのポスターに度肝を抜かれたことから来ていると思います。たった6種の図形でここまで多様に表現できるのか!と非常に衝撃を受けました。また自分はこのような幾何学図形が大好きなのでブッ刺さりました。

      • 結果的に自分のは図形5種で構成されててちょっと勝った気がした

    • さらに、otogrooveの高速合作で知ったomodakaに最近ドハマりしているために、yosawya sanのMVからも影響を受けています(特に後半)。最低限のピクセルによるドット絵に惹かれるところがありました。(例:これとかこれ)

    • このようなことがあった中で、動画の最小単位とは何だ...?と考えていて出てきたのがこのアイデアです。黒塗りMVはほぼ白黒だし、いける!となりました。
      AviUtl上1600×900, 60fpsでの編集です。

    • フロクロさんのDJmixである16と近いコンセプトですが、発想はこれと独立していたと思います。

      • 曲の印象ってここまで情報減らせるんだ!?ってなりました

      • reaper完結なのも理想すぎる

最高
  • 文字列を表現できる多様な手法を用いる

    • きっかけは友人から四角号碼を知ったことです。どんな漢字もその形状から4桁の数で(ほぼ)指定できる、このシステムに衝撃を受けました。そういえば黒塗りで出てくるモールスも文字列をリズムに変換してて共通してるな…こういうの集めるか…と思い立ち、このようなテーマとなりました。

    • 見た人がへーこんな手法があるのか!と思ってくれていたら嬉しい

    • あくまで文字表現であり謎解きとしての意図はありませんでした がそのような楽しみ方をしてくれた方がいたのも嬉しかったです

  • AviUtlに触りたくない

    • 音MADや映像を作る経験が足りていないというのもありますが、自分がどうも映像編集というのに向いてないなと思うことがあります。対象にエフェクトを重ねていくという操作は好きなのですが、映像編集とはそのエフェクトを時間変化させていくことであり、これが本当に苦手です。だって、動画は二次元なのに何で時間軸まで意識しないといけないんですか!!!!!!!!

      • 自分がAviUtlに触るとどうしてもエフェクト準拠のありきたりになってしまう、単純にAviUtlが重くてイライラが溜まる、というのもあります。

    • 単純図形で構成するというテーマもあるため、各フレームごとの画像を他のツールで描き、AviUtlではそれをつなげるだけということにしました。つまりある意味手描き動画です。このツールはchatGPTやclaudeにp5.jsで作ってもらいました。(コードを記事最下に置いておきます)

      • 本当は動画書き出しまで全てこれでやってみたかった…

      • group_inouのHAPPENINGからさんを知ったりァネイロ,melonadeさんの一龠を知ったりして、プログラミングでツールを作ることにも憧れを持っていたので!

ということで、「16×9の基本図形と様々な手法でギャグのネタ名を表現する映像をp5js上のツールで作る」ことになりました。

アニメーションやドット絵、ピクト絵などを描く経験が0で(うごメモとかやってれば良かった…?)、ほんとにこれで伝わるのかなーと思いながら描いてました。逆にやることすべてが新鮮でもありました。
とくに自ツールで作字をたくさん出来たのが良かったですね。

ギャグ名と表現手法のペア付け、実際のネタ名表現をどうするか考えるのもとても楽しかったです。音声を作っているときは考えてもいなかった意外なつながりが見つかったり、表現手法が音声のリズム感を増強しているように感じたり、偶然に助けられた箇所が多くあります。
タイトルとなった「9×16」と黒塗り×原西の対応は意図せず制作中に偶然思いついたものです。天啓でしたね

自分の好きなものを詰め込んだ、自分にしか作れない映像が作れたと思います。また何か新しいことを思いついたら投稿したいですね。

書き足りないことは多くありますが、纏まらなくなるので下に雑に書き連ねています。もしよければ是非


雑記

  • こんなに見てもらえるとは思わなかった!とても嬉しいです

    • フロクロさん巡回速すぎてビックリしました 上海いましたよね?

    • ruijiさんに反応貰えたの特に嬉しかったです 図形、文字、配置を扱うのが好きな作者さんという印象があるので

    • 正直実感が湧かない

  • あれやっておけばよかった!という後悔が全然ないのが嬉しい

  • 音声はわかりません 音量バランスとか本当に

  • ドンがつくポケモン

    • この動画見た時衝撃受けて自分もやってみて~とか思ってたけど、いつの間にか似たようなことをしていた

    • 好きすぎる 音声からCAまで貫いていて最高

  • 文章力が無い!!!

  • 自分はパラメータをキリよくしないと済まない性格なので、今回のはこれにも合っているなと思った

    • 例えばreaperでボリュームが-2.3dBになってるとか、aviutlでx座標が234.5になってるとかが耐えられない

      • これ耐えられる人すごいと思う

  • 体調によって映像と音声の先行具合が変わるの怖い

  • omodakaって良いですよね~

    • MVが好みすぎ これとか

  • 4×3は無理な気がする どうすれば

    • Institute of Designのそれを使った映像とかも見てみたい 権利的なとこが怪しいけど

  • 他に文字(列)の面白表現方法あったら教えてください まだまだ知りたい

  • 動画関係ないことも書いちゃいます

  • 音MAD(映像面)を実体化するアイデアとして、フリップドットディスプレイ(こういうやつ)による装置化を以前から考えています。

    • 左右反転に近しい動きをするところに音MADらしさを感じて

    • ただ、電子工作系の技能経験が0で何もできていません

    • この動画のテーマを決めるときにはこのアイデアのことは忘れていて、そういえば最適だなーと制作途中で気付いた

      • でもこの動画は音MADらしい映像ではなく、この動画をパタパタさせることは本意ではないです。いつかこのアイデアにぴったりな音MAD作りたいですね

    • 7セグのフリップディスプレイや大人の科学のフリップ目覚ましとかLEDディスプレイとかも使って

    • 実体化するだけでその良さって発生しますよね

没1
没2
没3
没4
没5

フロク

今回使ったツールのコードです。ChatGPTやClaudeで生成しています。p5.jsの仕様をあまりよくわかってないのですが、ここのデフォルトのsketch.jsのところにコピペすればいいはずです。改変しまくってください

Drawing

+Ctrlで消しゴム,+Shiftで回転ツールになります

let cellSize = 50; // マスのサイズ
let gridSizeX = 16; // グリッドの横幅
let gridSizeY = 9;  // グリッドの高さ
let grid = []; // グリッドの状態を保存する2次元配列
let currentTool = 4; // 現在選択されているツール
let previousTool = 4; // Control キーを押す前のツール
let isDrawing = false; // マウスがドラッグされているかどうか
let lastRotatedCell = null; // 最後に回転したセルを記録

function setup() {
  createCanvas(cellSize * gridSizeX, cellSize * gridSizeY);
  initGrid();
  createToolButtons();
}

function draw() {
  background(222);
  drawGrid();
  
  if (keyIsDown(CONTROL) && currentTool !== 10) {
    previousTool = currentTool;
    currentTool = 10; // 消しゴムツール
  } else if (!keyIsDown(CONTROL) && currentTool === 10 && previousTool !== 10) {
    currentTool = previousTool;
  }
}

function initGrid() {
  for (let i = 0; i < gridSizeY; i++) {
    grid.push(new Array(gridSizeX).fill(10));
  }
}

function drawGrid() {
  for (let i = 0; i < gridSizeY; i++) {
    for (let j = 0; j < gridSizeX; j++) {
      drawCell(grid[i][j], j * cellSize, i * cellSize);
    }
  }
}

function drawCell(type, x, y) {
  push();
  translate(x, y);
  fill(0);
  noStroke();
  
  switch(type) {
    case 0: case 1: case 2: case 3: // 扇形
      let centers = [
        [0, 0],
        [cellSize, 0],
        [cellSize, cellSize],
        [0, cellSize]
      ];
      arc(centers[type][0], centers[type][1], 
          cellSize * 2, cellSize * 2, 
          HALF_PI * type, HALF_PI * (type + 1), PIE);
      break;
    case 4: // 正方形
      rect(0, 0, cellSize, cellSize);
      break;
    case 5: // 円
      ellipse(cellSize/2, cellSize/2, cellSize, cellSize);
      break;
    case 6: case 7: case 8: case 9: // 三角形
      let points = [[0, 0], [cellSize, 0], [cellSize, cellSize], [0, cellSize]];
      triangle(
        points[type-6][0], points[type-6][1],
        points[(type-5)%4][0], points[(type-5)%4][1],
        points[(type-4)%4][0], points[(type-4)%4][1]
      );
      break;
    case 12: case 13: case 14: case 15: // D型図形
      drawDShape(type - 12);
      break;
  }
  
  pop();
}

function drawDShape(rotation) {
  beginShape();
  if (rotation === 0) { // 上向き
    rect(0, cellSize/2, cellSize, cellSize/2); // 下半分の長方形
    arc(cellSize/2, cellSize/2, cellSize, cellSize, PI, TWO_PI); // 上半分の半円
  } else if (rotation === 1) { // 右向き
    rect(0, 0, cellSize/2, cellSize); // 左半分の長方形
    arc(cellSize/2, cellSize/2, cellSize, cellSize, -HALF_PI, HALF_PI); // 右半分の半円
  } else if (rotation === 2) { // 下向き
    rect(0, 0, cellSize, cellSize/2); // 上半分の長方形
    arc(cellSize/2, cellSize/2, cellSize, cellSize, 0, PI); // 下半分の半円
  } else { // 左向き
    rect(cellSize/2, 0, cellSize/2, cellSize); // 右半分の長方形
    arc(cellSize/2, cellSize/2, cellSize, cellSize, HALF_PI, PI + HALF_PI); // 左半分の半円
  }
  endShape(CLOSE);
}

function createToolButtons() {
  let buttonY = height + 20;
  createButton('正方形').position(10, buttonY).mousePressed(() => { currentTool = 4; previousTool = 4; });
  createButton('円').position(80, buttonY).mousePressed(() => { currentTool = 5; previousTool = 5; });
  createButton('扇形').position(150, buttonY).mousePressed(() => { currentTool = 0; previousTool = 0; });
  createButton('三角形').position(220, buttonY).mousePressed(() => { currentTool = 6; previousTool = 6; });
  createButton('D型').position(290, buttonY).mousePressed(() => { currentTool = 12; previousTool = 12; });
  createButton('消しゴム').position(360, buttonY).mousePressed(() => { currentTool = 10; previousTool = 10; });
}

function mousePressed() {
  isDrawing = true;
  lastRotatedCell = null;
  let col = floor(mouseX / cellSize);
  let row = floor(mouseY / cellSize);
  if (keyIsDown(SHIFT)) {
    rotateShape(col, row);
  } else {
    drawAtCell(col, row);
  }
}

function mouseDragged() {
  let col = floor(mouseX / cellSize);
  let row = floor(mouseY / cellSize);
  if (keyIsDown(SHIFT)) {
    if (lastRotatedCell === null || lastRotatedCell.col !== col || lastRotatedCell.row !== row) {
      rotateShape(col, row);
      lastRotatedCell = { col, row };
    }
  } else {
    drawAtCell(col, row);
  }
}

function mouseReleased() {
  isDrawing = false;
}

function drawAtCell(col, row) {
  if (col >= 0 && col < gridSizeX && row >= 0 && row < gridSizeY) {
    grid[row][col] = currentTool;
  }
}

function rotateShape(col, row) {
  if (col >= 0 && col < gridSizeX && row >= 0 && row < gridSizeY) {
    let currentType = grid[row][col];
    if (currentType >= 0 && currentType <= 3) { // 扇形
      grid[row][col] = (currentType + 1) % 4;
    } else if (currentType >= 6 && currentType <= 9) { // 三角形
      grid[row][col] = 6 + ((currentType - 6 + 1) % 4);
    } else if (currentType >= 12 && currentType <= 15) { // D型図形
      grid[row][col] = 12 + ((currentType - 12 + 1) % 4);
    }
    // その他の図形は回転しない
  }
}

Pattern Generator

let cellSize = 50;
let gridSizeX = 16;
let gridSizeY = 9;
let grid = [];
let probabilitySlider;
let probabilityDisplay;
let shapeCheckboxes = {};
let shapes = ['square', 'circle', 'fan', 'triangle', 'dShape'];

function setup() {
  createCanvas(cellSize * gridSizeX, cellSize * gridSizeY);
  initGrid();
  createControls();
}

function draw() {
  background(222);
  drawGrid();
}

function initGrid() {
  for (let i = 0; i < gridSizeY; i++) {
    grid.push(new Array(gridSizeX).fill(10));
  }
}

function createControls() {
  createButton('ランダム生成').position(10, height + 20).mousePressed(generateRandomPattern);
  
  probabilitySlider = createSlider(0, 100, 50);
  probabilitySlider.position(150, height + 20);
  probabilitySlider.input(updatePattern); // スライダーの値が変更されたときに呼び出す
  
  createP('配置確率: ').position(150, height + 40);
  probabilityDisplay = createSpan('50%'); // 確率表示を初期値に設定
  probabilityDisplay.position(220, height + 40);
  
  let yPos = height + 70;
  shapes.forEach((shape, index) => {
    shapeCheckboxes[shape] = createCheckbox(shape, true);
    shapeCheckboxes[shape].position(10, yPos + index * 30);
    shapeCheckboxes[shape].changed(updatePattern); // チェックボックスの状態が変更されたときに呼び出す
  });
}

function generateRandomPattern() {
  let p = probabilitySlider.value() / 100;
  let selectedShapes = shapes.filter(shape => shapeCheckboxes[shape].checked());

  for (let i = 0; i < gridSizeY; i++) {
    for (let j = 0; j < gridSizeX; j++) {
      if (random() < p) {
        let shape = random(selectedShapes);
        grid[i][j] = getShapeType(shape);
      } else {
        grid[i][j] = 10; // 空白
      }
    }
  }
}

function getShapeType(shape) {
  switch(shape) {
    case 'square':
      return 4;
    case 'circle':
      return 5;
    case 'fan':
      return floor(random(4)); // 0-3
    case 'triangle':
      return 6 + floor(random(4)); // 6-9
    case 'dShape':
      return 12 + floor(random(4)); // 12-15
  }
}

function drawGrid() {
  for (let i = 0; i < gridSizeY; i++) {
    for (let j = 0; j < gridSizeX; j++) {
      drawCell(grid[i][j], j * cellSize, i * cellSize);
    }
  }
}

function drawCell(type, x, y) {
  push();
  translate(x, y);
  fill(0);
  noStroke();

  switch(type) {
    case 0: case 1: case 2: case 3: // 扇形
      let centers = [[0, 0], [cellSize, 0], [cellSize, cellSize], [0, cellSize]];
      arc(centers[type][0], centers[type][1], cellSize * 2, cellSize * 2, 
          HALF_PI * type, HALF_PI * (type + 1), PIE);
      break;
    case 4: // 正方形
      rect(0, 0, cellSize, cellSize);
      break;
    case 5: // 円
      ellipse(cellSize/2, cellSize/2, cellSize, cellSize);
      break;
    case 6: case 7: case 8: case 9: // 三角形
      let points = [[0, 0], [cellSize, 0], [cellSize, cellSize], [0, cellSize]];
      triangle(
        points[type-6][0], points[type-6][1],
        points[(type-5)%4][0], points[(type-5)%4][1],
        points[(type-4)%4][0], points[(type-4)%4][1]
      );
      break;
    case 12: case 13: case 14: case 15: // D型図形
      drawDShape(type - 12);
      break;
  }

  pop();
}

function drawDShape(rotation) {
  beginShape();
  if (rotation === 0) { // 上向き
    rect(0, cellSize/2, cellSize, cellSize/2);
    arc(cellSize/2, cellSize/2, cellSize, cellSize, PI, TWO_PI);
  } else if (rotation === 1) { // 右向き
    rect(0, 0, cellSize/2, cellSize);
    arc(cellSize/2, cellSize/2, cellSize, cellSize, -HALF_PI, HALF_PI);
  } else if (rotation === 2) { // 下向き
    rect(0, 0, cellSize, cellSize/2);
    arc(cellSize/2, cellSize/2, cellSize, cellSize, 0, PI);
  } else { // 左向き
    rect(cellSize/2, 0, cellSize/2, cellSize);
    arc(cellSize/2, cellSize/2, cellSize, cellSize, HALF_PI, PI + HALF_PI);
  }
  endShape(CLOSE);
}

function updatePattern() {
  generateRandomPattern(); // ランダムパターンを生成
  updateProbabilityDisplay(); // 確率表示を更新
}

function updateProbabilityDisplay() {
  let probability = probabilitySlider.value();
  probabilityDisplay.html(probability + '%'); // 確率表示を更新
}


この記事が気に入ったらサポートをしてみませんか?