サンプルプログラム/文字が流れるテキストパネル

Last-modified: 2017-01-20 (金) 21:40:11

テキストパネルの内容を読み取り、編集して書き込むスクリプトと、それをタイマーで繰り返させる設定を使って、テキストパネルの文字を電光掲示板のように流してみましょう。

script_lcd_1.jpg


準備

電源のほかに必要なブロックと設定

ブロックの設定
ブロック備考
テキストパネル類×1Show text on screenをオンにしておく
Public textの内容は後で説明
プログラマブルブロック×1このスクリプトを保存しておく
Argumentにテキストパネルの名前を入れておく
タイマーブロック×1設定は後で説明

処理の流れを決める

メモ帳やC#言語が扱えるテキストエディタなどで、ざっくりと流れを書いてみます。

public void Main(string argument) {
    //対象にするテキストパネルを取得する
    //テキストパネルのPublic textを読み取る
    //読み込んだ文章を編集する
    //テキストパネルのPublic textに書き込む
}

第1段階:テキストパネルの読み書き

文章が移動する点は一旦置いておいて、まずは新しい知識になるテキストパネルの内容の読み込みと、それを動作確認するための文字列編集、前回まで同様のパネルへの書き込みだけ実装してみます。

2~3行目:ブロックの取得

var target = GridTerminalSystem.GetBlockWithName(argument) as IMyTextPanel;

まず、2行目、Mainメソッドの開始直後に、これまでと同じように、名前でブロックを取得する処理を入れます。

hello, worldで少し触れた短い書き方を使用しています。

前回では、変数argumentの内容をパネルに書き込む内容に使いましたが、今回はそれを応用し、取得するブロックの名前として「argumentの中身」を使います。

この場合、プログラマブルブロックのArgument欄に書いた文字列と同じ名前のブロックを取得することになります。

現在の状態は以下のようになります。まだ読み込むだけで何もしません。

public void Main(string argument) {
    var target = GridTerminalSystem.GetBlockWithName(argument) as IMyTextPanel;
}

4~5行目:テキストパネルの内容の取得

わかりやすいように1行空けて、テキストパネルの取得を行ってみます。

4行目:変数の準備

変数の型 変数の名前;

string text;

ますは4行目。この後の行で読み取る文字列を入れるために、前回行ったようにstring(文字列)型の変数を事前に作ります。

名前はtext(テキスト)にしておきました。

5行目:Public textをブロックから読み取る

変数 = 対象のブロック.GetPublicText();

text = target.GetPublicText();

「WritePublicText()」と似た「GetPublicText()」は、同様に、対象の後にピリオドを挟んで書くと、そのブロックのPublic textをstring(文字列)型のデータとして返してきます。

この処理結果を、先ほど用意した変数textに入れます。

現在の状態は以下のようになります。まだブロックからテキストを読み込むだけで何もしない状態です。

public void Main(string argument) {
    var target = GridTerminalSystem.GetBlockWithName(argument) as IMyTextPanel;
    string text;
    text = target.GetPublicText();
}

7~8行目:仮の文字列の操作を作る

書き込み処理を書く前に、Runしたら動作したことが分かる変化があるように、少し文字列を操作するようにします。

string outText;
outText = "<" + text + ">";

前回の補足で触れたように、「string(文字列)型のデータ」は+で繋ぐことができます。

ここでは、string型のoutTextという変数を新たに作り、「<」+「textの中身」+「>」を繋いだ結果を入れました。つまり、読み込んだテキストの左右に「<」と「>」を付け足します。

現在の状態は以下のようになります。編集した文字列を作るところまで来ましたが、書き込み処理が無いので動かしたとしてもまだ何も起こりません。

public void Main(string argument) {
    var target = GridTerminalSystem.GetBlockWithName(argument) as IMyTextPanel;
    string text;
    text = target.GetPublicText();
    string outText;
    outText = "<" + text + ">";
}

10行目:文字列の書き込み

対象.WritePublicText(書き込む文字列, 追記するかどうか);

target.WritePublicText(outText, false);

これは前回と同じ書き込み処理です。今回は書き込みたい文字列を入れた変数の名前がoutTextなので、括弧()内もそれを反映しています。

第1段階で実行

第1段階の完成状態は、下記のようになります。

public void Main(string argument) {
    var target = GridTerminalSystem.GetBlockWithName(argument) as IMyTextPanel;
    string text;
    text = target.GetPublicText();
    string outText;
    outText = "<" + text + ">";
    target.WritePublicText(outText, false);
}

テキストパネルの名前を、プログラマブルブロックのArgument欄に書いていることを確認し、Runをクリックしてください。

文字列の前後に<と>が付きます。繰り返すと増えていきます。

これで、テキストパネルの内容を読み込み、その内容を編集してから書き込むことができました。

その他に前回までから発展した点として、対象にしたブロックに対して2種類の操作を行っています。

第2段階:文字列が流れる機能を作る

7~8行目に仮の操作を入れていますが、ここを目的にあわせて変更していきます。

処理内容を考える

文字列を左に向かって流していく方法を考えてみると、「先頭の1文字を切り取って後ろに置く」ことを繰り返すことで実現できそうです。

先頭の文字を消して復活させるわけにもいかないので、

  1. 先に先頭の1文字を取り出して変数に入れる
  2. 2文字以降を取り出して変数に入れる、もしくは先頭の一文字を消す
  3. 取り出しておいた先頭の1文字を後ろに繋ぐ

といった処理が想定できます。

文字列の操作はゲーム特有ではないので、使用しているプログラミング言語であるC#自体の資料を探します。「C# 文字列 先頭 取得」や「C# 文字列 先頭 削除」などと調べると、Substringというメソッドの解説記事が見つかりました。

C#以外のサンプルプログラムもあるのでC#の方を読むと、先頭から2文字取得する例と、4文字目から最後まで取得する例がちょうど参考になりそうです。これを参考に実装してみます。

文字列の処理を実装する

7~8行目の文字列を編集する部分を変えていきます。

string outText;
outText = "<" + text + ">";

元の状態は、8行目で変数outTextを作り、9行目で文字列を処理した結果をoutTextに入れているわけですが、文字列を処理する部分を1行で済ませるには少し複雑なので、以下のように複数行に分けます。

変数outTextを作る
1文字目を取り出す
2文字目以降を取り出す
2文字目以降の後ろに1文字目を繋いで、outTextに入れる

string outText;
string str1 = text.Substring(0,1);
string str2 = text.Substring(1);
outText = str2 + str1;

Substringメソッドは、Public textを読み取る処理のようにピリオドを挟んで、string型のデータの後に入れ、括弧()内で数を設定することで、その変数の中身の特定の範囲の内容を取得する処理です。

まず、先頭1文字一時保存するためにstr1という変数を作り、「変数textの内容の先頭から1文字を取得」して、それを入れています。

次に、2文字目以降を一時保存するためにstr2という変数を作り、「変数textの内容の2文字目から最後までを取得」して、それを入れています。

最後に、outTextに、「2文字目以降」が入ったstr2と「1文字目」が入ったstr1の順番で繋いだ結果を入れています。

完成したスクリプト

public void Main(string argument) {
    var target = GridTerminalSystem.GetBlockWithName(argument) as IMyTextPanel;
    string text;
    text = target.GetPublicText();
    string outText;
    string str1 = text.Substring(0,1);
    string str2 = text.Substring(1);
    outText = str2 + str1;
    target.WritePublicText(outText, false);
}

実行

テキストパネルのPublic textには、例えば以下の例文のように、文の終わりから始まりまでの空きスペースとして適当に空白を追加した、1行だけの文章を入れてください。

Hello!       Welcome!

スクリプトを実行(Run)するたびに、先頭の1文字が消えて文字列が1文字左に移動し、即表示されるか数回かかるかは空白の長さで変わりますが、消えた文字列は右側から移動してきます。

タイマーにセットして繰り返し自動実行

タイマーブロックのツールバーに、プログラマブルブロックの「Run with default argument」と、そのタイマーブロックのスタートを設定してください。

タイマーブロックの待ち時間を1秒にしてスタートすると、1秒ごとにスクリプトが実行され、文字列がループしていきます。

argumentを利用して、複数のタイマー+パネルで並行して実行

このスクリプトは対象をargumentで選び、内容は対象のパネルから取っているので、
テキストパネルやLCDパネル1個とタイマーブロック1個の組み合わせを用意した数だけ、並行して実行することができます。


まず、テキストパネル類2つを違う名前にし、タイマーブロック2個も、ツールバー画面でどちら用か分かるような名前を付けておきます。

それぞれのタイマーブロックで自身をスタートするのは同じですが、タイマーから実行するプログラマブルブロックのアクションは「Run」を選び、Argumentダイアログで、対応するパネルの名前を設定します。

こうすると、それぞれのタイマーはargumentの文字列をそれぞれが担当するパネルの名前にしてプログラマブルブロックを実行(Run)するので、タイマーごとに別のパネルを操作することができます。

まとめ

応用の効く要素としては、テキストパネルのPublic textを読み取る操作、対象を実行時に決める方法を解説しました。

また、ブロックの情報によって結果が変わるスクリプトを、タイマーで繰り返し実行することが可能になりました。

コメント