-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMessageWindow.java
More file actions
200 lines (170 loc) · 5.77 KB
/
MessageWindow.java
File metadata and controls
200 lines (170 loc) · 5.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/*
* Created on 8/20/2018
*
*/
import javafx.animation.AnimationTimer;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
/**
* @author nyatadecocoa
*/
public class MessageWindow {
// 白枠の幅
private static final int EDGE_WIDTH = 2;
// 行間の大きさ
protected static final int LINE_HEIGHT = 8;
// 1行の最大文字数
private static final int MAX_CHAR_IN_LINE = 20;
// 1ページに表示できる最大行数
private static final int MAX_LINES = 3;
// 1ページに表示できる最大文字数
private static final int MAX_CHAR_IN_PAGE = MAX_CHAR_IN_LINE * MAX_LINES;
// 一番外側の枠
private Rectangle rect;
// 一つ内側の枠(白い枠線ができるように)
private Rectangle innerRect;
// 実際にテキストを描画する枠
private Rectangle textRect;
// メッセージウィンドウを表示中か
private boolean isVisible = false;
// カーソルのアニメーションGIF
private Image cursorImage;
// メッセージを格納した配列
private char[] text = new char[128 * MAX_CHAR_IN_LINE];
// 最大ページ
private int maxPage;
// 現在表示しているページ
private int curPage = 0;
// 表示した文字数
private int curPos;
// 次のページへいけるか(▼が表示されてればtrue)
private boolean nextFlag = false;
// メッセージエンジン
private MessageEngine messageEngine;
// テキストを流すタイムライン
private AnimationTimer task;
public MessageWindow(Rectangle rect) {
this.rect = rect;
innerRect = new Rectangle(
rect.getX() + EDGE_WIDTH,
rect.getY() + EDGE_WIDTH,
rect.getWidth() - EDGE_WIDTH * 2,
rect.getHeight() - EDGE_WIDTH * 2);
textRect = new Rectangle(
innerRect.getX() + 16,
innerRect.getY() + 16,
320,
120);
// メッセージエンジンを作成
messageEngine = new MessageEngine();
cursorImage = new Image("image/cursor.gif");
}
public void draw(GraphicsContext gc) {
if (!isVisible) return;
// 枠を描く
gc.setFill(Color.WHITE);
gc.fillRect(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
// 内側の枠を描く
gc.setFill(Color.BLACK);
gc.fillRect(innerRect.getX(), innerRect.getY(), innerRect.getWidth(), innerRect.getHeight());
// 現在のページ(curPage)のcurPosまでの内容を表示
for (int i = 0; i <curPos; i++) {
char c = text[curPage * MAX_CHAR_IN_PAGE + i];
int dx = (int) textRect.getX() + MessageEngine.FONT_WIDTH * (i % MAX_CHAR_IN_LINE);
int dy = (int) textRect.getY() + (LINE_HEIGHT + MessageEngine.FONT_HEIGHT) * (i / MAX_CHAR_IN_LINE);
messageEngine.drawCharacter(dx, dy, c, gc);
}
// 最後のページでない場合は矢印を表示する
if (curPage < maxPage && nextFlag) {
int dx = (int) textRect.getX() + (MAX_CHAR_IN_LINE / 2) * MessageEngine.FONT_WIDTH - 8;
int dy = (int) textRect.getY() + (LINE_HEIGHT + MessageEngine.FONT_HEIGHT) * 3;
gc.drawImage(cursorImage, dx, dy);
}
}
/**
* メッセージをセットする
*
* @param msg メッセージ
*/
public void setMessage(String msg) {
curPos = 0;
curPage = 0;
nextFlag = false;
// 全角スペースで初期化
for (int i = 0; i < text.length; i++) {
text[i] = ' ';
}
int p = 0; // 処理中の文字位置
for (int i = 0; i < msg.length(); i++) {
char c = msg.charAt(i);
if (c == '\\') {
i++;
if (msg.charAt(i) == 'n') { // 改行
p += MAX_CHAR_IN_LINE;
p = (p / MAX_CHAR_IN_LINE) * MAX_CHAR_IN_LINE;
} else if (msg.charAt(i) == 'f') { // 改ページ
p += MAX_CHAR_IN_PAGE;
p = (p / MAX_CHAR_IN_PAGE) * MAX_CHAR_IN_PAGE;
}
} else {
text[p++] = c;
}
}
// デバッグ用
System.out.println(text);
maxPage = p / MAX_CHAR_IN_PAGE;
task = new DrawingWindowTask();
task.start();
}
/**
* メッセージを先に進める
*
* @return メッセージが終了したらtrueを返す
*/
public boolean nextMessage() {
// 現在ページが最後のページだったらメッセージを終了する
if (curPage == maxPage) {
task.stop();
return true;
}
// ▼が表示されてなければ次ページへいけない
if (nextFlag) {
curPage++;
curPos = 0;
nextFlag = false;
}
return false;
}
/**
* ウィンドウを表示
*/
public void show() {
isVisible = true;
}
/**
* ウィンドウを隠す
*/
public void hide() {
isVisible = false;
}
/**
* ウィンドウを表示中か
*/
public boolean isVisible() {
return isVisible;
}
class DrawingWindowTask extends AnimationTimer {
@Override
public void handle(long now) {
if (!nextFlag) {
curPos++; // 1文字増やす
// 1ページの文字数になったら▼を表示
if (curPos % MAX_CHAR_IN_PAGE == 0) {
nextFlag = true;
}
}
}
}
}