"ティラノスクリプト"のラベル・ジャンプ操作をStateGoで省力化する


# はじめに

本投稿は、[詳解「StateGoの"ティラノスクリプト"サンプル動作と変更事例」](https://qiita.com/tohmas/items/7b83a35b852f2c339970)の続きになります。

ティラノスクリプトを使う上で面倒で苦労する『ラベル・ジャンプ操作系命令』について、[StateGo](https://statego.programanic.com/index-j.html)で簡単に記述する方法を説明します。

本投稿の題目は以下の通りです。

- [ティラノスクリプトのラベル・ジャンプ操作系命令について](#%E3%83%86%E3%82%A3%E3%83%A9%E3%83%8E%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%AE%E3%83%A9%E3%83%99%E3%83%AB%E3%82%B8%E3%83%A3%E3%83%B3%E3%83%97%E6%93%8D%E4%BD%9C%E7%B3%BB%E5%91%BD%E4%BB%A4%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)
- [StateGo"ティラノスクリプト"サンプルによるラベル・ジャンプ操作系の命令について](#statego%E3%83%86%E3%82%A3%E3%83%A9%E3%83%8E%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%81%AB%E3%82%88%E3%82%8B%E3%83%A9%E3%83%99%E3%83%AB%E3%82%B8%E3%83%A3%E3%83%B3%E3%83%97%E6%93%8D%E4%BD%9C%E7%B3%BB%E3%81%AE%E5%91%BD%E4%BB%A4%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)
- [まとめ](#%E3%81%BE%E3%81%A8%E3%82%81)
- [変更事例](#%E5%A4%89%E6%9B%B4%E4%BA%8B%E4%BE%8B)
- [【資料１】StateGo"ティラノスクリプト"サンプルのラベル・ジャンプ操作系命令仕様](#%E8%B3%87%E6%96%99%EF%BC%91statego%E3%83%86%E3%82%A3%E3%83%A9%E3%83%8E%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%81%AE%E3%83%A9%E3%83%99%E3%83%AB%E3%82%B8%E3%83%A3%E3%83%B3%E3%83%97%E6%93%8D%E4%BD%9C%E7%B3%BB%E5%91%BD%E4%BB%A4%E4%BB%95%E6%A7%98)
- [【資料２】glinkの実装サンプル](#%E8%B3%87%E6%96%99%EF%BC%92glink%E3%81%AE%E5%AE%9F%E8%A3%85%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB)
- [【資料３】buttonの実装サンプル](#%E8%B3%87%E6%96%99%EF%BC%93button%E3%81%AE%E5%AE%9F%E8%A3%85%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB)


# ティラノスクリプトのラベル・ジャンプ操作系命令について

ノベルゲームにおける選択肢は必須の機能です。
そして、最も使用頻度が高い命令です。

ティラノスクリプトでは、選択肢に使用される命令を『ラベル・ジャンプ操作系命令』と呼んでいます。

以下は命令一覧になります。

### ティラノスクリプトのラベル・ジャンプ操作系命令一覧

|命令|内容|詳細|
|:---:|:---:|:---:|
|link|文字列を選択可へ＆クリック時ラベルへ遷移|https://tyrano.jp/tag/#link|
|glink|ボタン表示し選択可へ＆クリック時ラベルへ遷移|https://tyrano.jp/tag/#glink|
|button|画像ファイルを表示し選択可へ＆クリック時ラベルへ遷移|https://tyrano.jp/tag/#button|
|clickable|クリック可能領域を指定＆クリック時ラベルへ遷移|https://tyrano.jp/tag/#clickable|

記述の一番シンプルなのがlink命令で、公式サイトでは次のサンプルコードが掲げてあります。

### 公式サイトでのlinkの実装例

```
選択肢を表示します[l][r][r]

[link target=*select1]【１】選択肢　その１[endlink][r] <color=red>s</red>
[link target=*select2]【２】選択肢　その２[endlink][r]

[s]

*select1
[cm]
「選択肢１」がクリックされました[l]
@jump target=*common

*select2
[cm]
「選択肢２」がクリックされました[l]
@jump target=*common

*common
[cm]

共通ルートです
```

上記サンプルの ラベル・ジャンプ命令実装は以下のように行われています。

***【１】linkの記述***

- [link]命令内にクリック時のジャンプ先ラベルをtargetにて指定
- テキストを記述
- link命令の終了用のタグ[endlink]を追加

***【２】ジャンプ先ラベルの記述***

- 先の[link]命令で指定したラベルを宣言
- 処理を記述
- 次のラベルへジャンプ

選択肢を追加するたびに上記の【１】と【２】を記述していきます。

***なかなか面倒な記述です。***

link命令はパラメータがジャンプ先ラベルの指定だけでしたが、他の命令([glink](https://tyrano.jp/tag/#glink)・[button](https://tyrano.jp/tag/#button)・[clickable](https://tyrano.jp/tag/#clickable))ではさらに多数のパラメータを設定する必要があります。

もちろんティラノスクリプトにも、引数によるサブルーチンコールやマクロが用意されており、省力化を図ることが出来ます。

それでも、アセンブラに似たラベル式の記述はミスを誘引しやすく、***大変面倒です。***

# StateGo"ティラノスクリプト"サンプルによるラベル・ジャンプ操作系の命令について

翻って、[StateGo](https://statego.programanic.com/index-j.com)の["ティラノスクリプト"サンプル](https://qiita.com/tohmas/items/7b83a35b852f2c339970)ではラベル・ジャンプ操作系命令と同じ名前の（テーブル内の）該当項目に***必要なパラメータを記述するだけです。***


たとえば、[S_MUSICステート(クリックでステートの場所確認可)](https://statego.programanic.com/images/s_music_goto.gif)のlink命令は、下図のように【link】項目に記入します。

<img src="https://raw.githubusercontent.com/NNNIC/psgg-tyranoscript-sample/master/wiki/s_music_tbl.png" width="100%" />


link命令のフォーマットは以下の通りです。

<pre>
識別ID,"テキスト",【オプション】(例:[r])
</pre>

S_MUSICでは、以下のように設定してあります。

<pre>
play,"【１】うん。再生してください",[r]
noplay,"【２】いや。今は再生しないで！"
</pre>

１行が一つの選択肢に対応しており、サンプルは２つの選択肢をもちます。
そしてStateGoでは、先に説明にした【１】と【２】の部分を自動で実装します。
次にそれぞれの変換について説明します。

## link命令へ自動変換・・・【１】に相当

ジャンプ先ラベルはステート名とID識別子から生成して、他のパラメータから以下のように出力されます。

>出力：
><pre>
[link target="S_MUSIC___linklabel_play"] 【１】うん。再生してください [endlink] [r]
</pre>

## ジャンプ先ラベル処理を自動出力・・・【２】に相当

ジャンプ先ラベル処理では、link命令用に用意された f.lnkValにID識別子をセットします。
その後、ステートの分岐命令先頭ラベルへジャンプします。

>出力：
><pre>
*S_MUSIC___linklabel_play
[iscript]
    f.lnkval = 'play';
[endscript]
[jump target="S_MUSIC___branch"]
</pre>

## ステートの分岐編集について

ジャンプ先ラベル処理にて、ID識別子を変数に格納しました。
その変数とID識別子を比較することでステートの分岐部分を作成します。

S_MUSICステートのクリックメニューより、分岐編集を選択し、link用のID格納変数 'f.glnkval'と識別IDの比較の分岐を用意します。

![](https://raw.githubusercontent.com/NNNIC/psgg-tyranoscript-sample/master/wiki/s_music_br.png)

サンプルでは、以下のように分岐の遷移先が決定しています。

+ f.glnkval=='play'時はS_PLAYMUSICへ
+ f.glnkval=='noplay'時はS_PLAYMUSICへ

![](https://raw.githubusercontent.com/NNNIC/psgg-tyranoscript-sample/master/wiki/s_music_st3.png)




## 変換結果

最終的に、S_MUSICのデータは以下のように変換されます。

<pre>
;------------------------------
;    S_MUSIC
;
*S_MUSIC
[iscript]
    f.curstate = 'S_MUSIC';
    f.nextstate ='';
    f.yesno=0;
[endscript]
[iscript]
    f.lnkval='';
[endscript]
[link target="S_MUSIC___linklabel_play"] 【１】うん。再生してください [endlink] [r]
[link target="S_MUSIC___linklabel_noplay"] 【２】いや。今は再生しないで！ [endlink]
[s]
*S_MUSIC___branch
;
; BRANCH
;
[iscript]
    if ( f.lnkval == 'play' ) {  f.nextstate='S_PLAYMUSIC'; }
    else if ( f.lnkval == 'noplay' ) {  f.nextstate='S_NOPLAYMUSIC'; }
[endscript]
[jump target=&f.nextstate]
;
; LINK LABEL
;
*S_MUSIC___linklabel_play
[iscript]
    f.lnkval = 'play';
[endscript]
[jump target="S_MUSIC___branch"]
*S_MUSIC___linklabel_noplay
[iscript]
    f.lnkval = 'noplay';
[endscript]
[jump target="S_MUSIC___branch"]
;
; END OF S_MUSIC
;
</pre>

###　実行

S_MUSICステートの実行は以下のようになります。

(クリックでGIF再生)
<a href="https://statego.programanic.com/images/s_music_a.gif">
<img src="https://raw.githubusercontent.com/NNNIC/psgg-tyranoscript-sample/master/wiki/s_music.png" width=450px /></a>

#まとめ

ティラノスクリプトのラベル・ジャンプ操作系命令を、StateGoの機能により必要最低限の記述にて実装することが出来ます。

遷移先はGUIで決定されるため、ソースエディタ上でのラベル操作の必要がありません。

#変更事例

新規選択肢を作成する様子を動画にしました。

[動画-youtube](https://youtu.be/LD2BcO_OODg) 

実行-gif
![](https://statego.programanic.com/images/brsmp.gif)


#【資料１】StateGo"ティラノスクリプト"サンプルのラベル・ジャンプ操作系命令仕様

## テーブル項目

ラベル・ジャンプ操作系命令のフォーマットと格納変数、および、サンプルでの実装箇所となります。

|テーブル項目|フォーマット|変数|サンプルでの実装箇所|
|---|---|---|---|
|link|識別ID,"テキスト",【オプション】(例:[r])|f.lnkval| /MUSIC/S_MUSIC|
|glink|X座標,Y座標,幅,フォントサイズ,識別ID,テキスト|f.glkval|/S_QUESTION<br>/BTNLINK/S_BTNLINK1|
|button|X座標,Y座標,画像ファイル,識別ID|f.butval |/S_TITLE|
|clickable|X座標,Y座標,幅,高さ,識別ID|f.clkval|該当なし|
<img src="https://raw.githubusercontent.com/NNNIC/psgg-tyranoscript-sample/master/wiki/s_title_tbl.png" width=350px />

#【資料２】glinkの実装サンプル

実装箇所: /S_QUESTION 

<img src="https://raw.githubusercontent.com/NNNIC/psgg-tyranoscript-sample/master/wiki/s_question.png" width=350px />

### 入力

>```init.
#あかね
もしかして、ノベルゲームの開発に興味があるの？[p]
```

>```glink.
260,100,400,20,YES,"はい。興味あります"
260,170,400,20,OFCOUSE,"興味あります！"
260,240,400,20,MAYBE,"どちらかと言うと興味あり"
```
>```wait.
[s]
```

>![](https://raw.githubusercontent.com/NNNIC/psgg-tyranoscript-sample/master/wiki/s_question_br.png)

### 変換結果

><pre>
;------------------------------
;    S_QUESTION
;
*S_QUESTION
[iscript]
    f.curstate = 'S_QUESTION';
    f.nextstate ='';
    f.yesno=0;
[endscript]
#あかね
もしかして、ノベルゲームの開発に興味があるの？[p]
[iscript]
    f.glkval='';
[endscript]
[glink color="blue"  x=260 y=100 width=400 size=20 target="S_QUESTION___glinklabel_YES"  text="はい。興味あります" ]
[glink color="blue"  x=260 y=170 width=400 size=20 target="S_QUESTION___glinklabel_OFCOUSE"  text="興味あります！" ]
[glink color="blue"  x=260 y=240 width=400 size=20 target="S_QUESTION___glinklabel_MAYBE"  text="どちらかと言うと興味あり" ]
[s]
*S_QUESTION___branch
;
; BRANCH
;
[iscript]
    if ( f.glkval == 'YES' ) {  f.nextstate='S_INTREST'; }
    else if ( f.glkval == 'OFCOUSE' ) {  f.nextstate='S_INTREST'; }
    else if ( f.glkval == 'MAYBE' ) {  f.nextstate='S_INTREST'; }
[endscript]
[jump target=&f.nextstate]
;
; GLINK LABEL
;
*S_QUESTION___glinklabel_YES
[iscript]
    f.glkval = 'YES';
[endscript]
[jump target="S_QUESTION___branch"]
*S_QUESTION___glinklabel_OFCOUSE
[iscript]
    f.glkval = 'OFCOUSE';
[endscript]
[jump target="S_QUESTION___branch"]
*S_QUESTION___glinklabel_MAYBE
[iscript]
    f.glkval = 'MAYBE';
[endscript]
[jump target="S_QUESTION___branch"]
;
; END OF S_QUESTION
;
</pre>


#【資料３】buttonの実装サンプル

実装箇所 : /S_TITLE

<img src="https://raw.githubusercontent.com/NNNIC/psgg-tyranoscript-sample/master/wiki/s_title.png" width=350px />

###入力

テーブルのbuttonの項目に、フォーマットに従い以下を記述します。

>```button.
100,250,title/button_start.png,START
```

> 規定外の記述については、prewaitに直書きします。

>```prewait.
[button x=100 y=320 graphic="title/button_load.png"  role="load" ]
[button x=100 y=390 graphic="title/button_cg.png" storage="cg.ks" ]
[button x=100 y=460 graphic="title/button_replay.png" storage="replay.ks" ]
[button x=100 y=530 graphic="title/button_config.png" role="sleepgame" storage="config.ks" ]
```

>```wait.
[s]
```

>![](https://raw.githubusercontent.com/NNNIC/psgg-tyranoscript-sample/master/wiki/s_title_br.png)

###変換結果

><pre>
;------------------------------
;    S_TITLE
;    タイトル表示
*S_TITLE
[iscript]
    f.curstate = 'S_TITLE';
    f.nextstate ='';
    f.yesno=0;
[endscript]
@bg storage="title.jpg"
[iscript]
    f.butval='';
[endscript]
[button x=100 y=250 graphic="title/button_start.png" target="S_TITLE___buttonlabel_START"]
[button x=100 y=320 graphic="title/button_load.png"  role="load" ]
[button x=100 y=390 graphic="title/button_cg.png" storage="cg.ks" ]
[button x=100 y=460 graphic="title/button_replay.png" storage="replay.ks" ]
[button x=100 y=530 graphic="title/button_config.png" role="sleepgame" storage="config.ks" ]
[s]
*S_TITLE___branch
;
; BRANCH
;
[iscript]
    if ( f.butval == 'START' ) {  f.nextstate='S_SCENE_1'; }
[endscript]
[jump target=&f.nextstate]
;
; BUTTON LABEL
;
*S_TITLE___buttonlabel_START
[iscript]
    f.butval = 'START'
[endscript]
[jump target="S_TITLE___branch"]
;
; END OF S_TITLE
;
</pre>

以上