みなさん、こんにちは。本日は頭と尻尾、体を動かすプログラムを実装するところまで作成しました。プログラムと動作を紹介します。なお、この記事は前回の続きになります。前回の記事を読んでいない方はそちらを参照してくださいね。

Vtuberのアバターとソフトウェア(プログラム)を1から作成してみた(その2)
みなさん、こんにちは。今回はVtuberのアバターとソフトウェアその2と言うことで、瞬きと口パクをするプログラムを実装しました。processing言語を用いて作成しましたので、今回はソースコードも載せていきます。この記事は前回の...
体と頭、尻尾のプログラム実装
上記の動画は体、頭、尻尾が動くプログラムを実装し、動作確認している様子です。各部位の動きはマウスの座標で動いています。まずは、体の動作から解説します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
//体を動かす void bodyAnimation() { //マウスのx座標で回転させるようにセット //これは仮設定です rotFase = (mouseX - SCREEN_SIZE/2)/25; //座標軸変更 translate(SCREEN_SIZE*0.43, SCREEN_SIZE*9/10); //座標回転 rotate(PI * rotFase / 600); //体の表示 image(body,SCREEN_SIZE*-0.43, SCREEN_SIZE*-9/10,SCREEN_SIZE,SCREEN_SIZE); //腕の表示 //※腕を動かすならアニメーションにした方が良さげという結論に至る image(rightHand,SCREEN_SIZE*-0.43, SCREEN_SIZE*-9/10,SCREEN_SIZE,SCREEN_SIZE); image(leftHand,SCREEN_SIZE*-0.43, SCREEN_SIZE*-9/10,SCREEN_SIZE,SCREEN_SIZE); //座標軸の初期化 resetMatrix(); } |
このプログラムを簡単に説明します。画像を回転して表示されることがこのプログラムで実装する内容です。まず原点の座標を移動させます。移動する位置は画像の回転軸の位置です。原点を移動したら、座標を回転させます。processingの座標軸回転はラジアン方式なので、計算式にはπを用いて計算します。体と腕の画像を表示させて、座標軸を初期化すれば終了です。同様に、頭と尻尾のプログラム作成します。腕を動かすプログラムも同様な方法で考えましたが、前回の記事で説明したアニメショーンを作った方が自然な感じで動くだろうと考え腕は実装しませんでした。
なお、回転角度はマウスの座標を取得して動くようにプログラムされています。体が動いたら左右に動くプログラムを作成する必要がありますが、今回は動作確認しやすいように意図的にプログラムしています。
最後にプログラム全文は下記に記載します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
import processing.sound.*; //マイク AudioIn in; //音量を取得してくれるもの Amplitude amp; //ウインドウのサイズ int SCREEN_SIZE = 500; PImage fase; int rotFase; PImage[] mouth; int mouthNum; boolean mouthCount; boolean mouthTime; PImage[] eye; int eyeNum; int eyeRandom; boolean eyeTime; boolean eyeCount; double eyeTimer; PImage leftFoot; PImage rightFoot; PImage body; PImage rightHand; PImage leftHand; int rotRigthHand; int rotLeftHand; PImage tail; void setup() { frameRate(60); PFont font = createFont("Yu Gothic",64,true); textFont(font); size(500,500); //マイク設定 in = new AudioIn(this); in.start(); // 音量の取得を開始 amp = new Amplitude(this); amp.input(in); //目の処理 eyeNum = 0; eyeCount = true; eyeTimer = millis(); eyeRandom = 0; eye = new PImage[5]; eye[0] = loadImage ("eye.png"); eye[1] = loadImage ("eye1.png"); eye[2] = loadImage ("eye2.png"); eye[3] = loadImage ("eye3.png"); eye[4] = loadImage ("eye4.png"); mouthNum = 0; mouthCount = true; mouth = new PImage[5]; mouth[0] = loadImage("mouth4.png"); mouth[1] = loadImage("mouth3.png"); mouth[2] = loadImage("mouth2.png"); mouth[3] = loadImage("mouth1.png"); mouth[4] = loadImage("mouth.png"); fase = loadImage ("face.png"); rotFase = 1; body = loadImage("body.png"); rightHand = loadImage("rightHand.png"); leftHand = loadImage("leftHand.png"); rotRigthHand = 0; rotLeftHand = 0; leftFoot = loadImage("leftFoot.png"); rightFoot = loadImage("rightFoot.png"); tail = loadImage("tail.png"); } void draw() { //目の処理 eyeAnimation(); //口の処理 mouthAnimation(); background(255,205,147); //尻尾の処理 tailAnimation(); image(rightFoot,0,0,SCREEN_SIZE,SCREEN_SIZE); image(leftFoot,0,0,SCREEN_SIZE,SCREEN_SIZE); //体と手の処理 bodyAnimation(); //顔の処理 faseAnimation(); } //尻尾を動かす void tailAnimation() { //座標軸変更 translate(SCREEN_SIZE*0.43, SCREEN_SIZE*4/5); rotate(PI * (-rotFase*1.5 + 10) / 500); image(tail,SCREEN_SIZE*-0.43, SCREEN_SIZE*-4/5,SCREEN_SIZE,SCREEN_SIZE); //座標軸の初期化 resetMatrix(); } //体を動かす void bodyAnimation() { //マウスのx座標で回転させるようにセット //これは仮設定です rotFase = (mouseX - SCREEN_SIZE/2)/25; //座標軸変更 translate(SCREEN_SIZE*0.43, SCREEN_SIZE*9/10); //座標回転 rotate(PI * rotFase / 600); //体の表示 image(body,SCREEN_SIZE*-0.43, SCREEN_SIZE*-9/10,SCREEN_SIZE,SCREEN_SIZE); //腕の表示 //※腕を動かすならアニメーションにした方が良さげという結論に至る image(rightHand,SCREEN_SIZE*-0.43, SCREEN_SIZE*-9/10,SCREEN_SIZE,SCREEN_SIZE); image(leftHand,SCREEN_SIZE*-0.43, SCREEN_SIZE*-9/10,SCREEN_SIZE,SCREEN_SIZE); //座標軸の初期化 resetMatrix(); } //頭を動かす void faseAnimation() { //座標を移動させる translate(SCREEN_SIZE*0.43, SCREEN_SIZE*3/5); //座標回転 rotate(PI * rotFase / 100); //顔、目、口の表示 image(fase,SCREEN_SIZE*-0.43+rotFase*2*SCREEN_SIZE/500,SCREEN_SIZE*-3/5,SCREEN_SIZE,SCREEN_SIZE); image(eye[eyeNum],SCREEN_SIZE*-0.43+rotFase*2*SCREEN_SIZE/500,SCREEN_SIZE*-3/5,SCREEN_SIZE,SCREEN_SIZE); image(mouth[mouthNum],SCREEN_SIZE*-0.43+rotFase*2*SCREEN_SIZE/500,SCREEN_SIZE*-3/5,SCREEN_SIZE,SCREEN_SIZE); //座標軸の初期化 resetMatrix(); } //口のアニメーション void mouthAnimation() { //マイクからの音声入力で反応する if(amp.analyze() * 1000 > 10) { mouthTime = true; } //口パク実行 if(mouthTime) { //口を開ける if(mouthCount && mouthNum < mouth.length){ mouthNum++; } //口を閉じる if(!mouthCount && mouthNum > 0){ mouthNum--; //口パク終了 if(mouthNum == 0) { mouthTime = false; mouthCount = true; } } //口が完全に開いた if(mouthNum == mouth.length-1){ mouthCount = false; } } } //目のアニメーション void eyeAnimation() { //瞬きする時間間隔判定 if((millis() - eyeTimer)/1000 > eyeRandom) { eyeTime = true; } //瞬き実行 if(eyeTime) { //目を閉じる if(eyeCount && eyeNum < eye.length){ eyeNum++; } //目を開ける if(!eyeCount && eyeNum > 0){ eyeNum--; //瞬き終了 if(eyeNum == 0) { eyeTime = false; eyeCount = true; eyeTimer = millis(); eyeRandom = int(random(21)) + 10; } } //目が完全に閉じた if(eyeNum == eye.length-1){ eyeCount = false; } } } |
次回は、画像処理のプログラムを作成していく予定です。画像処理のプログラムを作成したら、完成かと思います。

Vtuberのアバターとソフトウェア(プログラム)を1から作成してみた(その4)
みなさん、こんにちは。今回は自分の動きに合わせて体動くようにprocessingでプログラムを作成していきます。この記事は前回の続きです。前回の記事を読んでいない方はまずはそちらをご覧頂くとどのようにして作成しているか分かると思います。...
コメント