owned this note
owned this note
Published
Linked with GitHub
# 【AviUtl】動画編集ソフトでゲームを作る方法【入門】
###### tags: `MIS.W` `アドカレ2019`
どうも53代のエレンです。[みす53代非公式アドベントカレンダー2019](https://adventar.org/calendars/4121)の17日目の記事です。
### 本題に入る前に…
これとは別に裏アドカレがあります。
リンクはこちら→ https://hackmd.io/GRtxzMLJQUKsg4MSRsmY2w
本記事
===
突然ですが、皆さんの中に以下のような悩みを抱えたことのある人もいるのではないでしょうか。
<br>
<font size="4.5">**「動画編集をしている最中に突然ゲームを作りたくなった!でもゲームエディタを起動するのはめんどうだなぁ…」**</font>
<br>
[~~君たちの中にも、思った人がいるだろう?~~](https://dic.nicovideo.jp/a/%E9%A6%B4%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3)これは簡単に解決方法できます。**動画編集ソフトをゲームエディタにしてしまえばいい**のです。
というわけで、今日の記事は<font size="4.5">==**AviUtlでゲームを作る方法【入門】**==</font>です。
## 目次
[Toc]
前書き:After Effectsとの比較
===
同じ動画編集ソフトとして、AviUtlはよくAfter Effectsと比較されます。なぜAEではなくAviUtlなのか、簡単に書きます。
### ①AEだとゲームが作れない
最大のデメリットです。AEだとゲームが作れません。頑張ればできるかもしれませんが、大変です。
### ②無料
AEはお金がかかります。一方、AviUtlは無料です。
<br>
以上より、動画編集ソフトでゲームを作るなら基本的にAviUtlで問題ないと思います。「せっかく高い金を払ってAEを買ったのにゲームが作れないじゃないか!:angry::anger::angry::anger::angry::anger:」となっても後の祭りです。それでもいいという方はAEを使ってもいいと思います。
注意点
===
AviUtlでゲーム制作するにあたっていくつか注意点を挙げます。
- **スクリプトの記述に使う言語はLua**
スクリプトの記述にはLua言語を用います。[ここなど](https://qiita.com/dwarfJP/items/e033728f5cbecbabe11f)が詳しく書かれています。Lua特有の書き方などがあるので注意しましょう。
- **「再生ウィンドウの動画再生をメインウィンドウにする」のチェックを外す**
ここにチェックがついていると正常に動作しない場合があります。AviUtlを起動して「ファイル>環境設定>システムの設定」から設定できます。
- **ファイルの文字コードは必ず==Shift-JIS==にする**
自分はこれで嵌りました。Shift-JIS以外の文字コードで書くと、スクリプトが一切動かなくなってしまいます。特にVScodeを使用する場合は、文字コードがUTF-8になってしまうことが多いので必ず確認しましょう。
ゲーム制作
===
この記事は入門記事ということで、ゲーム制作のホントのホントに導入部分を書きます。具体的には、**キー入力をしている間、円が別の場所に表示されるようになる**スクリプトを書きます。
## 下準備
### scriptフォルダの作成
「aviutl.exe」ファイルがある階層に「script」フォルダを作成します。**scriptフォルダの中にスクリプトファイルなどを置いていきます。**「script」フォルダ直下に別のフォルダを作って、そのフォルダの中に置いても大丈夫です(ただし、2階層以上深いフォルダはAviUtlで認識されません)。
### rikky_moduleを導入
AviUtlのバージョンがv1.00以前なら[ここから](http://hazumurhythm.com/wev/amazon/?script=rikkymodulea2Z)、v1.10なら[ここから](http://hazumurhythm.com/wev/amazon/?script=NRMv2q9Q)rikky_moduleを導入します。リンク先の指示に従って導入してください。
### 「sample.obj」ファイルを作成
このファイルにスクリプトを記述します。拡張子を「.obj」とすることで、AviUtlが「カスタムオブジェクト」として認識します。今回は例として「sample.obj」とします。「sample」のところには任意の名前を入れても構いません。
AviUtlでは、カスタムオブジェクトを配置して再生すると、このカスタムオブジェクトのファイルが ==**毎フレーム**== 呼ばれます。Unityでいう**Update関数**のようなものです。
VScodeを使用する場合、拡張子を「.obj」にするとLuaの補完が効かないので、同じ階層に「sample.lua」ファイルを作ってそっちでコードを書くのがオススメ。その場合、sample.objには以下の一行を記述しておきます。
```lua=
dofile(obj.getinfo("script_path").."sample.lua")
```
ただし、上記のような手法を採るとトラックバー、チェックボックス、ダイアログなどをスクリプト制御できなくなります(厳密にはグローバル変数を用いればできますが、非推奨)。
:::info
:bulb:**トラックバー、チェックボックス、ダイアログ**
以下の赤線で囲った部分が自分で編集できる部分です(書き方は[こちら](https://aviutlscript.wiki.fc2.com/wiki/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E4%BD%9C%E6%88%90)参照)。変数の値を、スクリプトではなく設定ダイアログから変更することができます。
![](https://i.imgur.com/eTEmg2p.png =400x)
:::
### AviUtlを起動して、カスタムオブジェクトを配置
AviUtlを起動して適当にプロジェクトを作成し、カスタムオブジェクトを配置します。その後、設定ダイアログの左下から「sample」を選びます。このとき、カスタムオブジェクトの長さを長めに取ってください。「カスタムオブジェクトの長さ=プレイできる時間です。」
<br>
## スクリプトを書く
実際にsample.luaにスクリプトを書き込んでいきます。先ほど記した通り、**キー入力をしている間、円が別の場所に表示されるようになる**スクリプトを書きます。AviUtlでは**F5**キーを押すとスクリプトの変更が反映されます。変更を確認したいときは**F5キーを押してください**。
先にスクリプト全体を知りたい方→[#スクリプト全体](#スクリプト全体)
### 円を表示する
AviUtlではスクリプトで動画、画像、図形、テキストを描画できます。描画のおおまかな流れは以下の通り。
1. obj.load関数で読み込むオブジェクト(動画、画像など)を指定する
2. obj.effect関数でエフェクトをかける
3. obj.draw関数で描画する
---
#### <font size="4.5">**obj.load**</font>
```lua
obj.load(type, …)
```
obj.load関数では、描画するオブジェクトを読み込みます。第一引数で読み込むオブジェクトを指定します。オブジェクトによって2つ目以降の引数が変わります。例えば、図形を読み込むときは第一引数が`"figure"`になり、それ以降の引数は以下のようになります。
```lua
obj.load("figure", name[, color, size, line])
```
|名前|説明|
|--:|:---|
|name|図形の名前(背景、円、三角形、四角形、五角形、六角形、星形)|
|color|図形の色(16進数表記で0x000000~0xffffff、RGBの順)|
|size|図形のサイズ|
|line|図形のライン幅|
[ ]の中は省略可です。省略した場合は、デフォルト値が入ります(以下同様)。
<br>
#### <font size="4.5">**obj.effect**</font>
```lua
obj.effect(name[, parameter1, valu1, parameter2, valu2, …])
```
> 実はnameも省略できるが、関数の意味が変わるのでここでの説明は割愛
|名前|説明|
|--:|:---|
|name|エフェクトの名前を指定|
|parameter|エフェクトのパラメータの名前を指定|
|value|エフェクトのパラメータの値を指定|
AviUtlでは「フィルタ効果の追加」からエフェクトを掛けられますが、obj.effect関数を使えばスクリプトからエフェクトが掛けられます。
使い方は、たぶん口で説明するより具体例見た方が早いです。↓
:::info
:bulb:「縁取り」エフェクトを掛ける
例えば、以下のように記述してみます。
```lua
obj.effect("縁取り", "ぼかし", 30, "color", 0xffff00)
```
これは、オブジェクトに以下のフィルタ効果を掛けるのと同じです。
![](https://i.imgur.com/9J80MbF.png =450x)
ぼかしを30、縁色を黄色に設定しています(サイズにはデフォルト値の3が入ります)。
:::danger
:memo:パラメータの名前は基本的に設定ダイアログのものと同じものを書けばよいですが、上記の「color」のように異なる場合があります。[こちらのサイト](https://madeinpc.blog.fc2.com/blog-entry-1075.html)が参考になります。
:::
#### <font size="4.5">**obj.draw**</font>
```lua
obj.draw([ox, oy, oz, zoom, alpha, rx, ry, rz])
```
|名前|説明|
|--:|:---|
|ox, oy, oz|描画する相対座標|
|zoom|拡大率(1.0 = 等倍)|
|alpha|透明度(0.0 = 透明、1.0 = 不透明)|
|rx, ry, rz|各軸に対する回転角度|
最後にobj.draw関数を使うことで画面に描画されます。ちなみに、AviUtlでは画面の中央が原点です。`obj.draw()`とだけ書くと、中央に描画されます。
---
#### <font size="4.5">**描画**</font>
上記三つの関数を使用しながら円を描画していきましょう。今回は円に縁取りとシャドーを掛けて描画します。まず、背景を白っぽくしたいので以下の二行を追加します。
```lua=21
obj.load("figure", "背景", 0xffffff) --白っぽい背景を読み込む
obj.draw() --描画
```
続いて、円を描画するために以下の三行を追加します。
```lua=24
obj.load("figure", "円", 0xff0000, 200) --赤色、サイズ200の円を読み込む
obj.effect("縁取り", "color", 0xffff00) --縁取りをかける
obj.effect("シャドー") --シャドーエフェクトをかける
obj.draw() --描画
```
すると、以下のように表示されたと思います。
![](https://i.imgur.com/uaSZzSi.png =400x)
これで円の描画ができました。好みに合わせて図形を変えたり、エフェクトを追加したりしてもいいかもしれません。
---
### キー入力を作る
#### <font size="4.5">**概要**</font>
まず、rikky_moduleをダウンロードした際、中に「rikky_module.dll」が入っていたと思います。それを、sample.luaがある場所と同じ場所に配置します。そして、冒頭に以下を追加します。
```lua=
require("rikky_module")
```
これでrikky_module.dllが使えるようになります。rikky_module.dll内の関数を使用する場合、`rikky_module.xxxx()`という風に記述します。
#### <font size="4.5">**key関数**</font>
キー入力を受け付けるには、rikky_module内にあるkey関数を使います。
```lua
table [, table] = rikky_module.key(string or number [, string or number, ...])
```
> 「rikky_moduleの使い方.txt」から抜粋
key関数の引数として、キー入力しているかを判定してほしいキーを、文字列か数字で渡します。戻り値は、引数で指定した各キーが押されているかどうかのboolean型が格納されたテーブル型が返ってきます。
:::info
:memo:テーブル型とは?
>「テーブルは、配列と STL の map が一緒になったようなデータです。」([C/C++ 言語プログラマのための Lua 入門リファレンス](https://qiita.com/dwarfJP/items/e033728f5cbecbabe11f)より)
:::
ここでは配列が返されると思っていいです。
:::info
:memo:以下のコードを試してみてください。
```lua=
require("rikky_module")
local keyPressed = rikky_module.key(65, "B", "SHIFT", "←")
local keyName = ""
if keyPressed[1] then
keyName = "A"
elseif keyPressed[2] then
keyName = "B"
elseif keyPressed[3] then
keyName = "SHIFT"
elseif keyPressed[4] then
keyName = "←"
else
keyName = "なしor未定義"
end
obj.load("text", "押されているボタン:"..keyName)
obj.draw()
```
A、B、Shift、左矢印キーをそれぞれ押してみてください。押しているボタンが表示され、キー入力ができていることが分かると思います。keyPressedに、順にA、B、Shift、左矢印キーが入力されたかどうかのbooleanが入っています。
対応しているキーは、rikky_module導入時に同封されている「rikky_moduleの使い方.txt」参照。
:::
---
#### <font size="4.5">**実際に書く**</font>
今回は矢印キーを押すと、その方向に円が表示されるスクリプトを書きます。本当は移動させたかったのですが説明が複雑になるので諦めました…。
まずはrikky_moduleを読み込んで、各矢印のキー入力をkey関数で受け取ります。
```lua=
require("rikky_module")
local keyPressed = rikky_module.key("←", "↑", "→", "↓")
```
これで、keyPressedに矢印が
次に、円の描画座標を変えるために変数${x、y}$を用意します
```lua=+
local x = 0
local y = 0
```
そして、キー入力に合わせて座標を書き換えます。
まず試しに、左矢印が押されたときに、左側に円が表示されるように座標を書き変えます。
```lua=7
if keyPressd[1] then
x = -200
y = 0
end
```
if文で、左矢印が押されたときに${x}$座標が-200に書き換わるようにします。見やすいかなと思って${y}$座標に0入れてますが意味ないので書かなくてもいいです。
> ちなみに、Luaでは配列のインデックスは0ではなく1から始まります。
[color=blue]
同様に、他の矢印キーを入力したときの座標を書いていきます。
```lua=7
if keyPressed[1] then
x = -200
y = 0
elseif keyPressed[2] then
x = 0
y = -200
elseif keyPressed[3] then
x = 200
y = 0
elseif keyPressed[4] then
x = 0
y = 200
end
```
これで、キー入力によって座標を変えるスクリプトが書き終わりました。
最後に円が描画される場所が変数${x、y}$の値になるように書き換えます。先ほど円の描画をしたときは以下のようなスクリプトでした。
```lua=24
obj.load("figure", "円", 0xff0000, 200)
obj.effect("縁取り", "color", 0xffff00)
obj.effect("シャドー")
obj.draw()
```
これのobj.draw()の引数に変数${x、y}$を渡してあげるように書き換えます。
```lua=27
obj.draw(x, y)
```
これでスクリプトは完成です。実際にAviutlを再生して矢印キーを押してみましょう。円の位置が変わるはずです。
スクリプト全体
===
今回書いたスクリプトの全体です。
```lua=
require("rikky_module")
local keyPressed = rikky_module.key("←", "↑", "→", "↓")
local x = 0
local y = 0
if keyPressed[1] then
x = -200
y = 0
elseif keyPressed[2] then
x = 0
y = -200
elseif keyPressed[3] then
x = 200
y = 0
elseif keyPressed[4] then
x = 0
y = 200
end
obj.load("figure", "背景", 0xfffaf0)
obj.draw()
obj.load("figure", "円", 0xff0000, 200)
obj.effect("縁取り", "color", 0xffff00)
obj.effect("シャドー")
obj.draw(x, y)
```
まとめ
===
ゲーム制作の導入として、図形の描画とキー入力の方法を書きました。今日書いたスクリプトでは大したゲームにはなってませんが、まあ、入門記事だから、多少は、ね?
最後に
===
さあ~て、明日の記事を書くのは…
<font size="10" class = "color"><div style="text-align:center;"><div class="soekipurupuru"><div class="soekirotate">${†soeki†}$</div></div></div></font>
です!soekiについて詳しく知りたい人は
<font size="4" class="adkare"><div style="text-align:center;">[**アドカレ7日目#今日のソエキ大辞典**](https://hackmd.io/@TmGZV_MXRdusFleUVyzsDQ/HylBiJZaS#%E4%BB%98%E9%8C%B21-%E4%BB%8A%E6%97%A5%E3%81%AE%E3%82%BD%E3%82%A8%E3%82%AD%E5%A4%A7%E8%BE%9E%E5%85%B8)</div></font>
を参照してください。何やら夏休みが待ち遠しいようです(~~おじいちゃん、夏休みはもう終わったでしょ?~~)。きっと素晴らしい記事を書いてくれると思うのでお楽しみに!!!!!!!!!!!!!!
<style>
.color {
animation: iroiroiroiroi 1.0s linear 0s infinite;
}
@keyframes iroiroiroiroi {
0% { color: magenta; }
33% { color: cyan; }
67% { color: yellow; }
100% { color: magenta; }
}
.soekipurupuru {
display:inline-block;
font-size: 30px;
font-family: monospace;
animation: soekinorenai 0.1s linear 0s infinite;
}
@keyframes soekinorenai {
0% { transform: scale(1.0, 1.0) translate(5%, 0%) }
50% { transform: scale(1.0, 1.0) translate(-5%, 0%) }
100% { transform: scale(1.0, 1.0) translate(5%, 0%) }
}
.soekirotate {
display:inline-block;
font-size: 30px;
font-family: monospace;
animation: soekirotate 1.5s ease 0s infinite;
}
@keyframes soekirotate {
0% { transform: scale(1.0, 1.0) rotate(-180deg); }
50% { transform: scale(2.0, 2.0) rotate(0deg); }
100% { transform: scale(1.0, 1.0) rotate(180deg); }
}
.adkare {
display:inline-block;
font-size: 30px;
font-family: monospace;
animation: ad 1.0s ease-in-out 0s infinite;
}
@keyframes ad {
0% { transform: scale(1.0, 1.0); }
40% { transform: scale(1.5, 1.5); }
80% { transform: scale(1.0, 1.0); }
}
</style>