[C#]流れる文字列

エロゲのテキストみたいなやつです
Twitterで話題になってたので作ってみました

瞬間的に「あ」の左半分だけ描きたいようなこともあるかなと思って、画像コピーで実装しました。なのでちょっとコードが増えたかも。「あいうえお」の何文字目まで表示とかやったほうが実装は簡単だと思います。

サンプルプログラム
http://db.tt/JAozYD04

ソースコード

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;
using System.Text;

static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}

//設定画面
public class Form1 : Form
{
//フィールド
TextBox tb_text, tb_speed;
Label label_text, label_speed;
Button button;
static double speed = 5.0;

//プロパティ
public static double Speed { get { return speed; } }

//初期化
public Form1()
{
//フォームの設定
this.ClientSize = new Size(250, 180);
this.Text = "設定";
//文章を入力するテキストボックス
tb_text = new TextBox()
{
Size = new Size(200, 100),
Multiline = true,
ScrollBars = ScrollBars.Vertical,
Location = new Point(50, 5),
Text = "本日は晴天なり\r\nただいまマイクのテスト中",
};
//スピードを入力するテキストボックス
tb_speed = new TextBox()
{
Size = new Size(50, 15),
Text = speed.ToString(),
Location = new Point(50, 120),
};
//ラベル
label_text = new Label()
{
AutoSize = true,
Text = "文章",
Location = new Point(5, 5),
};
label_speed = new Label()
{
AutoSize = true,
Text = "スピード",
Location = new Point(5, 125),
};
//ボタン
button = new Button()
{
AutoSize = true,
Text = "表示",
Location = new Point(70, 145),
};
button.Click += button_Click;
//コントロールへ
this.Controls.AddRange(new Control[]
{
tb_text, tb_speed, button,
label_text, label_speed
});
}

//メソッド
//ボタン
private void button_Click(object sender, EventArgs e)
{
double speed_temp;
double.TryParse(tb_speed.Text, out speed_temp);
if (speed_temp <= 0) speed_temp = 1;//1px以下だとエラーを吐くため
speed = speed_temp;
tb_speed.Text = speed_temp.ToString();
View view = new View(tb_text.Text);
view.ShowDialog();
}
}

//表示用
public class View : Form
{
Timer timer;
Line[] lines;
static int fontsize = 12;//フォントサイズ
static int offsetY = 5;//縦の行間

//初期化
public View(string text)
{
//フォームの設定
this.Text = "流れるテキスト";
this.StartPosition = FormStartPosition.CenterParent;
this.Size = new Size(200, 150);
this.BackColor = Color.SkyBlue;
this.DoubleBuffered = true;
//Lineクラスの初期設定
string[] split = text.Replace("\r\n", "\n").Split('\n');
lines = new Line[split.Length];
Font font = new Font("MS UI Gothic", fontsize);
Point point = new Point(5, 5);
for (int i = 0; i < lines.Length; i++)
{
lines[i] = new Line(split[i], font, point);
point.Y += fontsize + offsetY;
}
lines[0].IsStart = true;
//タイマー
timer = new Timer()
{
Interval = 50,
Enabled = true,
};
timer.Tick += timer_Tick;
}

//タイマーイベント
void timer_Tick(object sender, EventArgs e)
{
this.Invalidate();
}

//グラフィックイベント
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
bool tonext = false;//次に進ませるフラグ
foreach (Line x in lines)
{
if (tonext && !x.IsStart)
{
x.IsStart = true;
tonext = false;
}
//横に広げる
if(x.IsStart) x.AddProgress(Form1.Speed);
if (x.IsEnd) tonext = true;
//画像の切り出し
if (x.IsStart)
{
Bitmap b = x.CutImage();
g.DrawImage(b, x.Location);
}
else
{
break;
}
}
}
}

//行単位のテキストのクラス
public class Line
{
//プロパティ
//テキスト
public string Text { get; set; }
//フォント
public Font Font { get; set; }
//場所
public Point Location { get; set; }
//進んだピクセル
public double Progress { get; private set; }
//横幅(pixel)
public int Width { get; private set; }
//縦幅(pixel)
public int Height { get; private set; }
//行の出力の開始、終了のフラグ
public bool IsStart { get; set; }
public bool IsEnd { get; private set; }

//初期化
public Line(string text, Font font, Point point)
{
//プロパティの設定
this.Text = text; this.Font = font; this.Location = point;
this.IsStart = false; this.IsEnd = false;
//進んだピクセル=0
this.Progress = 0.0;
//横幅の計算
Bitmap canvas = new Bitmap((int)(Text.Length * font.Size * 1.5),
(int)(font.Size * 2));//計算用のBitmap。領域を多めに確保
Graphics g = Graphics.FromImage(canvas);
SizeF stringSize = g.MeasureString(Text, font, canvas.Width);
this.Width = (int)stringSize.Width;
this.Height = (int)stringSize.Height;
}

//メソッド
//画像の切り出し
public Bitmap CutImage()
{
using (Bitmap temp = new Bitmap(Width, Height))
{
using (Graphics g = Graphics.FromImage(temp))
{
//背景を白で塗る
g.FillRectangle(Brushes.White, 0, 0, temp.Width, temp.Height);
//文字を書く
g.DrawString(Text, Font, Brushes.Black, new Point(0, 0));
};
//透明色の指定
temp.MakeTransparent(Color.White);
//切り抜く
Rectangle rect = new Rectangle(0, 0, (int)Progress, Height);
return temp.Clone(rect, temp.PixelFormat);
}
}

//Progress値増加
public void AddProgress(double diff)
{
//Progress値の増加
this.Progress = Math.Min(this.Width, this.Progress + diff);
//もし全て出力してたら
if (this.Progress >= this.Width) this.IsEnd = true;
}

//デバッグ用
public void Show()
{
Console.WriteLine("Text = {0}", Text);
Console.WriteLine("Font = {0}, {1}px", Font.Name, Font.Size);
Console.WriteLine("Location = ({0}, {1})", Location.X, Location.Y);
Console.WriteLine("Progress = {0}", Progress);
Console.WriteLine("Width = {0}, Height = {1}", Width, Height);
Console.WriteLine("IsStart = {0}, IsEnd = {1}", IsStart, IsEnd);
}
}
スポンサーサイト
プロフィール

こしあん

Author:こしあん
(:3[____]
【TwitterID : koshian2】
【ほしい物リスト】http://goo.gl/bDtvG2

Twitter
カウンター
天気予報

-天気予報コム- -FC2-
カテゴリ
月別アーカイブ
最新記事
最新トラックバック
検索フォーム
リンク