1

私はゲームを作っており、XMLファイルからダイアログテキストを読みます。テキストボックスに収まるように、必要に応じて改行を自動的に追加するルーチンを作成しようとしています。ただし、正しく機能しません。現在のコードは次のとおりです。

SpriteFont dialogueFont = font31Adelon;
int lastSpace = 0;
string builder = "";
string newestLine = "";
float maxWidth = 921.6f;
float stringLength = 0;

for (int i = 0; i <= speech.Length - 1; i++) //each char in the string
{
    if (speech[i] == ' ') //record the index of the most recent space
    {
        lastSpace = i;
    }

    builder += speech[i]; 
    newestLine += speech[i]; 
    stringLength = dialogueFont.MeasureString(newestLine).X;

    if (stringLength > maxWidth) //longer than allowed
    {
        builder = builder.Remove(lastSpace); //cut off from last space 
        builder += Environment.NewLine;
        i = lastSpace; //start back from the cutoff
        newestLine = "";
    }
}
speech = builder;

私のテスト文字列は、「これは、正しく複数行に分割する必要がある長いスピーチの例です。これは数行の長さであり、単なる例のテキストであるため、重要なことは何も言いません。」

これがスピーチがどのように見えるかです:http: //www.iaza.com/work/120627C/iaza11394935036400.png

最初の行は、たまたま限界を超えたスペースなのでうまくいくと思います。

i=81およびlastSpace=80は、2行目が終了する場所です。.Removeコマンドの前のビルダーは次のようになります:「これは長いスピーチの例であり、\ r\n複数の行に分割する必要がありますc」

実行すると、次のようになります。「これは、\ r\n複数の行に分割する必要がある長いスピーチの例です」

3行目は、i=123およびlastSpace=120でサイズ制限を超えています。.Removeの前は次のようになります: "これは、\ r\n複数行に分割する必要がある長いスピーチの例です\r\正しくありません。数行の長さです。」

以降:「これは、\ r\n複数の行に正しく分割する必要がある\r\n長いスピーチの例です。\r\n数行の長さです。」

ご覧のとおり、余分な文字は切り取られますが、そのスペースである文字80が削除を開始することになっています。私が読んだものから.Removeは、単一のパラメーターで呼び出されると、指定されたインデックスを含むすべてのものを切り取ります。ただし、i=79もカットしています。これを補うためにlastSpaceに加算または減算するのは簡単なようですが、「インデックスの範囲外」エラーが発生するか、さらに多くの文字を切り取ります。.Remove(lastSpace、i-lastSpace)を実行しようとしましたが、それも機能しません。lastSpaceに加算または減算することにより、「スペースで終わる」ケースを他のケースとは異なる方法で処理しようとしました。私はさまざまな方法で物事を分割しようとしましたが、どれもうまくいきませんでした。

私はこれを見るのにとてもうんざりしているので、どんな助けもいただければ幸いです。

4

3 に答える 3

1

別の方法として、.splitを使用して文を配列に分割し、次の作業用のスペースがなくなるまでボックスに入力してから、改行を追加して次の行から開始することができます。

于 2012-06-27T05:51:56.597 に答える
1

に追加Environment.NewLineするStringBuilder場合は、削除を開始するインデックスを指定するときに考慮する必要があります。

Environment.NewLineの値はシステムに依存します。"\r\n""\n"または(または、 MSDNによると"\r"最初の2つのうちの1つのみ)にすることができます。 あなたの場合、それは、1つのスペースを削除するために、他の2つの文字を追加したことを意味します。
"\r\n"

まず、新しい変数を宣言する必要があります。

int additionalChars = 0;

次に、テキスト行を追加するときは、コードを次のように変更する必要があります。

builder = builder.Remove(lastSpace + additionalChars); //cut off from last space 
builder += Environment.NewLine;
additionalChars += Environment.NewLine.Length - 1; 

これ-1は、すでにスペースを削除しているためです(このコードは、システムのの定義から独立している必要がありますEnvironment.NewLine)。

更新:行制限より長い単語も考慮する必要があります。とにかくそれらを壊す必要があります(仕方がないので試してみてください):

if (stringLength > maxWidth) //longer than allowed
{
    // Cut off only if there was a space to cut off at
    if (lastSpace >= 0) { 
        builder = builder.Remove(lastSpace + additionalChars); //cut off from last space 
        i = lastSpace; //start back from the cutoff
    }
    builder += Environment.NewLine;
    // If there was no space that we cut off, there is also no need to subtract it here
    additionalChars += Environment.NewLine.Length - (lastSpace >= 0 ? 1 : 0);
    lastSpace = -1; // Means: No space found yet
    newestLine = "";
}
于 2012-06-27T06:07:57.580 に答える
0

次のコードのようなことをしてもらえますか?利点は2つあります。まず、次のスペースにスキップして、文字ごとに移動するのではなく、単語全体を追加するかどうかを測定して決定します。次に、文字列に追加されたすべての文字ではなく、文字列内の単語ごとに1回だけMeasureStringを呼び出します。Append単語が収まる場合、または収まらAppendLineず改行が必要な場合にStringBuilderを使用します。

        int lastSpace = 0;
        int nextSpace = s.IndexOf(' ', lastSpace + 1);
        float width = 0;
        float totalWidth = 0;
        float maxWidth = 200;
        while (nextSpace >= 0)
        {
            string piece = s.Substring(lastSpace, nextSpace - lastSpace);
            width = g.MeasureString(piece, this.Font).Width;
            if (totalWidth + width < maxWidth)
            {
                sb.Append(piece);
                totalWidth += width;
            }
            else
            {
                sb.AppendLine(piece);
                totalWidth = 0;
            }
            lastSpace = nextSpace;
            nextSpace = s.IndexOf(' ', lastSpace + 1);
        }
        MessageBox.Show(sb.ToString());
于 2012-06-27T07:02:20.553 に答える