チュートリアルページ一覧
チュートリアル
タイトル準備編
タイトル実践編
ERB製作実践編

当ページはDiscordのとあるサーバーの発言をまとめたものです
Discord - eraEVENT_KXX
https://discord.gg/cuSh6y5j93

タイトル実践編から続いてERBの実践的な内容を説明

VSCodeの導入方法について

PDF形式で詳しく説明されたものもある。こちらのほうが本格的で分かりやすい
eraVSCode:ダウンロード

以下画像付きなので折りたたみ

変数の種類について

eraで初めてプログラミング触りますという人なら「変数って何?」と思う人も多いはず
散々説明されてる通り変数とは箱のようなもの もう本当に手垢が付いた解説にしかならないので割愛
この概念を調べるために「変数」とググると、booleanだのdoubleだのfloatだのいろんな種類が出てきて混乱するのは初心者あるあるだろう
他言語ではいろんな種類がある変数も、Emueraで使われるのは2つ、str(string)型とint(integer)型だけ

str型(string型、文字列型) 変数の中身が文字の変数 数字を含めあらゆるデータを格納できる
int型(数値型) 変数の中身が数字の変数 数字しか入れられないが、計算に強い

文字を入れるものと数字を入れるもの、この2つしか概念が無いのでEmueraを使う場合はひとまず他の変数は忘れよう
はじめからEmueraで使用可能な変数にも数値型と文字列型があるものの、変数の名前にSTRやSが付いてるものは文字列型という雰囲気がある。「CSTR」「LOCALS」「ARGS」「GLOBALS」などは文字列型である

eraをプレイしていても馴染み深い○○日目とか所持金○○圓とかは数値型変数が使われている
そして「あなた」含めてキャラクターの名前には文字列型が使われている

後者は使われてるのはNAMEやCALLNAMEといった変数 変数名の通りキャラ名と呼び名(略称)
ITEMNAME(道具の名前)やTRAINNAME(コマンドの名前)などの変数もあるが、ERBで参照することはあっても代入することはないので、最初は覚えなくても大丈夫 のはず

CFLAG、キャラクタ変数、口上で使える変数について

多くの場面でCFLAG:XXと省略されて書かれてるのでFLAG:XXなどと同じに見えるが、キャラクタ変数という二次元配列変数である
どの変数がキャラクタ変数なのかはEmueraWikiの変数表に書かれている
Emuera Wiki - 定数・変数 - 暫定的な仕様表
https://ja.osdn.net/projects/emuera/wiki/exvar#h4-...

FLAG等の一次元配列ならFLAG:XXは横一列に並んだ箱、CFLAG等の二次元配列ならさらに縦にも並べた箱、となる
「CFLAG:3:2」だったら3列目の前から2番目を指定してることになる(正確には0から数えるので4列目の前から3番目)
これがCFLAG:2と省略されている場合は「CFLAG:TARGET:2」と自動で補完されて処理される
TARGET(調教対象)の処理が多くなりがちなeraにとってはコードを書きやすくする仕様といえる

そして中でもキャラクタ変数は、上記「CFLAG:3:2」の3の部分がキャラ(いわゆる奴隷)に対応している
つまり「3人目の奴隷の2番目のステータス」となる
もちろんのことCFLAG:3:XXを弄ってもCFLAG:1:XX(1番目のキャラのステータス)には影響しない
これによって口上で独自のイベントを作る場合等に、他のキャラを侵害しないものが作れる

ただしCFLAGを口上で使えるのは、eraTWのように「CFLAGの1000〜1999は口上で自由に使っていいよ」と明示されてるバリアントのみ
それが明示されていないバリアントで、口上で勝手にCFLAGを書き換えると、本体の動作に支障をきたす場合がある。注意しよう

では次に「口上で使えるCFLAGが無いんですけど!」と「CFLAGはバリアントで使ってるから口上で使われると困るんですけど!」を、口上作者とバリアント作者の両方の視点から説明する

これを解決するのが「変数定義」と「ERHファイル」
Emuera Wiki - ユーザー定義の変数
https://ja.osdn.net/projects/emuera/wiki/UserVars
Emuera Wiki - ヘッダーファイル(ERH)
https://ja.osdn.net/projects/emuera/wiki/ERH

ひとつの関数内で完結して、かつ進行状況がセーブされなくてもいい単発のイベントを口上で作りたい場合、関数名の下にDIMを使って変数を作ると便利
たとえば「今日はクリスマスです」的なシチュで分岐作るときに「CHRISTMAS」という変数を作ったり
@XXXX;口上用の関数
#DIM DYNAMIC CHRISTMAS

「ひとつの関数じゃ足りない 他の関数を跨いだもっと大規模なイベントを作りたい」という時に使うのはERHファイル
こちらを使うと、どの関数でも使えてセーブもされる変数を作ることができる
たとえば「特定のコマンドを実行した回数」を記録して、「こういうコマンドが好きなんですね」と言わせるような分岐に使える

以下、キャラナンバーが3のキャラの口上で使う変数をERHファイルで定義する場合の例文を挙げる
#DIM SAVEDATA KOJOFLAG3, 10
上記の例文は「KOJOFLAG3」という名前のセーブされる変数を、0〜9まで使えるように定義したものである
拡張子がERHのファイルを用意してこの1行を追加するだけで変数の定義は完了となる
このように口上側で使えるフラグが事前に用意されてるバリアントもあるが、無い場合は自分で用意するのも口上を作る上でひとつのテクニックといえる

バリアント作者が口上用にフラグを用意しておきたい場合も、ERHを使用する。口上で自由に使えるキャラクタ変数を定義するだけ
たとえばeratohoЯeverseなら口上用にKFLAGという変数が用意されてたりする
ERHファイル内に
#DIM SAVEDATA CHARADATA KOJOFLAG, 100
と書いたものを作って、「KOJOFLAGの0〜99は口上で自由に使ってね」とreadmeあたりに書いておけば解決
上記の例文はキャラクタ変数となるため、単一のキャラに複数の口上があるケースでない限りは競合せずに変数を使える

CHARADATAを使ってキャラクタ変数を作るときは、SAVEDATAを併記しないとセーブされないキャラ変数になるので注意。ほとんどの口上はセーブされる変数を望んでいるはず

IF〜ENDIF、SELECTCASE〜ENDSELECT、そしてインデントについて

eraでは分岐を作る際、最初に覚えるのがIFとENDIFだと思われる
これは必ず一組で使わないとエラーになる。応用のSELECTCASE〜ENDSELECTも同様
IFをひとつ使ったら、ENDIFもひとつ必要になる IFを5個使えば当然5個のENDIFが必要
「ソースコードを書く上でわざわざ使った数を数えてられないよ!」という意見はごもっともである。それを解決するのがインデントと呼ばれる行揃え

ほとんどのエディタではTabキーを押せば半角スペース4個分くらい空白を入れてくれる
これらはソースコードの動作には一切影響しない
「何個使ったっけ?」と曖昧になる前に、一対のIFとENDIFをインデントで揃えておくと分かりやすいのである
IF〜ENDIFと同じくらい頻繁に使われているSELECTCASE〜ENDSELECTは、SELECTCASE〜CASE〜ENDSELECTと三位一体の書き方になる
IF文とSELECTCASE文のインデントがどうなるか実際に見てみよう この例文ではFLAG:0を用いる
IF FLAG:0 == 0
    PRINTW FLAG:0の中身は0です
ELSEIF FLAG:0 == 1
    PRINTW FLAG:0の中身は1です
ELSE
    PRINTW FLAG:0の中身は0でも1でもありません
ENDIF

SELECTCASE FLAG:0
    CASE 0
        PRINTW FLAG:0の中身は0です
    CASE 1
        PRINTW FLAG:0の中身は1です
    CASEELSE
        PRINTW FLAG:0の中身は0でも1でもありません
ENDSELECT
この通り、IF文とSELECTCASE文では微妙にインデントが違うのである
この微妙な違いは初心者にはかなり難解だと思われる
なので口上テンプレートを用いない、用いても独自の分岐を組み込んでみる、といった場合は、最初はIF〜ENDIFで統一するのが混乱を避けられる。口上に限らずバリアント側でも同様

基本的にSELECTCASEで出来ることは全てIFでも出来るため、慣れないうちは無理にSELECTCASEを使う必要はない
インデントを使うのもSELECTCASEを使うのも「ソースコードを見やすくするため」であって、最初から見栄えまで良くしようというのは初心者には難易度が高い。エラーと格闘しながら覚えていこう

コードを書くときは上から1行ずつ書くのではなく、関数や分岐などの構造を先に書いておくといい
中身のPRINTWとかを書く前にIFとELSEIFとENDIFを先に書いておけば閉じ忘れも無くなる

IFとSELECTCASEに関する参考資料
システム改造Q&A - IF・ELSEIFのかたまりはSELECTCASE文に出来るかも
https://seesaawiki.jp/eraseries/d/%a5%b7%a5%b9%a5%...

関数とCALLについて

ERBファイルの中には「@XXX」と書かれた、アットマークから始まる行がある

獏公式の「関数について」の項目が分かりやすい
eramakerのera basic書式
https://cbaku2.sakura.ne.jp/b/erakanon/eramaerb.ht...

プログラムを最初から最後まで続けて書くとわかりづらいものです。
部分部分に切り分けてわかりやすくするためには、「関数」を使います。

関数はERBファイルであればどこに作ってもいい。Emuera起動時点でディレクトリ内の全てのERBファイルが読み込まれるので、ディレクトリ(フォルダ)の構造も関係無い
今のほとんどのバリアントでは分かりやすくフォルダ分けがされている。この通り、フォルダの下にあるERBファイルも読み込んでくれる
関数は実際の処理でCALLされて使われるもの。ゲーム開始時の関数は@SYSTEM_TITLEで、ここからゲームが広がっていく
ファイル名は全く関係無く、ERBファイルの中の関数単位で読み込まれる
フォルダの中にあるERBファイル、さらにERBファイルの中にある関数、と、ERBファイルそのものもフォルダと似たようなものと思えば分かりやすい

そしてその関数を呼び出すのがCALL命令

PRINTFORMW これは口上です
この書き方は「これは口上です」という文を「画面に表示する」、PRINT命令を使った行となる

CALL KANSUU

@KANSUU
PRINTFORMW 関数が呼ばれました
この書き方は「@KANSUU」という関数を「呼び出す」処理をした後、「関数が呼ばれました」という文を「画面に表示する」処理

このように、「画面に表示する」「呼び出す」といった動作を行うものが「命令」と呼ばれるコードである
PRINTFORMWもCALLも命令なので、その後に続くコードに応じて動いてるということだ
この命令という概念が大事。これが分かると、上で説明したIF〜〜やSELECTCASE〜〜も命令だったんだなぁと気づく
変数、関数、命令、eraを作る上で重要な概念が3つ。これを理解すると出来ることが大幅に増える

次は関数の作り方を説明する
「CALLで関数に移動するのは便利そう!」「ところで関数ってどうやって作るの?難しいの?」いいえ、まったく難しくありません

ERBファイル内に@〜〜と書けば関数の出来上がり 本当にこれだけ

上記の例文だと
@KANSUU
この一行だけで関数が作られてるのである。難しいことは一切無く、他の関数と被らない名前を付けて、CALLで呼べばもうマスターしたも同然
先述の通り関数とはフォルダの中のファイルと同等なものなので、他の関数の途中に関数を挟むのは間違った書き方だから注意
@〜〜の関数が一区切りついてるのを確認してから作ろう
もちろん「他人の作ったERBファイルをいじるのは不安!」という時には、自分でERBファイルを作ってそこに関数を作ってもいい

ここまでで関数の概念と作り方について説明した これで十分CALLの実践はできるが、いくつかの留意事項を挙げておこう
ひとつは「CALLを使って別の関数が呼ばれたあと、元のCALLの場所まで戻ってくる」ということ

PRINTFORMW 家を出て羽田空港につきました
CALL USA
PRINTFORMW 羽田空港から家に戻りました

@USA
PRINTFORMW 国際便でアメリカ旅行して戻ってきました

処理の流れを旅行者にたとえるとこういう動作をする
もうひとつは、関数名には日本語も使えるということ
ただしこちらは「こっちのほうが見やすいかな」程度のものだから、無理に日本語で使う必要もない

CALL 関数

@関数
PRINTFORMW 関数が呼ばれました

上記の@KANSUUを使った例文を日本語に置き換えただけ。これで問題なく同じ動作をする

最後に、この解説ではあえてCALLだけ説明したが、同じく関数を呼ぶ命令ではJUMPやCALLFORM、TRYCCALLFORMなど上位モンスターみたいなやつらがいる。これらは最初は覚える必要は無いので「こういう処理を作りたい」と閃いたときに調べてみよう

変数と代入、演算について


※以下「演算」という言葉が聞き慣れない人は「計算」と同義なのでその解釈でOK

変数の種類については説明した。今回はこの変数の中身を変える様々な方法を解説したいと思う
まず前提として、数値型の変数には数値、文字列型の変数には文字しか代入できない点に注意
代入と言われる、変数の中に特定の値を入れる処理には数値型文字列型共に「=」を使う

@TEST
#DIM INT

INT = 123
STR = ABC

PRINTFORMW {INT} %STR%

#DIMの使い方は当ページで説明した通り。TEST関数を呼び出すと「123 ABC」と表示されるはず
変数INTに123を代入して、変数STRにはABCと代入してるからである。代入の部分を書き換えればその通りに表示される文も変わる

ここでもうひとつ説明できるのが、PRINTFORMWで変数の中身を表示する方法
数値型変数は{}で囲むことで、文字列型変数は%%で囲むことで中身を表示できる
日数や所持金を表示する場合に
PRINTFORML 主人:%CALLNAME:MASTER% {DAY}日目 所持金:{MONEY}円
と書けば必要な情報は表示されることになる PRINTFORMLというのはクリック待ちをしない場合

また、上記の123やABCのように指定の値を入れる際に演算子を使うことができる
演算子というのは、算数や数学における計算記号。「+」「-」掛け算は「*」割り算は「/」など

@TEST
#DIM INT
#DIM PLUS

PLUS = 45
INT = 123+PLUS

PRINTFORMW {INT}

上記の例文で表示されるのは168となる。123+45の中身を表示している

@TEST
#DIM INT
#DIM PLUS

PLUS = 45
INT = 123

PRINTFORMW {INT+PLUS}

こういう書き方もできる。同じく結果は168
処理は上の行から行われるから、先にPLUS変数に代入するのが大事

基本は前述した「+」「-」「*」「/」この4つの演算子。単純だが、これらはera開発でずっと付き合うことになるのでマスターしたい
それ以外の演算子については次項から説明する

比較演算子とtrue、falseについて

プログラミングでは古くからtrue、falseという概念がある。「変数の種類」の項で触れたbooleanがそれにあたる
trueかfalseかは変数に入るものだが、erabasicにはこれも同項の通りint型とstr型しかない
これをEmueraでは、数値型変数の中身が0の場合はfalse、それ以外は全てtrueの扱いになっている

これを踏まえて比較演算子というものを説明しよう
主にIFで使われる。以下のコードは、eraであればどこでも使われているメジャーな例文

IF CFLAG:0 >= 1
  PRINTFORMW CFLAG:TARGET:0は1以上です
ELSE
  PRINTFORMW CFLAG:TARGET:0は0以下です
ENDIF

比較演算子は、IFのあとに変数、演算子、また別の変数や数値の組み合わせで使われている
これはCFLAG:0が1以上だった場合に上の分岐を表示して、それ以外なら下の分岐を表示するという処理になる
英語のIF及びELSEの意味と同じと言えばイメージしやすいと思われる

獏公式の「条件判断する」の項に基本的なことが載っている
eramakerのera basic書式
http://cbaku.com/b/erakanon/eramaerb.html

IFについてイマイチよく分からないなって方はこちらも読んでみるといいかも
タイトル実践編 - IF
https://seesaawiki.jp/eraseries/d/%a5%bf%a5%a4%a5%...

IFのあとに続いた条件式が満たされている場合にIF下の処理が実行されるのは前述の通り

そして使える比較演算子は以下の通り
X < Y , XがY未満の場合
X > Y , YがX未満の場合
X >= Y , XがY以上の場合
X <= Y , YがX以上の場合
X == Y , XとYが等しい場合
X != Y , XとYが等しくない場合

>と>=は少し違うので注意。両方が同じ値だった場合に違う結果になる
=については上で話した代入の処理とはまったく別物
上の6つの比較演算子は、基本的に2つの値を比べるものなので、ひとつの条件で原則1個しか使えない。それ以外の、比較しない演算子は使える

IF X+Y >= 10
  PRINTFORMW {X}+{Y}は10以上です
ELSE
  PRINTFORMW {X}+{Y}は10未満です
ENDIF
このように、比較演算子とは別に前項で説明した演算子が使える

このIFでの条件式は複数設定することもできる その場合は&&、||といったまた別の種類の演算子が出てくる これは次項で説明する

「で、結局冒頭で話したtrueとfalseって何だったの?」と思う方もいるだろう
IFの後に条件を満たしている状態がtrue(1)、満たしてない場合がfalse(0)なのである
なので極端な書き方をすれば
IF 1
  PRINTFORMW trueです
ELSE
  PRINTFORMW falseです
ENDIF
こういうことになる

もちろんのことながら1はtrueで常にIFの条件を満たしているので、ELSE下の「falseです」は絶対に表示されない
0(false)を条件式にした場合も同様
IF 0
  PRINTFORMW falseです
ELSE
  PRINTFORMW trueです
ENDIF
ELSE下は絶対に(ry

冒頭で話したとおり0だけfalse、それ以外は(マイナスの値だろうが)すべてtrue扱いなので、「IF使ってるのに比較演算子が無いよ!」という場合はこの仕組みを使っている

IF MONEY
  PRINTFORMW お金を持っています 所持金は{MONEY}円です
ELSE
  PRINTFORMW 所持金は0円です
ENDIF

MONEY変数みたいに大きな値を取る変数ではあまり使われないが、比較演算子を省略したときの意味としてはこうなる
フラグが立っているかどうか、みたいな単純な分岐を書く時に便利

ひとつのIF分岐に複数の条件を指定する方法

比較演算子は一つの条件式に一つまで、「+」や「-」などの算術演算子は制限無しと説明した
今回説明するのはこれらとはまた違う、論理演算子と呼ばれるもの

基本的には以下の3つ
条件式1 && 条件式2 , 条件式1と2を両方満たす場合に分岐を実行(true)
条件式1 || 条件式2 , 条件式1か2、どちらかを満たす場合に分岐を実行
!条件式 , 条件式が満たされていた場合にfalseを、満たしてないとtrueになる

これらは条件式の数をそのまま増やすため、上述の「比較演算子は一つの条件式につき一つまで」のルールも、条件式1と2で適用される
&&と||の演算子を使えば条件式はいくらでも増やすことができる

IF CFLAG:0 == 0 && FLAG:0 == 0 && STR:0 == ""
  PRINTFORMW CFLAG:0とFLAG:0とSTR:0には何も代入されていません
ENDIF

これは&&(AND,論理積)を使った式 条件が全て満たされている場合に分岐
このように条件式を3つ以上設定したり、数値型の条件と文字列型の条件を一緒に使えたりする

IF CFLAG:0 != 0 || FLAG:0 != 0 || STR:0 != ""
  PRINTFORMW CFLAG:0とFLAG:0とSTR:0のどれかに値が代入されています
ENDIF

こっちの式は||(OR,論理和)を使った式 どれかひとつでも満たされている場合に分岐

見ての通り&&は条件が厳しいので、||のほうが分岐を通りやすい
それは言い換えると、意図していない分岐を実行するコードになることも多々ある
たとえば
IF (CFLAG:0 == 0 || (FLAG:0 == 0 && STR:0 == "") || TEQUIP:0 == 0) && (CSTR:0 == "" || TFLAG:0 == 0)
  PRINTFORMW ???
ENDIF
こうなるともはや書いている側も読んでいる側も、どういう処理を実行するのか非常に難解となる

一つのIF分岐の中で&&と||を両方使うこともできる。ただし使いすぎると可読性が著しく下がるため、おすすめはしない
特に初心者のうちは情報を増やしすぎるとどこを間違えてるのかすら判別できなくなる まずは条件式3つくらいを上限にしてやってみよう
条件式3つで&&と||を混在させた例を書くと
IF (CFLAG:0 == 0 || FLAG:0 == 0) && STR:0 == ""
  PRINTFORMW CFLAG:0とFLAG:0のどちらかは0で、かつSTR:0は空文字列です
ENDIF

||を使ったOR分岐は基本的に括弧でまとめることになる。掛け算や割り算と同じく計算の順序を守るためである

文字列変数の演算について

これまでは数値型変数の演算について説明していた 今日は文字列型変数の演算について説明しよう
まず共通のこととして、代入は数値型と同じ「=」を使う
ただし、この代入の書式が少々曲者で、いくつかのルールがある

@TEST
#DIM DYNAMIC INT

INT = 1
STR = AAA
PRINTFORMW INTは{INT}です STRは%STR%です
これの結果についてはここまで読んだ人ならある程度予測が付くだろう
変数INT及びSTRの中身を表示する
では次の例文ならどうだろう

@TEST
#DIM DYNAMIC INT, 2

INT:0 = 1
INT:1 = INT:0

STR:0 = AAA
STR:1 = STR:0

PRINTFORMW INT:1は{INT:1}です STR:1は%STR:1%です
「配列」のおさらいも兼ねている INT:0とINT:1は別の変数なので別の値を入れられるし、INT:0の中身を上記のようにINT:1にコピー(代入)もできる
「結果はさっきのと同じじゃないの?」と思うかもしれないけど、違う

INTは数値型変数なので、INT:0を変数と自動で解釈してINT:1にも1が入れられる
ただし文字列型の代入は変数と解釈してくれないので、STR:1の中身は「AAA」ではなく「STR:0」という文字列がそのまま代入されている

「変数の中身を参照したいんだよ!」という場合に使える記法はいくつかある
まずはPRINTFORMW系と同じく「%%」で括って代入すること
上記の例文を
STR:1 = STR:0
↓
STR:1 = %STR:0%
に変更してみると、STR:0が変数として解釈され、STR:1にはAAAが代入される
この代入は変数と非変数が混在していても動く 数値型も同様

@TEST
#DIM DYNAMIC INT, 2

INT:0 = 1
INT:1 = INT:0+3

STR:0 = AAA
STR:1 = BBB%STR:0%CCC

PRINTFORMW INT:1は{INT:1}です STR:1は%STR:1%です
こう書いた場合はINT:1には1+3の「4」が、STR:1には「BBBAAACCC」という文字が代入される

文字列型の代入にはもうひとつ方法がある 「'=」を用いる記述
STR:0 = AAA
STR:1 '= STR:0

PRINTFORMW STR:1は%STR:1%です
この記述なら%%で括らなくても変数と解釈してもらえるので、STR:1の中身はAAAになる

はっきり言って、似てるのに違う2つの記法があると混乱は必至。どちらを使うかを最初に決めておいて、片方は一旦忘れるくらいでいいと思う
「『'=』を使って上のBBBAAACCCみたいにやるにはどう書くの?」という質問もあると思われる
その場合は、
STR:0 = AAA
STR:1 '= @"BBB%STR:0%CCC"

PRINTFORMW STR:1は%STR:1%です
と書く @"〜〜"で括った文章はPRINTFORM系と同じく処理される
アットマークが「これから変数を使いますよ!」と予めera側に教えておくためのものなので、アットマークを忘れて
STR:0 = AAA
STR:1 '= "BBB%STR:0%CCC"

PRINTFORMW STR:1は%STR:1%です
と書くと、中身は「BBB%STR:0%CCC」になってしまう。STR:0が展開されない

少し話は飛躍して、「文字列型変数で他の演算子は使えるの?」について説明をする
数値型変数で使えた一部の演算子が使える
まず6種の比較演算子、あれらは全て使える

「==」と「!=」については分かりやすい。双方が同じかそうじゃないかの比較
@TEST
STR = AAA

IF STR == "AAA"
  PRINTFORMW STRはAAAです
ELSEIF STR != "AAA"
  PRINTFORMW STRはAAAではありません
ENDIF
比較演算子で、変数でない値を使うにはやはり"〜〜"で囲む必要がある

@TEST
STR:0 = AAA
STR:1 = AAA

IF STR:0 == STR:1
  PRINTFORMW STR:0は%STR:1%です
ELSEIF STR:0 != STR:1
  PRINTFORMW STR:0は%STR:1%ではありません
ENDIF
ただし変数同士の比較なら"〜〜"は必要無い

文字列型の演算で、比較演算子以外に何が使えるのか見てみよう
使えるのは「+」と「*」の演算子。足し算と掛け算

掛け算についてはここに書いてある通り
Emuera Wiki - 演算
https://ja.osdn.net/projects/emuera/wiki/exop#h4-....
    STR:0 = % "あ" * 10 %
    PRINTFORML STR:0 = "%STR:0%"
    WAIT
 ;結果
 STR:0 = "ああああああああああ"
※Emuera wikiからの引用

STR:0に「あ」を10倍、つまり「あ」10個分代入している

足し算について
STR:0 = AAA
STR:1 = BBB
STR:2 = %STR:0+STR:1%

PRINTFORMW STR:2は%STR:2%です
こう書くとSTR:0とSTR:1が結合されて「AAABBB」になる
当項の解説を読んだ人なら
STR:2 = %STR:0%%STR:1%
で良いんじゃないの?と思うかもしれない まったくその通りです

では足し算の演算子を活用できるのはどういう場面か、それは既存の文字列変数に加筆するときである
STR = AAA
STR += "BBB"
STR += "CCC"

PRINTFORMW STRは%STR%です
これはSTRにAAAが代入され、その後にBBBとCCCが加算演算子によって加筆され、最終的にAAABBBCCCという一文になっている
ここの加筆は"〜〜"で括るのが原則なので気をつけよう
これなら最初からAAABBBCCCを代入すればいいじゃん、それもそのとおりでございます

しかしこれがIFを用いて条件下で変わるものならどうだろう
STR = 今日は

IF RAND:2
  STR += "カレー"
ELSE
  STR += "オムライス"
ENDIF

STR += "が食べたい"

PRINTFORMW %STR%
このように、条件下で文字列変数の内容を変えたい場合に使える
口上や地の文を書くにもPRINT系の組み合わせで事足りるものではある ただしさらに難しい命令を使うには、この文字列変数の加算演算子が必須になってくる。HTML_PRINTなんかは特に

この項では文字列型変数の演算について説明した。使う演算子によって"〜〜"の有無が変わってくるので頑張って覚えるか、できるだけ記述を統一しよう

PRINT命令の種類

eraはテキストゲームなので、そのテキストを表示するためのPRINT系命令はゲームの中核である
極論言うとPRINTFORMLとPRINTFORMWさえあれば事足りるものではあるけど、それ以外に何があるのか、何が出来るのか見ていこう

参考リンク
タイトル実践編 - PRINTFORMLって?
https://seesaawiki.jp/eraseries/d/%a5%bf%a5%a4%a5%...
Emuera Wiki - 命令 - PRINT系
https://ja.osdn.net/projects/emuera/wiki/excom#h5-...

PRINT(L|W)とPRINTFORM(L|W)が今では最も見かけるPRINTだと思う
PRINT(L|W)は指定の文章をそのまま表示するのに対して、PRINTFORM(L|W)は変数や式中関数を展開して表示する
Lを付けると改行、Wを付けると改行してウェイト(入力待ち)、どっちも付けないと改行しない
PRINTL 改行して表示します
PRINTW 改行してウェイトします

PRINT 改行しません
PRINTL が上の行から続けて表示、改行します

変数を展開するかしないかの点は、文字列型変数の代入で説明したのと同じ
STR = AAA

PRINTW STRの中身は%STR%です
PRINTFORMW STRの中身は%STR%です

どっちもコード上では同じだが、STRの中身が正常に表示されるのは後者だけで、実際の表示は
STRの中身は%STR%です
STRの中身はAAAです
となる

前者が文字列変数でいうところの"〜〜"(ダブルクォーテーションだけの括り)、後者が@"〜〜"(ダブルクォーテーションのアットマーク付き)の処理と同等

「それじゃ機能がたくさんあるFORMのほうだけ使えばいいんだね!」となるわけだけど、あながち間違ってはいない
使い分けるのもそれはそれでいいし、統一するのもいい。人による

「PRINTFORMの方で%や{を使うと変数扱いされてエラーになる!」そういうときはエスケープ文字を使う
システム上、FORM内で変数を判別するための文字がいくつかあって、それらを文字として使いたい場合はシステム側に「これはただの文字ですよ」と教える必要がある

PRINTFORMW パーセントを表示します \%
PRINTFORMW 中括弧を表示します \{
このように、キーボード上ではスラッシュの右にある「\」を使う
BackSpaceの左にある¥マークも同義として使われる
eraに限らずプログラムのあらゆる場面でこのエスケープ文字は使われる。覚えておいて損はない

上記EmueraWikiにはいくつかPRINT系命令の項がある 項目分けされてる通り、それぞれ機能が違う
  • PRINTSINGLE系
    • 画面端で折り返さないPRINT 万が一の文字列超過で表示を崩さないために使うけど、画面端に飛び出てる時点で表示が崩れてるので画面サイズを見直したほうが良いと思われる
  • PRINTC系
    • コマンドや選択肢を一定間隔で揃えたい几帳面な製作者には重要
    • コンフィグで指定した数だけ表示したら自動で改行してくれる ただしボタンじゃない文章は自動改行しない
  • PRINTDATA系
    • 複数の文章からどれか1行をランダムで表示する
    • RAND:XXを使う乱数分岐を幾分スマートにできるものの、変数の代入や計算、他の命令を割り込ませることはできないので、本当に一言表示するだけの場面で使う(口上など)
  • PRINTBUTTON系
    • eraでは[]で括った数字が自動でマウスクリックに対応したボタンになる
    • [1]だったら1のボタンといったように、本来では数字しか指定できないボタンを、文字列型を返すようにしたりできる
  • PRINTPLAIN系
    • 上記のボタン化の仕様は一行全てに適用される。そのためPRINT(LでもWでもない)で複数の文を一行で表示すると、勝手にボタンとしてまとめられる
    • このボタン化を防ぐためにはPRINTPLAINを使う

他にPRINTを冠する命令ではDEBUGPRINTやHTML_PRINTがあるが、全くの別物なので当項は割愛する

デバッグの方法

以下画像付きなので折りたたみ

ランダム表示する口上の作り方

IFやSELECTCASEを理解できたなら、きっとIF RAND:XXやSELECTCASE RAND:XXといった分岐は既に使っている人も多いだろう
この「RAND:XX」は乱数と呼ばれる 書き方は変数と同じだが、中身は常にランダムに変わっている
RAND:3なら、3つの候補からランダムで1つ選出する
「1〜3がランダムで選ばれるんだね!」と思うかもしれないが、ほとんどのプログラミング言語は0から数えるため、0〜2の3種類から選ばれる

乱数を使うと、それまで同じ条件下では同じ結果しか出なかったものを、別の結果にする可能性を与えることができる
口上で同じコマンドを選んでも違うセリフが表示されるのは、この乱数を使っているものがほとんどである
では実際に乱数を使って口上を書くとして、例文は以下
;IFを使う場合
IF RAND:3 == 0
  PRINTW 「今日はカレーが食べたい」
ELSEIF RAND:2 == 0
  PRINTW 「今日はオムライスが食べたい」
ELSE
  PRINTW 「今日はパスタが食べたい」
ENDIF
これは各分岐を等確率で表示する正しい構文 しかし何か違和感に気づいただろうか
最初のIFがRAND:3なのに2番目のIFはRAND:2になっている
「こんなんおかしいぜ きっとこう書くのが正しいんだ」と
IF RAND:3 == 0
  PRINTW 「今日はカレーが食べたい」
ELSEIF RAND:3 == 1
  PRINTW 「今日はオムライスが食べたい」
ELSE
  PRINTW 「今日はパスタが食べたい」
ENDIF
直したい気持ちがあるだろう しかしこれでは等確率じゃないのである
なぜなら乱数は「常に」変わっていて、最初のIF RAND:3と2番目のIF RAND:3が同じ結果になるとは限らないからだ
最初の例文が33%:33%:33%の確率だったのに対して、2番目の例文は33%:22%:44%の確率になっている つまり表示される口上が偏ってしまう
3つの乱数分岐なら、1番目の分岐は33%(RAND:3)で表示、残りの分岐は2つなので、2番目の分岐は50%(RAND:2)で表示、それ以外ならELSEの分岐を表示、で等確率になる

これはちょっとした論理クイズのようなものなので、知っておくと便利だが、はっきり言ってプログラムで書くには実用的ではない
なので乱数分岐に関してはSELECTCASEを使うことをおすすめする
SELECTCASE RAND:3
  CASE 0
    PRINTW 「今日はカレーが食べたい」
  CASE 1
    PRINTW 「今日はオムライスが食べたい」
  CASE 2
    PRINTW 「今日はパスタが食べたい」
ENDSELECT
これなら最初のSELECTCASEの時点で分岐するための乱数は固定されるので、RAND:3が返す候補(0〜2)をCASEで指定すれば等確率になる

この乱数分岐に限ってはIFとSELECTCASE以外にも使えるものがある
PRINTDATAという命令で、複数の候補から等確率で1文を選んでくれるもの
PRINTDATAW
  DATA 「今日はカレーが食べたい」
  DATA 「今日はオムライスが食べたい」
  DATA 「今日はパスタが食べたい」
ENDDATA
上記の例文は、前述したIFとSELECTCASEの例文と同じ動作をする
SELECTCASEにしても分岐を追加する際には、RAND:Xを書き換えてCASEも増やしてと手間がかかるが、PRINTDATAを用いる場合はDATAから続く1行を追加するだけで済む
PRINTDATAW〜ENDDATAの間に
DATA 「今日はチャーハンが食べたい」
と追加するだけで、乱数分岐の候補を増やせるのである

この項では口上で乱数を使う場合の説明をしたが、乱数は計算処理に使ってランダム性を与えることもできるし、使い方はたくさんある これについてはまた加筆予定の別項で説明しよう

文字の色を変えてみよう

これまでの説明で文字を表示する方法、PRINT系は大方使えるようになったと思う
では昨今のバリアントでよく見る、文字に色を付けて華やかにする方法を説明しよう
一番簡単な方法は、命令「SETCOLOR」を使うこと
Emuera Wiki - 命令 - SETCOLOR
https://ja.osdn.net/projects/emuera/wiki/excom#h5-...

ここで書かれている通り、SETCOLORにはいくつか書き方がある
SETCOLOR 255, 0, 0
PRINTW これは赤い文字です
SETCOLOR 0x00FF00
PRINTW これは緑色の文字です
RGB形式と16進数方式の二通りの書き方がある
emueraでは「0x」から書くことで16進数での表記ができる。状況によっては16進数のほうがわかりやすく使いやすい。16進数って何?という人は別項で説明しよう

「数字だと色のイメージがしづらいよ〜」という人のために「SETCOLORBYNAME」という命令もある
使い方は以下の通り
SETCOLORBYNAME blue
PRINTW これは青い文字です
SETCOLORBYNAME yellow
PRINTW これは黄色い文字です
ここで指定できる色はEmueraで使用しているC#で定義されているものだけ
KnownColor 列挙型 (System.Drawing) - Microsoft Docs
https://docs.microsoft.com/ja-jp/dotnet/api/system...

はっきり言って上記マイクロソフトのページは分かりづらいので、こっちを見ると分かりやすい
WEB色見本 原色大辞典 - HTMLカラーコード
https://www.colordic.org/

cyanとかlimeとかpurpleとか名前で書いてあると「このSETCOLORはこの色になるんだなぁ」とイメージしやすいのでオススメ
ただしあくまで定義されてる色だけ指定できるのであって、オリジナルで付けた色名やスペルミスを指定するとエラーになる
COLOR_FROMNAMEという式中関数でその色名が存在しているのか確認できるので、不安なら一度通して確認してみよう
SIF COLOR_FROMNAME("yelow") == -1
  PRINTW 誤字ってます

これらはもちろん口上でも使えるし特定の1文を強調するのにも役に立つ
ただし、一度SETCOLORするとRESETCOLORするまでその色でPRINTされるということを忘れずに
口上でSETCOLORして「このキャラはこういうイメージカラーですよ」とするのも良いアイディアだけど、RESETCOLORを忘れるとゲーム全体の見た目が狂うため、IF〜ENDIFと同じくSETCOLORとRESETCOLORはセットで用いよう

文字色だけでなくフォントも変えることもできる
Emuera Wiki - 命令 - FONTBOLD・FONTITALIC・FONTREGULAR
https://ja.osdn.net/projects/emuera/wiki/excom#h5-...

FONTBOLDは太字に、FONTITALICは斜体に、FONTSTYLEで4を指定すれば打ち消し線、8なら下線
FONTSTYLEはビット数を用いてるので、そこが分からなければ今は手を出さないほうが無難
とりあえずFONTBOLDとFONTITALICをSETCOLORと同じ要領で使って、同じくFONTREGULARをRESETCOLORと同じ要領で使う、ということを覚えよう
こっちもFONTREGULARを忘れると表示が崩れるから忘れずに

ビット数について

画像が多いので折りたたみ

ビット演算に使える命令と式中関数について

主に4種類ある。「SETBIT」「CLEARBIT」「INVERTBIT」「GETBIT」
前述のビット数で、たとえば右から3番目のスイッチだけをオンにしたい場合は、変数に4を代入すればいい。2進数で0100
しかし代入した場合、その変数のビット数の記録は全て初期化されてしまう
なので既に使っている状態で右から3番目のスイッチをオンにしたい場合は、代入ではなく4を加算することになる
しかしこれでは既に3番目のスイッチが入ってる状態だと、重複のスイッチオンが起こってしまい、ビット数はめちゃくちゃになる
これを解決するのがSETBIT命令
;0番目のビットをオンにする
INT += 1
;2番目のビットをオンにする
INT += 4

;1番目のビットをオンにしたいが、オンオフの状態が分からない
SETBIT INT, 1
上記は右から2番目(0から数えて1)のオンオフが分からない状態で、なおかつ確実にオンにしたい場合に使われる
2を加算するのもいいけど、前述の通り既にオンになってると、9(2進数で1001)になってしまう
このSETBIT命令は、そのビットがオンになってるかどうかを判別して自動で加算してくれる命令なのだ
もちろん既にオンになってる場合は変数INTに変化は無い

CLEARBITは名前の通り、指定したビットを消す命令
;0,1,2番目のビットを入れる(0111=7)
INT = 7

;0番目のビットをオフにする
INT -= 1

;2番目のビットをオフにする
INT -= 4

;1番目のビットをオフにする これはCLEARBITを使ってみる
CLEARBIT INT, 1
最後のCLEARBITで2にあたるビットがオフになって2減算されるため、INTは0になる
これもオンオフの状態が分からない場面で確実にオフにしたい場合に使う 既にオフになっている場合は変化は無い

INVERTBITはこれを切り替えるための命令 つまり、スイッチの例えが分かりやすい


右から0、1、2のビットで、INVERTBIT INT, 0〜2を指定するとそれらのオンオフを切り替える
この命令は何も起こらないってことはなく、確実に指定したビットの数だけ加算もしくは減算される

そして最後にGETBIT。これは命令ではなく式中関数
;0番目と2番目のビットをオンにする(0101=5)
INT = 5

IF GETBIT(INT, 0)
  PRINTW 0番目のビットはオンです
ELSE
  PRINTW 0番目のビットはオフです
ENDIF

IF GETBIT(INT, 1)
  PRINTW 1番目のビットはオンです
ELSE
  PRINTW 1番目のビットはオフです
ENDIF

IF GETBIT(INT, 2)
  PRINTW 2番目のビットはオンです
ELSE
  PRINTW 2番目のビットはオフです
ENDIF
これは最初に代入したとおり0と2のビットをオンにしてる状態なので、結果は0=オン 1=オフ 2=オンとなる
今回の説明を参考に、上記の例文にSETBIT、CLEARBIT、INVERTBITを組み込んでみると面白いかもしれない
これを応用して、eraにおける汚れ(BIT)のセット(SET)、クリア(CLEAR)、取得(GET)を行う。反転(INVERT)はあまりしないけど、他の場面でビット演算を使うこともあるので覚えておいて損はない

無限ループの小ネタ

Emuera Ver1.823で実装されたAWAITという命令がある
あまりにループ回数が多い処理を作って、Emueraに「これもう無限ループみたいですね……」とダイアログボックスで注意されることがある



これが出るのは実際に無限ループが起きてる場合がほとんどだが、PCのスペックによっては重い処理は無限ループ扱いされる
ループ処理にAWAIT命令を入れることで、この誤動作を防ぐことができる
Emuera Wiki - 命令 - AWAIT関連
https://ja.osdn.net/projects/emuera/wiki/excom#h4-...

EmueraWikiの通り頻繁にAWAITが入ると目に見えて処理が遅くなるため、たとえばループ100回ごとにAWAITを入れる、全体の10%ごとにAWAITを入れるといった工夫をすると、AWAITを活かしつつ軽い処理を実現できる

文字コードの話

最近ではHTML規格の進化や文字コードの統一化も進んで見かける機会が減ったが、文字化けの現象は誰しも一度は経験してるはず
これの原因は文字コードというものにある

プログラムは0と1で作られているという有名な話の通り、今こうやってパソコンやスマホを介して読んでいる文章も、突き詰めれば0と1の組み合わせで出来ている
その0と1の組み合わせを文字に変換するために文字コードが使われる

日本で使われる主な文字コードはShift-JISとUnicode(UTF系含む)がある
前者のShift-JISはSJISとも略され、元々は日本語の扱いに秀でた文字コードとして作られた背景がある
しかしITの普及によってSJISでは対応していない各国特有の文字や記号を扱うために、Unicodeという文字コードが普及している

ではなぜこれらの文字コードの違いで文字化けが起こるのか、それは変換表が違うからである
前述の通りプログラム自体は0と1で作られているが、例えば同じ10101011でも文字コードによって対応してる文字が違う
SJISで書いたものをUnicodeとして開いたりすると文字化けが発生する 逆もまた然り

eraでもこれは起こりうる話だが、ありがたいことにEmueraはSJISファイルとUnicode系ファイルが混在していても動くハイテク仕様なのだ
ただし文字コードにもSJIS、Unicode以外にも様々な種類があり、これら全部を闇鍋にしても動く保証は全く無い
出来るだけファイルの文字コードは統一するのが望ましい 一括変換するフリーソフトもあるので活用しよう
前述の通り、Unicode系は記号の扱いに強い 特殊文字を用いてテキストを書きたい場合はUnicode系の文字コードを使おう


※今後も項目を増やしていく予定

Menu

メニュー







他OSで動かす方法



リンク

どなたでも編集できます