大域変数宣言static変数番号シーンシーン引数, シーン内static変数宣言, シーン内変数宣言,サブルーチン,
コマンドwrite, 代入, picture, layer, eraselayer, paint, erasepaint, cls, exit, wait, loadfile,文if, for, while, do, switch, choice, break, continue, jump, call, return, goto, ラベル式rand, rand, from, id, 演算子その他画像のレイヤ構造, 文字列
- 例:
この枠に囲まれた例は シナリオとして実行できます。
- 例:
この枠に囲まれた例は実行できません。 部分的な例や間違った例です。
- 例:
a = a + 1; // ここから先、行末までがコメントです // 先頭からコメントでも構いません a // 文字列を途中で分断しなければ、 // コメントは任意の位置に書くことができます = a + 1;
シナリオは大域変数宣言とシーンおよびサブルーチンの記述から成り立っています。 シナリオは一番最初に書かれたシーンから実行されます。
- 構文:
- [ 大域変数宣言 ] [ シーン [ シーンまたはサブルーチン ... ] ]
- 例:
int a = 3; // 大域変数の宣言 scene 最初のシーン () { // このシーンから実行される jump 最後のシーン(); } sub サブルーチンA () { // サブルーチン } scene 最後のシーン() { call サブルーチンA(); }
- 悪い例:
int a = 3; // 大域変数の宣言 sub サブルーチンA () { // エラー:サブルーチンの前に1つもシーンがないのはダメ } scene 最初のシーン () { } scene 最後のシーン() { }
シナリオの先頭で大域変数を宣言します。 大域変数は全てのシーンやサブルーチンで利用できます。
- 構文:
- int 変数名 [ = 式 ] [ , 変数名 [ = 式 ] ... ] ;
static [ static変数番号 ] int 変数名 [ = 式 ] ;
- 例:
int a = 3, b; // 複数まとめて宣言できます int c = a + 3; // 初期値には他の変数も参照できます static 10 int d; // 変数番号10でdを宣言 static 6 int e = 3; // 変数番号6でeを初期値3で宣言 static int f = 4; // 変数番号はなくてもよい
- 悪い例:
static 10 int a, b; // 変数番号を指定する場合は1度に1つしか宣言できない
変数番号
static変数(大域変数やシーン内static変数)は、 HPNV Senario Compilerにおける変数番号指定することができます。
mfstは0から順番に変数番号を使用していくので、 若い変数番号を使用するときはシナリオの先頭で定義してください。 ただし、大きい変数番号を使用すると 変数番号として利用できる数が減ってしまいます。
static変数が利用する最大の変数番号 + 最も数の多いシーン内変数の数の上限が 92個です。 (「最も数の多いシーン内変数の数」とは、例えば シーン内変数を10個利用しているシーンと、 シーン内変数を5個利用しているシーンがあるなら 「10個」ということです。10+5=15個ではありません)
シーンの最後には暗黙のexitがあり、シーンの最後まで実行されると シナリオはそこで終了します。
- 構文:
- scene シーン名( [ シーン引数 ] ) { [シーン内static変数宣言 ... ] [シーン内変数宣言 ... ] [ 文 ... ] }
- 例:
scene firstScene ( int a ) { write( "引数 a=", a ); } // ここまで来るとシナリオが終了します scene secondScene () { // 次のシーンが実行されたりはしません write( "ここには来ません" ); }
シーン引数
シーン引数は最大で3個です(いまのところ)。
- 構文:
- (何も書かない)
void
int 変数名 [, int 変数名 ... ]
- 例:
scene シーン1( int a, int b, int c ) { } scene シーン2() { } scene シーン3( void ) { }
- 悪い例:
scene シーン4( int a, b ) { // bの前に「int」が抜けています } scene シーン5( int a=3 ) { // シーン引数に初期値は書けません }
シーン内static変数宣言
大域変数と似ていますが、シーン内でしか参照できません。
- 構文:
- static [ static変数番号 ] int 変数名 [ = 式 ];
初期値の式はシナリオを実行開始直後に1回だけ実行されます。
大域変数との使い分けですが、 主人公の状態については大域変数を使い、 場面毎の状態(明りがついている/消えている、とか)はシーン内static変数を使うと 良いと思います。注意: シーン内static変数はシーンの初実行時ではなく、 シナリオの最初にまとめて初期化されます。 したがって、 シーン引数を使って初期化しようとすると、めちゃくちゃな値になります。
- 例:
static 10 int d; // 変数番号10でdを宣言 static int e = d; // 変数番号を指定せず、eをdの値で初期化
- 悪い例:
static int a, b; // 変数番号を指定する場合は1度に1つしか宣言できない
- 悪い例:
scene AAA ( int x ) { static book = x; // コンパイルはできますが // めちゃくちゃな値で初期化されます }
シーン内変数宣言
シーン内static変数と違い、 式がある場合は毎回初期化されます。 また、一度シーンを出ると変数の内容は壊れます。 C言語の自動変数(staticをつけないローカル変数)と同じです。
- 構文:
- int 変数名 [ = 式 ];
- 例:
int a, b = 10; int c = b;
サブルーチン名は、最初の1文字は英文字・漢字ひらがなで、 2文字目以降は英文字・漢字ひらがな・数字・_を利用できます。
- 例:
scene シーン ( ) { write("まずこれが表示され"); call サブ(); write("最後にこれが表示され終了"); } scene サブ () { write( "2番目にここが表示され" ); }
write
文字列や数値を表示します。 表示後、画面のタップ、またはボタンを押されるまで実行が止まります。
- 構文:
- write( 文字列 or 式 [ , 文字列 or 式 ... ] );
- 例:
scene aaa ( int a ) { write( "あいう", a ); // この行はすぐに表示されますが write( a * 34 ); // タップされるまでこの行は表示されません }
代入
変数に式の値を代入(演算)します。
- 構文:
- 変数 = 式 ;
変数 += 式;
変数 -= 式;
変数 *= 式;
変数 /= 式;
変数++;
変数--;
C言語と違い、左辺は値を持ちません。
- 例:
a = 3; b = 2 * ( a + 5 ) * rand( 3 ); a++; a += b * 2;
- 悪い例:
a = b = 2; // 左辺が値を持たないので続けられません if ( a-- ) { // これも同様で、使えません write( "aにbを代入した結果が0でない"); } --b; // 前置形式はありません
picture
文字列で示されたBMPファイルを、 式の方法で背景像を表示します。 160x120のBMPファイルを表示できます。 式の値により以下のエフェクトがかかります。
- 構文:
- picture( 文字列, 式 ) ;
picture( 文字列 ) ;
-1 表示しない 0 一瞬で表示 1〜5 エフェクトをかけて表示
- 例:
picture( "aaa.bmp", 5 ); picture( "bbb.bmp", a - b ); picture( "ccc.bmp" );
layer
整数はレイヤ番号を意味し、1または2が使えます。 文字列のBMPファイルを、座標( 式 1, 式 2 )に、エフェクト 式 3で表示します。 エフェクトの番号の意味はpictureと同じです。 なお、BMPファイルの紫色(R=255, G=0, B=255)の部分は透明になり 下の画像が透けて見えます。
- 構文:
- layer( 整数, 文字列, 式 1, 式 2, 式 3 ) ;
- 例:
for( a = 0; a < 100; a++ ) { layer( 1, "aaa.bmp", x, y, 0 ); layer( 2, "bbb.bmp", 100-x, y, 0 ); }
eraselayer
整数はレイヤ番号を意味し、1または2が使えます。 式で示すエフェクトを用いて、レイヤ画像を消去します。 エフェクトの番号の意味はpictureと同じです。
- 構文:
- eraselayer( 整数, 式 ) ;
- 例:
eraselayer( 1, 4 );
paint
式で示すエフェクトで 文字列(6ケタの16進数でRGB値を表現)で示す色を使い背景画像を塗り潰します。 エフェクトの番号の意味はpictureと同じです。
- 構文:
- paint( 文字列, 式 ) ;
- 例:
paint( "00FF00", 3 ); // エフェクト3で緑色に塗り潰します
erasepaint
式で示すエフェクトで背景画像を消去します。 エフェクトの番号の意味はpictureと同じです。
- 構文:
- erasepaint( 式 );
- 例:
erasepaint( 4 );
cls
文字の表示領域を消去します。
- 構文:
- cls();
exit
シナリオを終了します。シナリオファイル中にいくつ存在してもかまいません。 また、 シーンの最後には暗黙のexitが書かれているとして動作します。
- 構文:
- exit();
- 例:
scene aaa () { choice ( "どうしますか?" ) { case "終了する" exit(); // ここに来るとシナリオは終了します break; case "まだ続ける" break; } write("まだ続けます"); // シーンの最後では自動的にexit()されます } scene bbb () { // したがってこのシーンは実行されません write("でもここには来ません"); }
wait
タップまたはボタンの押下を待ちます。 rand関数と組み合わせて使うと、タップした位置を知ることができます。
- 構文:
- wait();
loadfile
他のシナリオで自動的に作成されたセーブデータを読み込みます。
- 構文:
- loadfile( 文字列 )
static変数は同じ番号に読み込まれるので、 大域変数宣言やシーン内static変数宣言で変数を宣言するとき、 static変数番号を用いて変数番号を指定すると良いでしょう。
ちなみに、セーブはできません。
- 例:
static 10 int age = 20; static 5 int money = 1000; scene 最初期シーン() { choice( "前作のシナリオのデータをロードしますか?" ) { case "ロードする": loadfile( "前作シナリオファイル名" ); break; case "ロードしない": break; } jump 開始シーン(); } scene 開始シーン() { write("あなたは...."); }
if
C言語のifと似ていますが、{}を省略することはできません。 C言語と同じで、 式が0以外のとき、直後のstatementを実行し、 式が0の時はelse以降のstatementを実行します。
- 構文:
- if ( 式 ) { 文 }
if ( 式 ) { 文 } else { 文 }
if ( 式 ) { 文 } else if ( 式 ) { 文 } ...
- 例:
if ( a == 3 ) { write( "aの値は", a, "です" ); } if ( a ) { write( "aは0以外の値です" ); }
- 悪い例:
if ( a == 4 ) write("あああ"); // {}は省略できません if ( write("いいい") ) { // 式ではありません write( "ううう" ); }
for
C言語のforと似ていますが、{}を省略することはできません。 C言語と同じで、 式は0のとき偽、0以外の時真となります。
- 構文:
- for( [コマンド [, ...]] ; 式 ; [コマンド [, ... ]] ) { 文 }
- 例:
scene aaa() { int a, b; for( a=0, b=2; b<10; b++ ) { // ","で区切ればコマンドを並べられます write( "a=", a, " b=", b ); // (Cと同じです) } for( ; a<10; a++ ) { // 不要ならコマンドを省略できます write( "a=", a, " b=", b ); } }
while
C言語のwhileと似ていますが、{}を省略できません。 C言語と同じで、 式は0のとき偽、0以外の時真となります。
- 構文:
- while( 式 ) { 文 }
- 例:
scene aaa () { int a = 5; while ( a ) { write("a=", a ); a--; }
do
C言語のdoと似ていますが、{}を省略できません。 C言語と同じで、 式は0のとき偽、0以外の時真となります。
- 構文:
- do { 文 } while( 式 );
- 例:
a = 10; do { a--; } while ( a > 0 );
switch
C言語のswitchと似ていますが、caseに値だけでなく式を書くことができます。
- 構文:
- switch( 式 ) {
case 式:
文
[ break; ]
...
default:
文
[ break; ] }
- 例:
switch( a ) { case b: write("aとbは等しいです"); break; case c+4: write("aはc+4と等しいです"); // Cと同じで、breakがないと、次のcaseも実行されます case rand(10): write( "aはc+4または10以下の乱数と等しいです" ); break; default: write("その他です"); }
choice
2択または3択の質問するウィンドウを開き、ユーザーの選択を求めます。 最初の文字列が、質問ウィンドウのタイトルです。 caseの文字列が選択肢で、この選択肢が選ばれると case以降に書いたstatementがbreakまで実行されます。 caseは2個または3個です。1個や4個以上はエラーになります。 構文や動作ははswitchと似ています。
- 構文:
- choice( 文字列 ) {
case 文字列:
statement [ break; ] case 文字列:
statement [ break; ] [case 文字列:
statement [ break; ] ] }
- 例:
choice ("AとBのどちらを取りますか?") { case "AとBの両方": a = 1; // breakが無ければ次のcaseも実行されます。 case "Bだけ": b = 1; break; case "どちらも取らない": jump 次のシーン(); }
break
while, for, do, switch, choiceの中で使用できます。 使用したブロックを抜けます。
- 例:
for( a=0; a<10; a++ ) { if ( a==4 ) { break; } }
continue
while, for, doの中で使用できます。次のループに移ります。
- 例:
while( a > 10 ) { if ( b < 0 ) { a++; continue; } }
jump
シーンまたはラベルにジャンプします シーンにジャンプするときは、 シーン引数の数が合っていないとエラーになります。
- 構文:
- jump シーン名( シーン引数 );
- 例:
scene aaa () { a = 3; jump bbb( a ); } scene bbb ( int x ) { write( "引数の値は", x ); }
- 悪い例:
scene aaa () { a = 3; jump bbb( ); // シーン引数の数が合っていません } scene bbb ( int x ) { write( "引数の値は", x ); }
call
サブルーチンコールします。
- 構文:
- call サブルーチン名() ;
()は、将来、サブルーチンに引数を作れるかもしれないので、 互換性の確保のためにつけてあります...
- 例:
scene A () { call 表示() ; } sub 表示 () { write("あああ"); return; }
return
サブルーチンから元に戻ります。 サブルーチンの最後には暗黙のreturnがあるので、 サブルーチンの最後のreturnは省略してもかまいません。
- 構文:
- return ;
- 例:
scene A() { call subA() ; call subB() ; } sub subA() { write("サブルーチンAです"); return; } sub subB() { write("サブルーチンBです"); } // 最後のreturnは省略しても構いません
goto
文字列のラベルにジャンプします。 ラベルを書けば、任意の場所にgotoできますが、 ループの中や他のシーンへのgotoは避けた方が良いでしょう (今のところスタックがないので動作はおかしくなりませんが、 変数が初期化されていないので値がヘンになります。 将来、スタックを使えるようになったら、暴走の原因になります)。
- 構文:
- goto ラベル名
ラベル
任意の場所にgotoするためのラベルです。
- 構文:
- :ラベル名
- 例:
scene aaa() { :もう一度 choice("どうする?") { case "まだやる": goto "もう一度"; case "もうやめる": exit(); } }
rand
0以上式以下の値となる乱数を返す関数です。
- 構文:
- rand( 式 )
- 例:
a = rand( 10 );
rect
wait時にタップした座標が(x1,y1)〜(x2,y2)の中なら1を返し、 それ以外では0を返す関数です。
- 構文:
- rect( x1, y1, x2, y2 )
- 例:
wait(); if ( rect( 10, 10, 100, 100 ) ) { write( "(10,10)-(100,100)をタップしました"); }
from
このシーンにjumpしてくる前のシーンのidを返す関数です。 シナリオ開始直後のシーン(どこからもjumpしてきていない)では-1を返します。 idと組み合わせて利用します。
- 構文:
- from()
id
シーンのidを返す関数です。idは非負の整数です。 from()と組み合わせて利用します。
- 構文:
- id(シーン名)
- 例:
scene aaa () { switch( from() ) { case -1: write("シナリオ開始直後です"); case id(bbb): write("bbbから来ました"); break; case id(ccc): write("cccから来ました"); break; default: write("どこから来たか解りません"); } }
演算子
演算子には、+ , - , * , / , < , <= , == , >= , > , ! , && , ||と、()があります。 演算子の結び付きの強さは、下の表のようになっています。
最も強い ( ) 符号の-, + ! *, / +, - <= , <, ==, >, >= && 最も弱い ||
- 例:
x = a + ( b - 3 ); y = a || 2 < b && b > 10;
画像レイヤ構造
画像のレイヤ構造は、一番上からレイヤ2、レイヤ1、背景となっています。
文字列
""でくくる。"自体は...表現できません。 (そういえば忘れてた)
- 例:
"abc" "あいう"