cyross-ruby-miyako 2.0.5.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. data/README +1092 -929
  2. data/Rakefile +7 -7
  3. data/defines.h +144 -144
  4. data/extern.h +29 -29
  5. data/install_miyako.rb +87 -87
  6. data/lib/Miyako/API/audio.rb +572 -198
  7. data/lib/Miyako/API/basic_data.rb +825 -573
  8. data/lib/Miyako/API/bitmap.rb +534 -507
  9. data/lib/Miyako/API/choices.rb +481 -475
  10. data/lib/Miyako/API/collision.rb +486 -460
  11. data/lib/Miyako/API/diagram.rb +586 -561
  12. data/lib/Miyako/API/drawing.rb +151 -151
  13. data/lib/Miyako/API/exceptions.rb +105 -0
  14. data/lib/Miyako/API/fixedmap.rb +462 -428
  15. data/lib/Miyako/API/font.rb +430 -403
  16. data/lib/Miyako/API/input.rb +456 -447
  17. data/lib/Miyako/API/layout.rb +636 -433
  18. data/lib/Miyako/API/map.rb +583 -529
  19. data/lib/Miyako/API/map_event.rb +222 -198
  20. data/lib/Miyako/API/modules.rb +357 -109
  21. data/lib/Miyako/API/movie.rb +166 -154
  22. data/lib/Miyako/API/parts.rb +276 -189
  23. data/lib/Miyako/API/plane.rb +205 -166
  24. data/lib/Miyako/API/screen.rb +341 -325
  25. data/lib/Miyako/API/shape.rb +443 -443
  26. data/lib/Miyako/API/sprite.rb +771 -752
  27. data/lib/Miyako/API/sprite_animation.rb +490 -481
  28. data/lib/Miyako/API/sprite_list.rb +1135 -0
  29. data/lib/Miyako/API/spriteunit.rb +168 -147
  30. data/lib/Miyako/API/story.rb +350 -300
  31. data/lib/Miyako/API/textbox.rb +770 -725
  32. data/lib/Miyako/API/utility.rb +419 -388
  33. data/lib/Miyako/API/viewport.rb +189 -139
  34. data/lib/Miyako/API/yuki.rb +1226 -996
  35. data/lib/Miyako/EXT/miyako_cairo.rb +62 -62
  36. data/lib/Miyako/EXT/raster_scroll.rb +138 -138
  37. data/lib/Miyako/EXT/slides.rb +157 -157
  38. data/lib/Miyako/miyako.rb +201 -171
  39. data/lib/Miyako/miyako_require_only.rb +35 -0
  40. data/miyako_basicdata.c +590 -590
  41. data/miyako_bitmap.c +1225 -1225
  42. data/miyako_collision.c +403 -403
  43. data/miyako_drawing.c +187 -187
  44. data/miyako_font.c +334 -334
  45. data/miyako_hsv.c +830 -830
  46. data/miyako_input_audio.c +254 -0
  47. data/miyako_layout.c +191 -191
  48. data/miyako_no_katana.c +1078 -1074
  49. data/miyako_sprite2.c +431 -0
  50. data/miyako_transform.c +438 -438
  51. data/miyako_utility.c +288 -288
  52. data/sample/Animation1/m1ku.rb +68 -68
  53. data/sample/Animation2/lex.rb +96 -96
  54. data/sample/Diagram_sample/diagram_sample_yuki2.rb +328 -386
  55. data/sample/Room3/blue.rb +297 -297
  56. data/sample/Room3/ending.rb +180 -180
  57. data/sample/Room3/green.rb +220 -220
  58. data/sample/Room3/main.rb +119 -119
  59. data/sample/Room3/main_component.rb +59 -59
  60. data/sample/Room3/red.rb +227 -227
  61. data/sample/Room3/room3.rb +25 -27
  62. data/sample/Room3/title.rb +184 -184
  63. data/sample/ball_action_sample.rb +204 -204
  64. data/sample/blit_rop.rb +70 -70
  65. data/sample/cairo_sample.rb +25 -25
  66. data/sample/circle_collision_test.rb +66 -66
  67. data/sample/collision_test.rb +33 -33
  68. data/sample/collision_test2.rb +108 -108
  69. data/sample/fixed_map_test/fixed_map_sample.rb +140 -140
  70. data/sample/fixed_map_test/readme.txt +72 -72
  71. data/sample/map_test/chara.rb +58 -58
  72. data/sample/map_test/main_parts.rb +69 -69
  73. data/sample/map_test/main_scene.rb +153 -153
  74. data/sample/map_test/map_manager.rb +75 -75
  75. data/sample/map_test/map_test.rb +23 -23
  76. data/sample/map_test/oasis.rb +71 -71
  77. data/sample/map_test/readme.txt +89 -89
  78. data/sample/map_test/route.rb +157 -157
  79. data/sample/map_test/town.rb +74 -74
  80. data/sample/polygon_test.rb +35 -35
  81. data/sample/rasterscroll.rb +24 -24
  82. data/sample/takahashi.rb +42 -42
  83. data/sample/textbox_sample.rb +189 -189
  84. data/sample/transform.rb +54 -54
  85. data/sample/utility_test.rb +73 -73
  86. data/sample/utility_test2.rb +61 -61
  87. data/sample/utility_test3.rb +64 -64
  88. data/sample/utility_test4.rb +73 -73
  89. data/uninstall_miyako.rb +19 -19
  90. data/win/miyako_no_katana.so +0 -0
  91. metadata +7 -2
@@ -1,140 +1,190 @@
1
- # -*- encoding: utf-8 -*-
2
- =begin
3
- --
4
- Miyako v2.0
5
- Copyright (C) 2007-2008 Cyross Makoto
6
-
7
- This library is free software; you can redistribute it and/or
8
- modify it under the terms of the GNU Lesser General Public
9
- License as published by the Free Software Foundation; either
10
- version 2.1 of the License, or (at your option) any later version.
11
-
12
- This library is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
- Lesser General Public License for more details.
16
-
17
- You should have received a copy of the GNU Lesser General Public
18
- License along with this library; if not, write to the Free Software
19
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
- ++
21
- =end
22
-
23
- module Miyako
24
- #==ビューポートクラス
25
- # 描画時の表示範囲を変更する
26
- # 画面全体を基準(640x480の画面のときは(0,0)-(639,479)の範囲)として、範囲を設定する
27
- # 範囲の設定はいつでも行えるが、描画にはrenderメソッドを呼び出した時の値が反映される
28
- class Viewport
29
- attr_accessor :visible #レンダリングの可否(true->描画 false->非描画)
30
-
31
- #===ビューポートのインスタンスを生成する
32
- #_x_:: ビューポートの左上位置(x座標)
33
- #_y_:: ビューポートの左上位置(y座標)
34
- #_w_:: ビューポートの幅(共に1以上、0以下のときはエラーが出る)
35
- #_h_:: ビューポートの高さ(共に1以上、0以下のときはエラーが出る)
36
- def initialize(x, y, w, h)
37
- raise MiyakoError, "Illegal size! w:#{w} h:#{h}" if (w <= 0 || h <= 0)
38
- @rect = Rect.new(x, y, w, h)
39
- @sq = Rect.new(x, y, x+w-1, y+h-1)
40
- @visible = true
41
- end
42
-
43
- #===ビューポートの内容を画面に反映する
44
- # ブロックが渡ってきたときは、範囲を変更して指定することが出来る(この変更は、本メソッドを呼ぶ時だけ有効)
45
- # ブロックの引数は、|Rect構造体|が渡される。
46
- #_block_:: 呼び出し時にブロック付き呼び出しが行われたときのブロック本体。
47
- #呼び先に渡すことが出来る。ブロックがなければnilが入る
48
- def render(&block)
49
- return unless @visible
50
- if block_given?
51
- rect = @rect.dup
52
- yield rect
53
- Screen.bitmap.set_clip_rect(*rect)
54
- else
55
- Screen.bitmap.set_clip_rect(*@rect)
56
- end
57
- end
58
-
59
- #===ビューポートの左上位置を変更する
60
- # 移動量を指定して、位置を変更する
61
- # ブロックを渡したとき、ブロックの評価した結果、偽になったときは移動させた値を元に戻す
62
- #_dx_:: 移動量(x方向)
63
- #_dy_:: 移動量(y方向)
64
- #返却値:: 自分自身を返す
65
- def move(dx,dy)
66
- orect = rect.to_a[0..1]
67
- osq = sq.to_a[0..1]
68
- @rect.move(dx,dy)
69
- @sq.move(dx, dy)
70
- if block_given?
71
- unless yield(self)
72
- @rect.move_to(*orect)
73
- @sq.move_to(*osq)
74
- end
75
- end
76
- return self
77
- end
78
-
79
- #===ビューポートの左上位置を変更する
80
- # 移動先を指定して、位置を変更する
81
- # ブロックを渡したとき、ブロックの評価した結果、偽になったときは移動させた値を元に戻す
82
- #_x_:: 移動先位置(x方向)
83
- #_y_:: 移動先位置(y方向)
84
- #返却値:: 自分自身を返す
85
- def move_to(x,y)
86
- orect = rect.to_a[0..1]
87
- osq = sq.to_a[0..1]
88
- @rect.move_to(x,y)
89
- @sq.move_to(x, y)
90
- if block_given?
91
- unless yield(self)
92
- @rect.move_to(*orect)
93
- @sq.move_to(*osq)
94
- end
95
- end
96
- end
97
-
98
- #===ビューポートの大きさを変更する
99
- # 変化量を指定して変更する
100
- #_dw_:: 幅
101
- #_dh_:: 高さ
102
- #返却値:: 自分自身を返す
103
- def resize(dw,dh)
104
- raise MiyakoError, "Illegal size! w:#{w} h:#{h}" if ((@rect.w + dw) <= 0 || (@rect.h + dh) <= 0)
105
- @rect.resize(dw, dh)
106
- @sq.resize(dw, dh)
107
- return self
108
- end
109
-
110
- #===ビューポートの大きさを変更する
111
- # 幅と高さを指定して変更する
112
- #_w_::
113
- #_h_:: 高さ
114
- #返却値:: 自分自身を返す
115
- def resize_to(w,h)
116
- raise MiyakoError, "Illegal size! w:#{w} h:#{h}" if (w <= 0 || h <= 0)
117
- @rect.resize_to(w,h)
118
- @sq.resize_to(w, h)
119
- return self
120
- end
121
-
122
- #===インスタンスを解放する
123
- def dispose
124
- @rect = nil
125
- @sq = nil
126
- end
127
-
128
- #===ビューポートのインスタンスを取得する
129
- #返却値:: ビューポートの矩形(Rect構造体インスタンス)の複製
130
- def viewport
131
- return @rect.dup
132
- end
133
-
134
- #===ビューポートのインスタンスを「左、右、上、下」の形式で取得する
135
- #返却値:: ビューポートの矩形(Square構造体インスタンス)の複製
136
- def square
137
- return @sq.dup
138
- end
139
- end
1
+ # -*- encoding: utf-8 -*-
2
+ =begin
3
+ --
4
+ Miyako v2.1
5
+ Copyright (C) 2007-2008 Cyross Makoto
6
+
7
+ This library is free software; you can redistribute it and/or
8
+ modify it under the terms of the GNU Lesser General Public
9
+ License as published by the Free Software Foundation; either
10
+ version 2.1 of the License, or (at your option) any later version.
11
+
12
+ This library is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General Public
18
+ License along with this library; if not, write to the Free Software
19
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ ++
21
+ =end
22
+
23
+ module Miyako
24
+ #==ビューポートクラス
25
+ # 描画時の表示範囲を変更する
26
+ # 画面全体を基準(640x480の画面のときは(0,0)-(639,479)の範囲)として、範囲を設定する
27
+ # 範囲の設定はいつでも行えるが、描画にはrenderメソッドを呼び出した時の値が反映される
28
+ class Viewport
29
+ include SpriteBase
30
+ include Animation
31
+
32
+ attr_accessor :visible #レンダリングの可否(true->描画 false->非描画)
33
+
34
+ #===ビューポートのインスタンスを生成する
35
+ #_x_:: ビューポートの左上位置(x座標)
36
+ #_y_:: ビューポートの左上位置(y座標)
37
+ #_w_:: ビューポートの幅(共に1以上、0以下のときはエラーが出る)
38
+ #_h_:: ビューポートの高さ(共に1以上、0以下のときはエラーが出る)
39
+ def initialize(x, y, w, h)
40
+ raise MiyakoValueError, "Illegal size! w:#{w} h:#{h}" if (w <= 0 || h <= 0)
41
+ @rect = Rect.new(x, y, w, h)
42
+ @sq = Rect.new(x, y, x+w-1, y+h-1)
43
+ @visible = true
44
+ end
45
+
46
+ def initialize_copy(obj) #:nodoc:
47
+ @rect = @rect.dup
48
+ @sq = @sq.dup
49
+ end
50
+
51
+ #===ビューポートの内容を画面に反映する
52
+ # ブロックが渡ってきたときは、範囲を変更して指定することが出来る(この変更は、本メソッドを呼ぶ時だけ有効)
53
+ # ブロックの引数は、|Rect構造体|が渡される。
54
+ #_block_:: 呼び出し時にブロック付き呼び出しが行われたときのブロック本体。
55
+ #呼び先に渡すことが出来る。ブロックがなければnilが入る
56
+ def render(&block)
57
+ return unless @visible
58
+ if block_given?
59
+ rect = @rect.dup
60
+ yield rect
61
+ Screen.bitmap.set_clip_rect(*rect)
62
+ else
63
+ Screen.bitmap.set_clip_rect(*@rect)
64
+ end
65
+ end
66
+
67
+ #===ビューポートの左上位置を変更する
68
+ # 移動量を指定して、位置を変更する
69
+ # ブロックを渡したとき、ブロックの評価した結果、偽になったときは移動させた値を元に戻す
70
+ #_dx_:: 移動量(x方向)
71
+ #_dy_:: 移動量(y方向)
72
+ #返却値:: 自分自身を返す
73
+ def move!(dx,dy)
74
+ orect = rect.to_a[0..1]
75
+ osq = sq.to_a[0..1]
76
+ @rect.move!(dx,dy)
77
+ @sq.move!(dx, dy)
78
+ if block_given?
79
+ unless yield(self)
80
+ @rect.move_to!(*orect)
81
+ @sq.move_to!(*osq)
82
+ end
83
+ end
84
+ return self
85
+ end
86
+
87
+ #===ビューポートの左上位置を変更する
88
+ # 移動先を指定して、位置を変更する
89
+ # ブロックを渡したとき、ブロックの評価した結果、偽になったときは移動させた値を元に戻す
90
+ #_x_:: 移動先位置(x方向)
91
+ #_y_:: 移動先位置(y方向)
92
+ #返却値:: 自分自身を返す
93
+ def move_to!(x,y)
94
+ orect = rect.to_a[0..1]
95
+ osq = sq.to_a[0..1]
96
+ @rect.move_to!(x,y)
97
+ @sq.move_to!(x, y)
98
+ if block_given?
99
+ unless yield(self)
100
+ @rect.move_to!(*orect)
101
+ @sq.move_to!(*osq)
102
+ end
103
+ end
104
+ end
105
+
106
+ #===ビューポートの大きさを変更する
107
+ # 変化量を指定して変更する
108
+ #_dw_:: 幅
109
+ #_dh_:: 高さ
110
+ #返却値:: 自分自身を返す
111
+ def resize!(dw,dh)
112
+ raise MiyakoValueError, "Illegal size! w:#{w} h:#{h}" if ((@rect.w + dw) <= 0 || (@rect.h + dh) <= 0)
113
+ @rect.resize!(dw, dh)
114
+ @sq.resize!(dw, dh)
115
+ return self
116
+ end
117
+
118
+ #===ビューポートの大きさを変更する
119
+ # 幅と高さを指定して変更する
120
+ #_w_:: 幅
121
+ #_h_:: 高さ
122
+ #返却値:: 自分自身を返す
123
+ def resize_to!(w,h)
124
+ raise MiyakoValueError, "Illegal size! w:#{w} h:#{h}" if (w <= 0 || h <= 0)
125
+ @rect.resize_to!(w,h)
126
+ @sq.resize_to!(w, h)
127
+ return self
128
+ end
129
+
130
+ #===ビューポートの左上位置を変更したときの位置を求める
131
+ #移動量を指定して、位置を変更する
132
+ #ただし、自分自身の位置は変わらない
133
+ #_dx_:: 移動量(x方向)
134
+ #_dy_:: 移動量(y方向)
135
+ #返却値:: 更新したインスタンス(Rect構造体)を返す
136
+ def move(dx,dy)
137
+ @rect.dup.move!(dx,dy)
138
+ end
139
+
140
+ #===ビューポートの左上位置を変更したときの位置を求める
141
+ #移動先を指定して、位置を変更する
142
+ #ただし、自分自身の位置は変わらない
143
+ #_x_:: 移動先位置(x方向)
144
+ #_y_:: 移動先位置(y方向)
145
+ #返却値:: 更新したインスタンス(Rect構造体)を返す
146
+ def move_to(x,y)
147
+ @rect.dup.move_to!(x,y)
148
+ end
149
+
150
+ #===ビューポートの大きさを変更したときの値を求める
151
+ #変化量を指定して変更する
152
+ #ただし、自分自身の位置は変わらない
153
+ #_dw_:: 幅
154
+ #_dh_:: 高さ
155
+ #返却値:: 更新したインスタンス(Rect構造体)を返す
156
+ def resize(dw,dh)
157
+ raise MiyakoValueError, "Illegal size! w:#{w} h:#{h}" if ((@rect.w + dw) <= 0 || (@rect.h + dh) <= 0)
158
+ @rect.dup.resize!(dw,dh)
159
+ end
160
+
161
+ #===ビューポートの大きさを変更したときの値を求める
162
+ #幅と高さを指定して変更する
163
+ #ただし、自分自身の位置は変わらない
164
+ #_w_:: 幅
165
+ #_h_:: 高さ
166
+ #返却値:: 更新したインスタンス(Rect構造体)を返す
167
+ def resize_to(w,h)
168
+ raise MiyakoValueError, "Illegal size! w:#{w} h:#{h}" if (w <= 0 || h <= 0)
169
+ @rect.dup.resize_to!(w,h)
170
+ end
171
+
172
+ #===インスタンスを解放する
173
+ def dispose
174
+ @rect = nil
175
+ @sq = nil
176
+ end
177
+
178
+ #===ビューポートのインスタンスを複製する
179
+ #返却値:: 自分自身の複製
180
+ def viewport
181
+ return self.dup
182
+ end
183
+
184
+ #===ビューポートのインスタンスを「左、右、上、下」の形式で取得する
185
+ #返却値:: ビューポートの矩形(Square構造体インスタンス)の複製
186
+ def square
187
+ return @sq.dup
188
+ end
189
+ end
140
190
  end
@@ -1,996 +1,1226 @@
1
- # -*- encoding: utf-8 -*-
2
- =begin
3
- --
4
- Miyako v2.0
5
- Copyright (C) 2007-2009 Cyross Makoto
6
-
7
- This library is free software; you can redistribute it and/or
8
- modify it under the terms of the GNU Lesser General Public
9
- License as published by the Free Software Foundation; either
10
- version 2.1 of the License, or (at your option) any later version.
11
-
12
- This library is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
- Lesser General Public License for more details.
16
-
17
- You should have received a copy of the GNU Lesser General Public
18
- License along with this library; if not, write to the Free Software
19
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
- ++
21
- =end
22
-
23
- #lambdaの別名として、yuki_plotメソッドを追加
24
- alias :yuki_plot :lambda
25
-
26
- #=シナリオ言語Yuki実装モジュール
27
- module Miyako
28
-
29
- #==Yuki本体クラス
30
- #Yukiの内容をオブジェクト化したクラス
31
- #Yukiのプロット処理を外部メソッドで管理可能
32
- #プロットは、引数を一つ(Yuki2クラスのインスタンス)を取ったメソッドもしくはブロック
33
- #として記述する。
34
- class Yuki
35
-
36
- #==キャンセルを示す構造体
37
- #コマンド選択がキャンセルされたときに生成される構造体
38
- Canceled = Struct.new(:dummy)
39
-
40
- #==コマンド構造体
41
- #_body_:: コマンドの名称(移動する、調べるなど、アイコンなどの画像も可)
42
- #_body_selected_:: 選択時コマンドの名称(移動する、調べるなど、アイコンなどの画像も可)(省略時は、bodyと同一)
43
- #_condition_:: 表示条件(ブロック)。評価の結果、trueのときのみ表示
44
- #_result_:: 選択結果(移動先シーンクラス名、シナリオ(メソッド)名他のオブジェクト)
45
- Command = Struct.new(:body, :body_selected, :condition, :result)
46
-
47
- #==コマンド構造体
48
- #_body_:: コマンドの名称(移動する、調べるなど、アイコンなどの画像も可)
49
- #_body_selected_:: 選択時コマンドの名称(移動する、調べるなど、アイコンなどの画像も可)(省略時は、bodyと同一)
50
- #_condition_:: 表示条件(ブロック)。評価の結果、trueのときのみ表示
51
- #_result_:: 選択結果(移動先シーンクラス名、シナリオ(メソッド)名他のオブジェクト)
52
- #_end_select_proc_:: この選択肢を選択したときに優先的に処理するブロック。
53
- #ブロックは1つの引数を取る(コマンド選択テキストボックス))。デフォルトはnil
54
- CommandEX = Struct.new(:body, :body_selected, :condition, :result, :end_select_proc)
55
-
56
- #===Yuki#update実行中に行わせる処理を実装するテンプレートメソッド
57
- #但し、メソッド本体は、update_inner=メソッドで設定する必要がある
58
- #_yuki_:: 実行中のYukiクラスインスタンス
59
- def update_inner(yuki)
60
- end
61
-
62
- #===Yuki#text実行中に行わせる処理を実装するテンプレートメソッド
63
- #update_textテンプレートメソッドは、textメソッドで渡した文字列全体ではなく、
64
- #内部で1文字ずつ分割して、その字が処理されるごとに呼ばれる。
65
- #そのため、引数chで入ってくるのは、分割された1文字となる。
66
- #但し、メソッド本体は、update_text=メソッドで設定する必要がある
67
- #_yuki_:: 実行中のYukiクラスインスタンス
68
- #_ch_:: textメソッドで処理中の文字(分割済みの1文字)
69
- def update_text(yuki, ch)
70
- end
71
-
72
- #===Yuki#cr呼び出し時に行わせる処理を実装するテンプレートメソッド
73
- #但し、メソッド本体は、update_cr=メソッドで設定する必要がある
74
- #_yuki_:: 実行中のYukiクラスインスタンス
75
- def update_cr(yuki)
76
- end
77
-
78
- #===Yuki#clear呼び出し時に行わせる処理を実装するテンプレートメソッド
79
- #但し、メソッド本体は、update_clear=メソッドで設定する必要がある
80
- #_yuki_:: 実行中のYukiクラスインスタンス
81
- def update_clear(yuki)
82
- end
83
-
84
- attr_accessor :visible
85
- attr_accessor :update_inner, :update_text, :update_cr, :update_clear
86
- attr_reader :parts, :vars, :valign
87
- #release_checks:: ポーズ解除を問い合わせるブロックの配列。
88
- #callメソッドを持ち、true/falseを返すインスタンスを配列操作で追加・削除できる。
89
- #ok_checks:: コマンド選択決定を問い合わせるブロックの配列。
90
- #callメソッドを持ち、true/falseを返すインスタンスを配列操作で追加・削除できる。
91
- #cancel_checks:: コマンド選択解除(キャンセル)を問い合わせるブロックの配列。
92
- #callメソッドを持ち、true/falseを返すインスタンスを配列操作で追加・削除できる。
93
- attr_reader :release_checks, :ok_checks, :cancel_checks
94
- attr_reader :pre_pause, :pre_command, :pre_cancel, :post_pause, :post_command, :post_cancel
95
- #selecting_procs:: コマンド選択時に行うブロックの配列。
96
- #ブロックは4つの引数を取る必要がある。
97
- #(1)コマンド決定ボタンを押した?(true/false)
98
- #(2)キャンセルボタンを押した?(true/false)
99
- #(3)キーパッドの移動量を示す配列([dx,dy])
100
- #(4)マウスの位置を示す配列([x,y])
101
- #callメソッドを持つブロックが使用可能。
102
- attr_reader :selecting_procs
103
-
104
- #===Yukiを初期化する
105
- #
106
- #ブロック引数として、テキストボックスの変更などの処理をブロック内に記述することが出来る。
107
- #引数の数とブロック引数の数が違っていれば例外が発生する
108
- #_params_:: ブロックに渡す引数リスト
109
- def initialize(*params, &proc)
110
- @yuki = { }
111
- @text_box = nil
112
- @command_box = nil
113
-
114
- @executing = false
115
- @with_update_input = true
116
-
117
- @exec_plot = nil
118
-
119
- @pausing = false
120
- @selecting = false
121
- @waiting = false
122
-
123
- @pause_release = false
124
- @select_ok = false
125
- @select_cancel = false
126
- @select_amount = [0, 0]
127
- @mouse_amount = nil
128
-
129
- @result = nil
130
- @plot_result = nil
131
-
132
- @update_inner = lambda{|yuki|}
133
- @update_text = lambda{|yuki, ch|}
134
- @update_cr = lambda{|yuki|}
135
- @update_clear = lambda{|yuki|}
136
-
137
- @parts = {}
138
- @visibles = []
139
- @vars = {}
140
- @visible = true
141
-
142
- @executing_fiber = nil
143
-
144
- @text_methods = {:char => self.method(:text_by_char),
145
- :string => self.method(:text_by_str) }
146
- @text_method_name = :char
147
-
148
- @valign = :middle
149
-
150
- @release_checks_default = [lambda{ Input.pushed_all?(:btn1) }, lambda{ Input.click?(:left) } ]
151
- @release_checks = @release_checks_default.dup
152
-
153
- @ok_checks_default = [lambda{ Input.pushed_all?(:btn1) },
154
- lambda{ self.commandbox.attach_any_command?(*Input.get_mouse_position) && Input.click?(:left) } ]
155
- @ok_checks = @ok_checks_default.dup
156
-
157
- @cancel_checks_default = [lambda{ Input.pushed_all?(:btn2) },
158
- lambda{ Input.click?(:right) } ]
159
- @cancel_checks = @cancel_checks_default.dup
160
-
161
- @key_amount_proc = lambda{ Input.pushed_amount }
162
- @mouse_amount_proc = lambda{ Input.mouse_cursor_inner? ? Input.get_mouse_position : nil }
163
-
164
- @pre_pause = []
165
- @pre_command = []
166
- @pre_cancel = []
167
- @post_pause = []
168
- @post_command = []
169
- @post_cancel = []
170
- @selecting_procs = []
171
-
172
- @is_outer_height = self.method(:is_outer_height)
173
-
174
- @now_page = nil
175
- @first_page = nil
176
-
177
- raise MiyakoError, "Aagument count is not same block parameter count!" if proc && proc.arity.abs != params.length
178
- instance_exec(*params, &proc) if block_given?
179
- end
180
-
181
- #===Yuki#showで表示指定した画像を描画する
182
- #描画順は、showメソッドで指定した順に描画される(先に指定した画像は後ろに表示される)
183
- #なお、visibleの値がfalseの時は描画されない。
184
- #返却値:: 自分自身を返す
185
- def render
186
- return self unless @visible
187
- @visibles.each{|name|
188
- @parts[name].render if @parts.has_key?(name)
189
- }
190
- return self
191
- end
192
-
193
- #===オブジェクトを登録する
194
- #オブジェクトをパーツnameとして登録する。
195
- #Yuki::parts[name]で参照可能
196
- #_name_:: パーツ名(シンボル)
197
- #_parts_:: 登録対象のインスタンス
198
- #
199
- #返却値:: 自分自身を返す
200
- def regist_parts(name, parts)
201
- @parts[name] = parts
202
- return self
203
- end
204
-
205
- #===表示・描画対象のテキストボックスを選択する
206
- #_box_:: テキストボックスのインスタンス
207
- #
208
- #返却値:: 自分自身を返す
209
- def select_textbox(box)
210
- @text_box = box
211
- return self
212
- end
213
-
214
- #===表示・描画対象のコマンドボックスを選択する
215
- #_box_:: テキストボックスのインスタンス
216
- #
217
- #返却値:: 自分自身を返す
218
- def select_commandbox(box)
219
- @command_box = box
220
- return self
221
- end
222
-
223
- #===テキストボックスを取得する
224
- #テキストボックスが登録されていないときはnilを返す
225
- #返却値:: テキストボックスのインスタンス
226
- def textbox
227
- return @text_box
228
- end
229
-
230
- #===コマンドボックスを取得する
231
- #コマンドボックスが登録されていないときはnilを返す
232
- #返却値:: コマンドボックスのインスタンス
233
- def commandbox
234
- return @command_box
235
- end
236
-
237
- #===オブジェクトの登録を解除する
238
- #パーツnameとして登録されているオブジェクトを登録から解除する。
239
- #_name_:: パーツ名(シンボル)
240
- #
241
- #返却値:: 自分自身を返す
242
- def remove_parts(name)
243
- @parts.delete(name)
244
- return self
245
- end
246
-
247
- #===パーツで指定したオブジェクトを先頭に表示する
248
- #描画時に、指定したパーツを描画する
249
- #すでにshowメソッドで表示指定している場合は、先頭に表示させる
250
- #_names_:: パーツ名(シンボル)、複数指定可能(指定した順番に描画される)
251
- #返却値:: 自分自身を返す
252
- def show(*names)
253
- names.each{|name|
254
- @visibles.delete(name)
255
- @visibles << name
256
- }
257
- return self
258
- end
259
-
260
- #===パーツで指定したオブジェクトを隠蔽する
261
- #描画時に、指定したパーツを描画させないよう指定する
262
- #_names_:: パーツ名(シンボル)、複数指定可能
263
- #返却値:: 自分自身を返す
264
- def hide(*names)
265
- names.each{|name| @visibles.delete(name) }
266
- return self
267
- end
268
-
269
- #===パーツで指定したオブジェクトの処理を開始する
270
- #nameで指定したパーツが持つ処理を隠蔽する。
271
- #(但し、パーツで指定したオブジェクトがstartメソッドを持つことが条件)
272
- #_name_:: パーツ名(シンボル)
273
- #返却値:: 自分自身を返す
274
- def start(name)
275
- @parts[name].start
276
- return self
277
- end
278
-
279
- #===パーツで指定したオブジェクトを再生する
280
- #nameで指定したパーツを再生する。
281
- #(但し、パーツで指定したオブジェクトがplayメソッドを持つことが条件)
282
- #_name_:: パーツ名(シンボル)
283
- #返却値:: 自分自身を返す
284
- def play(name)
285
- @parts[name].play
286
- return self
287
- end
288
-
289
- #===パーツで指定したオブジェクトの処理を停止する
290
- #nameで指定したパーツが持つ処理を停止する。
291
- #(但し、パーツで指定したオブジェクトがstopメソッドを持つことが条件)
292
- #_name_:: パーツ名(シンボル)
293
- #返却値:: 自分自身を返す
294
- def stop(name)
295
- @parts[name].stop
296
- return self
297
- end
298
-
299
- #===遷移図の処理が終了するまで待つ
300
- #nameで指定した遷移図の処理が終了するまで、プロットを停止する
301
- #_name_: 遷移図名(シンボル)
302
- #返却値:: 自分自身を返す
303
- def wait_by_finish(name)
304
- until @parts[name].finish?
305
- @update_inner.call(self)
306
- end
307
- return self
308
- end
309
-
310
- #===シーンのセットアップ時に実行する処理
311
- #
312
- #ブロック引数として、テキストボックスの変更などの処理をブロック内に記述することが出来る。
313
- #引数の数とブロック引数の数が違っていれば例外が発生する
314
- #_params_:: ブロックに渡す引数リスト
315
- #返却値:: 自分自身を返す
316
- def setup(*params, &proc)
317
- @exec_plot = nil
318
-
319
- @executing = false
320
-
321
- @pausing = false
322
- @selecting = false
323
- @waiting = false
324
-
325
- @pause_release = false
326
- @select_ok = false
327
- @select_cancel = false
328
- @select_amount = [0, 0]
329
- @mouse_amount = nil
330
-
331
- @result = nil
332
- @plot_result = nil
333
-
334
- @now_page = nil
335
- @first_page = nil
336
-
337
- raise MiyakoError, "Aagument count is not same block parameter count!" if proc && proc.arity.abs != params.length
338
- instance_exec(*params, &proc) if block_given?
339
-
340
- return self
341
- end
342
-
343
- #===実行するプロットと登録する
344
- #_plot_proc_:: プロットの実行部をインスタンス化したオブジェクト
345
- #返却値:: 自分自身を返す
346
- def select_plot(plot_proc)
347
- @exec_plot = plot_proc
348
- return self
349
- end
350
-
351
- #===プロット処理を実行する(明示的に呼び出す必要がある場合)
352
- #引数もしくはブロックで指定したプロット処理を非同期に実行する。
353
- #呼び出し可能なプロットは以下の3種類。(上から優先度が高い順)
354
- #プロットが見つからなければ例外が発生する
355
- #
356
- #1)引数prot_proc(Procクラスのインスタンス)
357
- #
358
- #2)引数として渡したブロック
359
- #
360
- #3)select_plotメソッドで登録したブロック(Procクラスのインスタンス)
361
- #
362
- #_plot_proc_:: プロットの実行部をインスタンス化したオブジェクト
363
- #_with_update_input_:: Yuki#updateメソッドを呼び出した時、同時にYuki#update_plot_inputメソッドを呼び出すかどうかを示すフラグ。デフォルトはfalse
364
- #返却値:: 自分自身を返す
365
- def start_plot(plot_proc = nil, with_update_input = true, &plot_block)
366
- raise MiyakoError, "Yuki Error! Textbox is not selected!" unless @text_box
367
- raise MiyakoError, "Yuki Error! Plot must not have any parameters!" if plot_proc && plot_proc.arity != 0
368
- raise MiyakoError, "Yuki Error! Plot must not have any parameters!" if plot_block && plot_block.arity != 0
369
- @with_update_input = with_update_input
370
- @executing_fiber = Fiber.new{ plot_facade(plot_proc, &plot_block) }
371
- @executing_fiber.resume
372
- return self
373
- end
374
-
375
- #===プロット処理を更新する
376
- #ポーズ中、コマンド選択中、 Yuki#wait メソッドによるウェイトの状態確認を行う。
377
- #プロット処理の実行確認は出来ない
378
- def update
379
- return unless @executing
380
- update_plot_input if @with_update_input
381
- pausing if @pausing
382
- selecting if @selecting
383
- waiting if @waiting
384
- @pause_release = false
385
- @select_ok = false
386
- @select_cancel = false
387
- @select_amount = [0, 0]
388
- @executing_fiber.resume
389
- end
390
-
391
- #===プロット用ブロックをYukiへ渡すためのインスタンスを作成する
392
- #プロット用に用意したブロック(ブロック引数無し)を、Yukiでの選択結果や移動先として利用できる
393
- #インスタンスに変換する
394
- #返却値:: ブロックをオブジェクトに変換したものを返す
395
- def to_plot(&plot)
396
- return plot
397
- end
398
-
399
- #===プロット処理に使用する入力情報を更新する
400
- #ポーズ中、コマンド選択中に使用する入力デバイスの押下状態を更新する
401
- #(但し、プロット処理の実行中にのみ更新する)
402
- #Yuki#update メソッドをそのまま使う場合は呼び出す必要がないが、 Yuki#exec_plot メソッドを呼び出す
403
- #プロット処理の場合は、メインスレッドから明示的に呼び出す必要がある
404
- #返却値:: nil を返す
405
- def update_plot_input
406
- return nil unless @executing
407
- if @pausing && @release_checks.inject(false){|r, c| r |= c.call }
408
- @pause_release = true
409
- elsif @selecting
410
- @select_ok = true if @ok_checks.inject(false){|r, c| r |= c.call }
411
- @select_cancel = true if @cancel_checks.inject(false){|r, c| r |= c.call }
412
- @select_amount = @key_amount_proc.call
413
- @mouse_amount = @mouse_amount_proc.call
414
- end
415
- return nil
416
- end
417
-
418
- def plot_facade(plot_proc = nil, &plot_block) #:nodoc:
419
- @plot_result = nil
420
- @executing = true
421
- exec_plot = @exec_plot
422
- @plot_result = plot_proc ? self.instance_exec(&plot_proc) :
423
- block_given? ? self.instance_exec(&plot_block) :
424
- exec_plot ? self.instance_exec(&exec_plot) :
425
- raise(MiyakoError, "Cannot find plot!")
426
- @executing = false
427
- end
428
-
429
- #===プロット処理中に別のプロットを呼び出す
430
- #呼び出し可能なプロットは以下の2種類。(上から優先度が高い順)
431
- #
432
- #1)引数prot_proc(Procクラスのインスタンス)
433
- #
434
- #2)引数として渡したブロック
435
- #
436
- #_plot_proc_:: プロットの実行部をインスタンス化したオブジェクト
437
- #返却値:: プロットの実行結果を返す
438
- def call_plot(plot_proc = nil, &plot_block)
439
- return plot_proc ? self.instance_exec(&plot_proc) :
440
- self.instance_exec(&plot_block)
441
- end
442
-
443
- #===プロット処理が実行中かどうかを確認する
444
- #返却値:: プロット処理実行中の時はtrueを返す
445
- def executing?
446
- return @executing
447
- end
448
-
449
- #===ポーズ解除問い合わせメソッド配列を初期状態に戻す
450
- #返却値:: 自分自身を返す
451
- def reset_release_checks
452
- @release_checks = @release_checks_default.dup
453
- return self
454
- end
455
-
456
- #===コマンド選択決定問い合わせメソッド配列を初期状態に戻す
457
- #返却値:: 自分自身を返す
458
- def reset_ok_checks
459
- @ok_checks = @ok_checks_default.dup
460
- return self
461
- end
462
-
463
- #===コマンド選択キャンセル問い合わせメソッド配列を初期状態に戻す
464
- #返却値:: 自分自身を返す
465
- def reset_cancel_checks
466
- @cancel_checks = @cancel_checks_default.dup
467
- return self
468
- end
469
-
470
- #===ポーズ前後処理メソッド配列を初期状態に戻す
471
- #pre_pause/post_pauseの処理を初期状態([])に戻す
472
- #返却値:: 自分自身を返す
473
- def reset_pre_post_release
474
- @pre_pause = []
475
- @post_pause = []
476
- return self
477
- end
478
-
479
- #===コマンド選択前後処理メソッド配列を初期状態に戻す
480
- #pre_command/post_commandの処理を初期状態([])に戻す
481
- #返却値:: 自分自身を返す
482
- def reset_pre_post_command
483
- @pre_command = []
484
- @post_command = []
485
- return self
486
- end
487
-
488
- #===コマンド選択キャンセル前後処理メソッド配列を初期状態に戻す
489
- #pre_cancel/post_cancelの処理を初期状態([])に戻す
490
- #返却値:: 自分自身を返す
491
- def reset_pre_post_cancel
492
- @pre_acncel = []
493
- @post_cancel = []
494
- return self
495
- end
496
-
497
- #===ブロック評価中、ポーズ解除問い合わせメソッド配列を置き換える
498
- #同時に、ポーズ時処理(Yuki#pre_pause)、ポーズ解除時処理(Yuki#post_pause)を引数で設定できる。
499
- #ブロックの評価が終われば、メソッド配列・ポーズ時処理・ポーズ解除時処理を元に戻す
500
- #procs:: 置き換えるメソッド配列(callメソッドを持ち、true/falseを返すメソッドの配列)
501
- #pre_proc:: ポーズ開始時に実行させるProc(デフォルトは[](何もしない))
502
- #post_proc:: ポーズ解除時に実行させるProc(デフォルトは[](何もしない))
503
- #返却値:: 自分自身を返す
504
- def release_checks_during(procs, pre_procs = [], post_procs = [])
505
- raise MiyakoError, "Can't find block!" unless block_given?
506
- backup = [@release_checks, @pre_pause, @post_pause]
507
- @release_checks, @pre_pause, @post_pause = procs, pre_proc, post_proc
508
- yield
509
- @release_checks, @pre_pause, @post_pause = backup.pop(3)
510
- return self
511
- end
512
-
513
- #===ブロック評価中、コマンド選択決定問い合わせメソッド配列を置き換える
514
- #同時に、コマンド選択開始時処理(Yuki#pre_command)、コマンド選択終了時処理(Yuki#post_command)を引数で設定できる。
515
- #ブロックの評価が終われば、メソッド配列・コマンド選択開始時処理・コマンド選択終了時処理を元に戻す
516
- #procs:: 置き換えるメソッド配列(callメソッドを持ち、true/falseを返すメソッドの配列)
517
- #pre_proc:: コマンド選択開始時に実行させるProc(デフォルトは[](何もしない))
518
- #post_proc:: コマンド選択決定時に実行させるProc(デフォルトは[](何もしない))
519
- #返却値:: 自分自身を返す
520
- def ok_checks_during(procs, pre_procs = [], post_procs = [])
521
- raise MiyakoError, "Can't find block!" unless block_given?
522
- backup = [@ok_checks, @pre_command, @post_command]
523
- @ok_checks, @pre_command, @post_command = procs, pre_proc, post_proc
524
- yield
525
- @ok_checks, @pre_command, @post_command = backup.pop(3)
526
- return self
527
- end
528
-
529
- #===ブロック評価中、コマンド選択キャンセル問い合わせメソッド配列を置き換える
530
- #同時に、コマンド選択開始時処理(Yuki#pre_cancel)、コマンド選択終了時処理(Yuki#post_cancel)を引数で設定できる。
531
- #ブロックの評価が終われば、メソッド配列・コマンド選択開始時処理・コマンド選択終了時処理を元に戻す
532
- #procs:: 置き換えるメソッド配列(callメソッドを持ち、true/falseを返すメソッドの配列)
533
- #pre_proc:: コマンド選択開始時に実行させるProc(デフォルトは[](何もしない))
534
- #post_proc:: コマンド選択キャンセル時に実行させるProc(デフォルトは[](何もしない))
535
- #返却値:: 自分自身を返す
536
- def cancel_checks_during(procs, pre_procs = [], post_procs = [])
537
- raise MiyakoError, "Can't find block!" unless block_given?
538
- backup = [@cancel_checks, @pre_cancel, @post_cancel]
539
- @cancel_checks, @pre_cancel, @post_cancel = procs, pre_proc, post_proc
540
- yield
541
- @cancel_checks, @pre_cancel, @post_cancel = backup.pop(3)
542
- return self
543
- end
544
-
545
- #===プロットの処理結果を返す
546
- #プロット処理の結果を返す。
547
- #まだ結果が得られていない場合はnilを得る
548
- #プロット処理が終了していないのに結果を得られるので注意!
549
- #返却値:: プロットの処理結果
550
- def result
551
- return @plot_result
552
- end
553
-
554
- #===プロット処理の結果を設定する
555
- #_ret_:: 設定する結果。デフォルトはnil
556
- #返却値:: 自分自身を返す
557
- def result=(ret = nil)
558
- @plot_result = ret
559
- return self
560
- end
561
-
562
- #===結果がシーンかどうかを問い合わせる
563
- #結果がシーン(シーンクラス名)のときはtrueを返す
564
- #対象の結果は、選択結果、プロット処理結果ともに有効
565
- #返却値:: 結果がシーンかどうか(true/false)
566
- def is_scene?(result)
567
- return (result.class == Class && result.include?(Story::Scene))
568
- end
569
-
570
- #===結果がシナリオかどうかを問い合わせる
571
- #結果がシナリオ(メソッド)のときはtrueを返す
572
- #対象の結果は、選択結果、プロット処理結果ともに有効
573
- #返却値:: 結果がシナリオかどうか(true/false)
574
- def is_scenario?(result)
575
- return (result.kind_of?(Proc) || result.kind_of?(Method))
576
- end
577
-
578
- #===コマンド選択がキャンセルされたときの結果を返す
579
- #返却値:: キャンセルされたときはtrue、されていないときはfalseを返す
580
- def canceled?
581
- return result == @cancel
582
- end
583
-
584
- #===ブロックを条件として設定する
585
- #メソッドをMethodクラスのインスタンスに変換する
586
- #_block_:: シナリオインスタンスに変換したいメソッド名(シンボル)
587
- #返却値:: シナリオインスタンスに変換したメソッド
588
- def condition(&block)
589
- return block
590
- end
591
-
592
- #===コマンド選択中の問い合わせメソッド
593
- #返却値:: コマンド選択中の時はtrueを返す
594
- def selecting?
595
- return @selecting
596
- end
597
-
598
- #===Yuki#waitメソッドによる処理待ちの問い合わせメソッド
599
- #返却値:: 処理待ちの時はtrueを返す
600
- def waiting?
601
- return @waiting
602
- end
603
-
604
- #===メッセージ送り待ちの問い合わせメソッド
605
- #返却値:: メッセージ送り待ちの時はtrueを返す
606
- def pausing?
607
- return @pausing
608
- end
609
-
610
- #===条件に合っていればポーズをかける
611
- #引数で設定した条件(Proc,メソッドインスタンス,ブロック)を評価した結果、trueのときはポーズを行い、
612
- #condの値がnilで、ブロックが渡されていないときは何もしない
613
- #falseのときは改行してプロットの処理を継続する
614
- #_cond_:: 条件を示すオブジェクト(返却値はtrue/false)。デフォルトはnil(渡されたブロックを評価する)
615
- #返却値:: 自分自身を返す
616
- def wait_by_cond(cond = nil)
617
- return yield ? pause_and_clear : cr if block_given?
618
- return cond.call ? pause_and_clear : cr if cond
619
- return self
620
- end
621
-
622
- #===テキストボックスに文字を表示する方法を指定する
623
- #引数に、:charを渡すと1文字ごと、:stringを渡すと文字列ごとに表示される。それ以外を指定したときは例外が発生
624
- #ブロックを渡せば、ブロックの評価中のみ設定が有効になる。
625
- #ブロック評価終了後、呼び出し前の設定に戻る
626
- #_mode_:: テキストの表示方法。:charのときは文字ごと、:stringのときは文字列ごとに表示される。それ以外を指定したときは例外が発生
627
- #返却値:: 自分自身を返す
628
- def text_method(mode)
629
- raise MiyakoError, "undefined text_mode! #{mode}" unless [:char,:string].include?(mode)
630
- backup = @text_method_name
631
- @text_method_name = mode
632
- if block_given?
633
- yield
634
- @text_method_name = backup
635
- end
636
- return self
637
- end
638
-
639
- #===テキストボックスに文字を表示する
640
- #テキストボックスとして用意している画像に文字を描画する。
641
- #描画する単位(文字単位、文字列単位)によって、挙動が違う。
642
- #(文字単位の時)
643
- #Yuki#text_by_charメソッドと同じ挙動。
644
- #(文字列単位の時)
645
- #Yuki#text_by_strメソッドと同じ挙動。
646
- #デフォルトは文字単位。
647
- #引数txtの値は、内部で1文字ずつ分割され、1文字描画されるごとに、
648
- #update_textメソッドが呼び出され、続けてYuki#start_plotもしくはYuki#updateメソッド呼び出し直後に戻る
649
- #_txt_:: 表示させるテキスト
650
- #返却値:: 自分自身を返す
651
- def text(txt)
652
- return self if txt.eql?(self)
653
- return self if txt.empty?
654
- return @text_methods[@text_method_name].call(txt)
655
- end
656
-
657
- #===テキストボックスに文字を1文字ずつ表示する
658
- #引数txtの値は、内部で1文字ずつ分割され、1文字描画されるごとに、
659
- #update_textメソッドが呼び出され、続けてYuki#start_plotもしくはYuki#updateメソッド呼び出し直後に戻る
660
- #注意として、改行が文字列中にあれば改行、タブやフィードが文字列中にあれば、nilを返す。
661
- #_txt_:: 表示させるテキスト
662
- #返却値:: 自分自身を返す
663
- def text_by_char(txt)
664
- return self if txt.eql?(self)
665
- txt.chars{|ch|
666
- if /[\n\r]/.match(ch)
667
- next wait_by_cond(@is_outer_height)
668
- elsif @text_box.locate.x + @text_box.font.text_size(ch)[0] >= @text_box.textarea.w
669
- wait_by_cond(@is_outer_height)
670
- elsif /[\t\f]/.match(ch)
671
- next nil
672
- end
673
- @text_box.draw_text(ch)
674
- @update_text.call(self, ch)
675
- Fiber.yield
676
- }
677
- return self
678
- end
679
-
680
- #===テキストボックスに文字を表示する
681
- #文字列が描画されるごとに、update_textメソッドが呼び出され、
682
- #続けてYuki#start_plotもしくはYuki#updateメソッド呼び出し直後に戻る
683
- #注意として、改行が文字列中にあれば改行、タブやフィードが文字列中にあれば、nilを返す。
684
- #_txt_:: 表示させるテキスト
685
- #返却値:: 自分自身を返す
686
- def text_by_str(txt)
687
- return self if txt.eql?(self)
688
- use_cr = false
689
- until txt.empty? do
690
- if /[\n\r]/.match(txt)
691
- tmp = Regexp.last_match.pre_match
692
- txt = Regexp.last_match.post_match
693
- use_cr = true
694
- elsif @text_box.locate.x + @text_box.font.text_size(txt)[0] >= @text_box.textarea.w
695
- w = (@text_box.textarea.w - @text_box.locate.x) / @text_box.font.size
696
- tmp = txt.slice!(0,w)
697
- use_cr = true
698
- elsif /[\t\f]/.match(txt)
699
- next nil
700
- else
701
- tmp = txt
702
- txt = ""
703
- end
704
- @text_box.draw_text(tmp)
705
- self.cr if use_cr
706
- @update_text.call(self, tmp)
707
- Fiber.yield
708
- use_cr = false
709
- end
710
- return self
711
- end
712
-
713
- def is_outer_height #:nodoc:
714
- return @text_box.locate.y + @text_box.max_height >= @text_box.textarea.h
715
- end
716
-
717
- private :is_outer_height
718
-
719
- #===文字色を変更する
720
- #ブロック内で指定した文字列を、指定の色で描画する
721
- #_color_:: 文字色
722
- #返却値:: 自分自身を返す
723
- def color(color, &block)
724
- @text_box.color_during(Color.to_rgb(color)){ text block.call }
725
- return self
726
- end
727
-
728
- #===ブロック評価中、行中の表示位置を変更する
729
- #ブロックを評価している間だけ、デフォルトの縦の表示位置を変更する
730
- #変更できる値は、:top、:middle、:bottomの3種類。
731
- #ブロックを渡していないときはエラーを返す
732
- #_valign_:: 文字の縦の位置(top, middle, bottom)
733
- #返却値:: 自分自身を返す
734
- def valign_during(valign)
735
- raise MiyakoError, "Can't find block!" unless block_given?
736
- oalign, @valign = @valign, valign
737
- yield
738
- @valign = oalign
739
- return self
740
- end
741
-
742
- #===文字の大きさを変更する
743
- #ブロック内で指定した文字列を、指定の大きさで描画する
744
- #_size_:: 文字の大きさ(整数)
745
- #_valign_:: 文字の縦の位置(top, middle, bottom)。デフォルトは:middle(Yuki#valign=,Yuki#valign_duringで変更可能)
746
- #返却値:: 自分自身を返す
747
- def size(size, valign = @valign, &block)
748
- @text_box.font_size_during(size){
749
- @text_box.margin_during(@text_box.margin_height(valign)){ text block.call }
750
- }
751
- return self
752
- end
753
-
754
- #===太文字を描画する
755
- #ブロック内で指定した文字列を太文字で表示する
756
- #(使用すると文字の端が切れてしまう場合あり!)
757
- #返却値:: 自分自身を返す
758
- def bold(&block)
759
- @text_box.font_bold{ text block.call }
760
- return self
761
- end
762
-
763
- #===斜体文字を描画する
764
- #ブロック内で指定した文字列を斜体で表示する
765
- #(使用すると文字の端が切れてしまう場合あり!)
766
- #返却値:: 自分自身を返す
767
- def italic(&block)
768
- @text_box.font_italic{ text block.call }
769
- return self
770
- end
771
-
772
- #===下線付き文字を描画する
773
- #ブロック内で指定した文字列を下線付きで表示する
774
- #返却値:: 自分自身を返す
775
- def under_line(&block)
776
- @text_box.font_under_line{ text block.call }
777
- return self
778
- end
779
-
780
- #===改行を行う
781
- #開業後にupdate_crテンプレートメソッドが1回呼ばれる
782
- #_tm_:: 改行回数。デフォルトは1
783
- #返却値:: 自分自身を返す
784
- def cr(tm = 1)
785
- tm.times{|n|
786
- @text_box.cr
787
- @update_cr.call(self)
788
- }
789
- return self
790
- end
791
-
792
- #===テキストボックスの内容を消去する
793
- #開業後にupdate_clearテンプレートメソッドが1回呼ばれる
794
- #返却値:: 自分自身を返す
795
- def clear
796
- @text_box.clear
797
- @update_clear.call(self)
798
- return self
799
- end
800
-
801
- #===ポーズを行う
802
- #ポーズが行われると、ポーズ用のカーソルが表示される
803
- #所定のボタンを押すとポーズが解除され、カーソルが消える
804
- #解除後は、プロットの続きを処理する
805
- #引数無しのブロックを渡せば、ポーズ開始前に行いたい処理を施すことが出来る
806
- #ポーズ中、update_innerメソッドを呼び出し、続けて、処理をYuki#startもしくはYuki#update呼び出し直後に戻す
807
- #Yuki#updateが呼び出されてもポーズ中の場合は、再び上記の処理を繰り返す
808
- #(たとえば、一定時間後に自動的にポーズ解除する場合、そのタイマーを開始させるなど)
809
- #返却値:: 自分自身を返す
810
- def pause
811
- @pre_pause.each{|proc| proc.call}
812
- yield if block_given?
813
- @text_box.pause
814
- @pausing = true
815
- while @pausing
816
- @update_inner.call(self)
817
- Fiber.yield
818
- end
819
- @post_pause.each{|proc| proc.call}
820
- return self
821
- end
822
-
823
- def pausing #:nodoc:
824
- return unless @pause_release
825
- @text_box.release
826
- @pausing = false
827
- @pause_release = false
828
- end
829
-
830
- #===ポーズをかけて、テキストボックスの内容を消去する
831
- #ポーズをかけ、ポーズを解除するときにテキストボックスの内容を消去する
832
- #返却値:: 自分自身を返す
833
- def pause_and_clear
834
- return pause.clear
835
- end
836
-
837
- #===コマンドを表示する
838
- #表示対象のコマンド群をCommand構造体の配列で示す。
839
- #キャンセルのときの結果も指定可能(既定ではキャンセル不可状態)
840
- #body_selectedをnilにした場合は、bodyと同一となる
841
- #body_selectedを文字列を指定した場合は、文字色が赤色になることに注意
842
- #引数無しのブロックを渡せば、コマンド選択開始前に、決定判別・キャンセル判別に必要な前処理を施すことが出来る
843
- #選択中、update_innerメソッドを呼び出し、続けて、処理をYuki#startもしくはYuki#update呼び出し直後に戻す
844
- #Yuki#updateが呼び出されても選択中の場合は、再び上記の処理を繰り返す
845
- #_command_list_:: 表示するコマンド群。各要素はCommand構造体の配列
846
- #_cancel_to_:: キャンセルボタンを押したときの結果。デフォルトはnil(キャンセル無効)
847
- #_chain_block_:: コマンドの表示方法。TextBox#create_choices_chainメソッド参照
848
- #返却値:: 自分自身を返す
849
- def command(command_list, cancel_to = Canceled, &chain_block)
850
- raise MiyakoError, "Yuki Error! Commandbox is not selected!" unless @command_box
851
- @cancel = cancel_to
852
-
853
- choices = []
854
- command_list.each{|cm|
855
- if (cm[:condition] == nil || cm[:condition].call)
856
- cm_array = [cm[:body], cm[:body_selected], cm[:result]]
857
- methods = cm.methods
858
- cm_array << (methods.include?(:end_select_proc) ? cm[:end_select_proc] : nil)
859
- choices.push(cm_array)
860
- end
861
- }
862
- return self if choices.length == 0
863
-
864
- @pre_command.each{|proc| proc.call}
865
- @pre_cancel.each{|proc| proc.call}
866
- yield if block_given?
867
- @command_box.command(@command_box.create_choices_chain(choices, &chain_block))
868
- @result = nil
869
- @selecting = true
870
- while @selecting
871
- @update_inner.call(self)
872
- Fiber.yield
873
- end
874
- @post_cancel.each{|proc| proc.call}
875
- @post_command.each{|proc| proc.call}
876
- return self
877
- end
878
-
879
- def selecting #:nodoc:
880
- return unless @selecting
881
- return unless @command_box.selecting?
882
- @selecting_procs.each{|sp|
883
- sp.call(@select_ok, @select_cansel, @select_amount, @mouse_amount)
884
- }
885
- if @select_ok
886
- @result = @command_box.result
887
- @command_box.finish_command
888
- @text_box.release
889
- @selecting = false
890
- reset_selecting
891
- elsif @select_cancel
892
- @result = @cancel
893
- @command_box.finish_command
894
- @text_box.release
895
- @selecting = false
896
- reset_selecting
897
- elsif @select_amount != [0,0]
898
- @command_box.move_cursor(*@select_amount)
899
- reset_selecting
900
- elsif @mouse_amount
901
- @command_box.attach_cursor(*@mouse_amount.to_a)
902
- reset_selecting
903
- end
904
- end
905
-
906
- def reset_selecting #:nodoc:
907
- @select_ok = false
908
- @select_cancel = false
909
- @select_amount = [0, 0]
910
- end
911
-
912
- #===コマンドの選択結果を返す
913
- #コマンド選択の結果を返す。
914
- #まだ結果が得られていない場合はnilを得る
915
- #プロット処理・コマンド選択が終了していないのに結果を得られるので注意!
916
- #返却値:: コマンドの選択結果
917
- def select_result
918
- return @result
919
- end
920
-
921
- #===プロットの処理を待機する
922
- #指定の秒数(少数可)、プロットの処理を待機する。
923
- #待機中、update_innerメソッドを呼び出し、続けて、処理をYuki#startもしくはYuki#update呼び出し直後に戻す
924
- #Yuki#updateが呼び出されても待機中の場合は、再び上記の処理を繰り返す
925
- #_length_:: 待機する長さ。単位は秒。少数可。
926
- #返却値:: 自分自身を返す
927
- def wait(length)
928
- @waiting_timer = WaitCounter.new(length)
929
- @waiting_timer.start
930
- @waiting = true
931
- while @waiting
932
- @update_inner.call(self)
933
- Fiber.yield
934
- end
935
- return self
936
- end
937
-
938
- def waiting #:nodoc:
939
- return if @waiting_timer.waiting?
940
- @waiting = false
941
- end
942
-
943
- #===シナリオ上の括り(ページ)を実装する
944
- #シナリオ上、「このプロットの明示的な範囲」を示すために使用する(セーブ時の再現位置の指定など)
945
- #Yuki#select_first_pageメソッドで開始位置が指定されている場合、以下の処理を行う。
946
- #(1)select_first_pageメソッドで指定されたページから処理する。それまでのページは無視される
947
- #(2)開始ページを処理する前に、select_first_pageメソッドの内容をクリアする(nilに変更する)
948
- #このメソッドはブロックが必須。ブロックがないと例外が発生する。
949
- #_name_:: ページ名。select_first_pageメソッドは、この名前を検索する。また、now_pageメソッドの返却値でもある
950
- #_use_pause_::ページの処理が終了した後、必ずpauseメソッドを呼び出すかどうかのフラグ。デフォルトはtrue
951
- #返却値:: select_first_pageメソッドで指定されていないページのときはnil、指定されているページの場合は引数nameの値
952
- def page(name, use_pause = true)
953
- raise MiyakoError, "Yuki#page needs block!" unless block_given?
954
- return nil if (@first_page && name != @first_page)
955
- @first_page = nil
956
- @now_page = name
957
- yield
958
- pause if use_pause
959
- @now_page = nil
960
- return name
961
- end
962
-
963
- #===シナリオ上の現在のページを返す
964
- #呼び出し当時、シナリオ上、pageメソッドでくくられていない場合は、nilを返す
965
- #返却値:: ページ名
966
- def now_page
967
- return @now_page
968
- end
969
-
970
- #===プロット上の最初に実行するページを指定知る
971
- #但し、ページ名を指定しないときはnilを指定する。
972
- #_name_:: 最初に実行するページ名
973
- def select_first_page(name)
974
- @first_page = name
975
- end
976
-
977
- #===インスタンスで使用しているオブジェクトを解放する
978
- def dispose
979
- @update_inner = nil
980
- @update_text = nil
981
- @update_cr = nil
982
- @update_clear = nil
983
-
984
- @executing_fiber = nil
985
-
986
- @parts.clear
987
- @parts = nil
988
- @visibles.clear
989
- @visibles = nil
990
- @vars.clear
991
- @vars = nil
992
-
993
- @is_outer_height = nil
994
- end
995
- end
996
- end
1
+ # -*- encoding: utf-8 -*-
2
+ =begin
3
+ --
4
+ Miyako v2.1
5
+ Copyright (C) 2007-2009 Cyross Makoto
6
+
7
+ This library is free software; you can redistribute it and/or
8
+ modify it under the terms of the GNU Lesser General Public
9
+ License as published by the Free Software Foundation; either
10
+ version 2.1 of the License, or (at your option) any later version.
11
+
12
+ This library is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General Public
18
+ License along with this library; if not, write to the Free Software
19
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ ++
21
+ =end
22
+
23
+ #lambdaの別名として、yuki_plotメソッドを追加
24
+ alias :yuki_plot :lambda
25
+
26
+ #=シナリオ言語Yuki実装モジュール
27
+ module Miyako
28
+
29
+ #==Yuki本体クラス
30
+ #Yukiの内容をオブジェクト化したクラス
31
+ #Yukiのプロット処理を外部メソッドで管理可能
32
+ #プロットは、引数を一つ(Yuki2クラスのインスタンス)を取ったメソッドもしくはブロック
33
+ #として記述する。
34
+ class Yuki
35
+ include SpriteBase
36
+ include Animation
37
+
38
+ #==キャンセルを示す構造体
39
+ #コマンド選択がキャンセルされたときに生成される構造体
40
+ Canceled = Struct.new(:dummy)
41
+
42
+ #==コマンド構造体
43
+ #_body_:: コマンドの名称(移動する、調べるなど、アイコンなどの画像も可)
44
+ #_body_selected_:: 選択時コマンドの名称(移動する、調べるなど、アイコンなどの画像も可)(省略時は、bodyと同一)
45
+ #_condition_:: 表示条件(ブロック)。評価の結果、trueのときのみ表示
46
+ #_result_:: 選択結果(移動先シーンクラス名、シナリオ(メソッド)名他のオブジェクト)
47
+ Command = Struct.new(:body, :body_selected, :condition, :result)
48
+
49
+ #==コマンド構造体
50
+ #_body_:: コマンドの名称(移動する、調べるなど、アイコンなどの画像も可)
51
+ #_body_selected_:: 選択時コマンドの名称(移動する、調べるなど、アイコンなどの画像も可)(省略時は、bodyと同一)
52
+ #_condition_:: 表示条件(ブロック)。評価の結果、trueのときのみ表示
53
+ #_result_:: 選択結果(移動先シーンクラス名、シナリオ(メソッド)名他のオブジェクト)
54
+ #_end_select_proc_:: この選択肢を選択したときに優先的に処理するブロック。
55
+ #ブロックは1つの引数を取る(コマンド選択テキストボックス))。デフォルトはnil
56
+ CommandEX = Struct.new(:body, :body_selected, :condition, :result, :end_select_proc)
57
+
58
+ #===Yuki#update実行中に行わせる処理を実装するテンプレートメソッド
59
+ #但し、メソッド本体は、update_inner=メソッドで設定する必要がある
60
+ #_yuki_:: 実行中のYukiクラスインスタンス
61
+ def update_inner(yuki)
62
+ end
63
+
64
+ #===Yuki#text実行中に行わせる処理を実装するテンプレートメソッド
65
+ #update_textテンプレートメソッドは、textメソッドで渡した文字列全体ではなく、
66
+ #内部で1文字ずつ分割して、その字が処理されるごとに呼ばれる。
67
+ #そのため、引数chで入ってくるのは、分割された1文字となる。
68
+ #但し、メソッド本体は、update_text=メソッドで設定する必要がある
69
+ #_yuki_:: 実行中のYukiクラスインスタンス
70
+ #_ch_:: textメソッドで処理中の文字(分割済みの1文字)
71
+ def update_text(yuki, ch)
72
+ end
73
+
74
+ #===Yuki#cr呼び出し時に行わせる処理を実装するテンプレートメソッド
75
+ #但し、メソッド本体は、update_cr=メソッドで設定する必要がある
76
+ #_yuki_:: 実行中のYukiクラスインスタンス
77
+ def update_cr(yuki)
78
+ end
79
+
80
+ #===Yuki#clear呼び出し時に行わせる処理を実装するテンプレートメソッド
81
+ #但し、メソッド本体は、update_clear=メソッドで設定する必要がある
82
+ #_yuki_:: 実行中のYukiクラスインスタンス
83
+ def update_clear(yuki)
84
+ end
85
+
86
+ attr_accessor :visible
87
+ attr_accessor :update_inner, :update_text, :update_cr, :update_clear
88
+ attr_reader :valign
89
+ #release_checks:: ポーズ解除を問い合わせるブロックの配列。
90
+ #callメソッドを持ち、true/falseを返すインスタンスを配列操作で追加・削除できる。
91
+ #ok_checks:: コマンド選択決定を問い合わせるブロックの配列。
92
+ #callメソッドを持ち、true/falseを返すインスタンスを配列操作で追加・削除できる。
93
+ #cancel_checks:: コマンド選択解除(キャンセル)を問い合わせるブロックの配列。
94
+ #callメソッドを持ち、true/falseを返すインスタンスを配列操作で追加・削除できる。
95
+ attr_reader :release_checks, :ok_checks, :cancel_checks
96
+ attr_reader :pre_pause, :pre_command, :pre_cancel, :post_pause, :post_command, :post_cancel
97
+ #selecting_procs:: コマンド選択時に行うブロックの配列。
98
+ #ブロックは4つの引数を取る必要がある。
99
+ #(1)コマンド決定ボタンを押した?(true/false)
100
+ #(2)キャンセルボタンを押した?(true/false)
101
+ #(3)キーパッドの移動量を示す配列([dx,dy])
102
+ #(4)マウスの位置を示す配列([x,y])
103
+ #callメソッドを持つブロックが使用可能。
104
+ attr_reader :selecting_procs
105
+
106
+ #===Yukiにメソッドを追加する
107
+ #ブロックを渡すことで、Yukiに新しいメソッドを追加できる。
108
+ #コンテキストはYukiクラスのインスタンスとなるため、Yukiスクリプトと同じ感覚でメソッドを追加できる。
109
+ #ただし、すでに追加したメソッド(もしくはYukiクラスですでに追加されているメソッド)を追加しようとすると例外が発生する
110
+ #
111
+ #_name_:: ブロックに渡す引数リスト
112
+ #_block_:: メソッドとして実行させるブロック
113
+ def Yuki.add_method(name, &block)
114
+ name = name.to_sym
115
+ raise MiyakoError, "Already added method! : #{name.to_s}" if self.methods.include?(name)
116
+ define_method(name, block)
117
+ return nil
118
+ end
119
+
120
+ #===Yukiを初期化する
121
+ #
122
+ #ブロック引数として、テキストボックスの変更などの処理をブロック内に記述することが出来る。
123
+ #引数の数とブロック引数の数が違っていれば例外が発生する
124
+ #_params_:: ブロックに渡す引数リスト(ただし、ブロックを渡しているときのみに有効)
125
+ def initialize(*params, &proc)
126
+ @yuki = { }
127
+ @over_yuki = nil
128
+ @over_exec = false
129
+ @text_box = nil
130
+ @command_box = nil
131
+
132
+ @executing = false
133
+
134
+ @exec_plot = nil
135
+
136
+ @pausing = false
137
+ @selecting = false
138
+ @waiting = false
139
+
140
+ @pause_release = false
141
+ @select_ok = false
142
+ @select_cancel = false
143
+ @select_amount = [0, 0]
144
+ @mouse_amount = nil
145
+
146
+ @result = nil
147
+ @plot_result = nil
148
+
149
+ @update_inner = lambda{|yuki|}
150
+ @update_text = lambda{|yuki, ch|}
151
+ @update_cr = lambda{|yuki|}
152
+ @update_clear = lambda{|yuki|}
153
+
154
+ @parts = {}
155
+ @visibles = SpriteList.new
156
+ @vars = {}
157
+ @visible = true
158
+
159
+ @executing_fiber = nil
160
+
161
+ @text_methods = {:char => self.method(:text_by_char),
162
+ :string => self.method(:text_by_str) }
163
+ @text_method_name = :char
164
+
165
+ @valign = :middle
166
+
167
+ @release_checks_default = [lambda{ Input.pushed_any?(:btn1, :spc) }, lambda{ Input.click?(:left) } ]
168
+ @release_checks = @release_checks_default.dup
169
+
170
+ @ok_checks_default = [lambda{ Input.pushed_any?(:btn1, :spc) },
171
+ lambda{ self.commandbox.attach_any_command?(*Input.get_mouse_position) && Input.click?(:left) } ]
172
+ @ok_checks = @ok_checks_default.dup
173
+
174
+ @cancel_checks_default = [lambda{ Input.pushed_any?(:btn2, :esc) },
175
+ lambda{ Input.click?(:right) } ]
176
+ @cancel_checks = @cancel_checks_default.dup
177
+
178
+ @key_amount_proc = lambda{ Input.pushed_amount }
179
+ @mouse_amount_proc = lambda{ Input.mouse_cursor_inner? ? Input.get_mouse_position : nil }
180
+
181
+ @pre_pause = []
182
+ @pre_command = []
183
+ @pre_cancel = []
184
+ @post_pause = []
185
+ @post_command = []
186
+ @post_cancel = []
187
+ @selecting_procs = []
188
+
189
+ @is_outer_height = self.method(:is_outer_height)
190
+
191
+ @now_page = nil
192
+ @first_page = nil
193
+
194
+ raise MiyakoProcError, "Aagument count is not same block parameter count!" if proc && proc.arity.abs != params.length
195
+ instance_exec(*params, &proc) if block_given?
196
+ end
197
+
198
+ def initialize_copy(obj) #:nodoc:
199
+ @yuki = @yuki.dup
200
+ @over_exec = false
201
+ @text_box = @text_box.dup
202
+ @command_box = @command_box.dup
203
+
204
+ @exec_plot = @exec_plot.dup
205
+
206
+ @select_amount = @select_amount.dup
207
+ @mouse_amount = @mouse_amount.dup
208
+
209
+ @result = @result.dup
210
+ @plot_result = @plot_result.dup
211
+
212
+ @update_inner = @update_inner.dup
213
+ @update_text = @update_text.dup
214
+ @update_cr = @update_cr.dup
215
+ @update_clear = @update_clear.dup
216
+
217
+ @parts = @parts.deep_dup
218
+ @visibles = @visibles.deep_dup
219
+ @vars = @vars.deep_dup
220
+
221
+ @executing_fiber = @executing_fiber.dup
222
+
223
+ @text_methods = @text_methods.dup
224
+
225
+ @release_checks = @release_checks.dup
226
+
227
+ @ok_checks = @ok_checks.dup
228
+
229
+ @cancel_checks = @cancel_checks.dup
230
+
231
+ @key_amount_proc = @key_amount_proc.dup
232
+ @mouse_amount_proc = @mouse_amount_proc.dup
233
+
234
+ @pre_pause = @pre_pause.dup
235
+ @pre_command = @pre_command.dup
236
+ @pre_cancel = @pre_cancel.dup
237
+ @post_pause = @post_pause.dup
238
+ @post_command = @post_command.dup
239
+ @post_cancel = @post_cancel.dup
240
+ @selecting_procs = @selecting_procs.dup
241
+
242
+ @is_outer_height = @is_outer_height.dup
243
+
244
+ @now_page = @now_page.dup
245
+ @first_page = @first_page.dup.dup
246
+ end
247
+
248
+ #===Yuki#showで表示指定した画像を描画する
249
+ #描画順は、showメソッドで指定した順に描画される(先に指定した画像は後ろに表示される)
250
+ #なお、visibleの値がfalseの時は描画されない。
251
+ #返却値:: 自分自身を返す
252
+ def render
253
+ @visibles.render if @visible
254
+ @over_yuki.render if @over_yuki && @over_yuki.executing?
255
+ return self
256
+ end
257
+
258
+ #===Yuki#showで表示指定した画像を描画する
259
+ #描画順は、showメソッドで指定した順に描画される(先に指定した画像は後ろに表示される)
260
+ #なお、visibleの値がfalseの時は描画されない。
261
+ #返却値:: 自分自身を返す
262
+ def render_to(dst)
263
+ @visibles.render_to(dst) if @visible
264
+ @over_yuki.render_to(dst) if @over_yuki && @over_yuki.executing?
265
+ return self
266
+ end
267
+
268
+ #===Yuki#showで表示指定した画像のアニメーションを更新する
269
+ #showメソッドで指定した画像のupdate_animationメソッドを呼び出す
270
+ #返却値:: 描く画像のupdate_spriteメソッドを呼び出した結果を配列で返す
271
+ def update_animation
272
+ @over_yuki.update_animation if @over_yuki && @over_yuki.executing?
273
+ @visibles.update_animation
274
+ end
275
+
276
+ #===変数を参照する
277
+ #[[Yukiスクリプトとして利用可能]]
278
+ #変数の管理オブジェクトを、ハッシュとして参照する。
279
+ #変数名nameを指定して、インスタンスを参照できる。
280
+ #未登録の変数はnilが変える。
281
+ #(例)vars[:a] = 2 # 変数への代入
282
+ # vars[:b] = vars[:a] + 5
283
+ # show vars[:my_name]
284
+ #
285
+ #_name_:: パーツ名(シンボル)
286
+ #
287
+ #返却値:: 変数管理ハッシュ
288
+ def vars
289
+ @vars
290
+ end
291
+
292
+ #===変数を参照する
293
+ #[[Yukiスクリプトとして利用可能]]
294
+ #変数の管理オブジェクトを、ハッシュとして参照する。
295
+ #変数名nameを指定して、インスタンスを参照できる。
296
+ #未登録の変数はnilが変える。
297
+ #(例)vars[:a] = 2 # 変数への代入
298
+ # vars[:b] = vars[:a] + 5
299
+ # vars_names => [:a, :b]
300
+ #
301
+ #_name_:: パーツ名(シンボル)
302
+ #
303
+ #返却値:: 変数管理ハッシュ
304
+ def vars_names
305
+ @vars.keys
306
+ end
307
+
308
+ #===パーツを参照する
309
+ #[[Yukiスクリプトとして利用可能]]
310
+ #パーツの管理オブジェクトを、ハッシュとして参照する。
311
+ #パーツ名nameを指定して、インスタンスを参照できる
312
+ #未登録のパーツはnilが返る
313
+ #(例)parts[:chr1]
314
+ #
315
+ #返却値:: パーツ管理ハッシュ
316
+ def parts
317
+ @parts
318
+ end
319
+
320
+ #===パーツ名の一覧を参照する
321
+ #[[Yukiスクリプトとして利用可能]]
322
+ #パーツ管理オブジェクトに登録されているパーツ名の一覧を配列として返す。
323
+ #順番は登録順。
324
+ #まだ何も登録されていないときは空の配列が返る。
325
+ #(例)regist_parts :chr1, hoge
326
+ # regist_parts :chr2, fuga
327
+ # parts_names # => [:chr1, :chr2]
328
+ #
329
+ #返却値:: パーツ管理ハッシュ
330
+ def parts_names
331
+ @parts.keys
332
+ end
333
+
334
+ #===現在描画対象のパーツ名のリストを取得する
335
+ #[[Yukiスクリプトとして利用可能]]
336
+ #現在描画しているパーツ名の配列を参照する。
337
+ #実体のインスタンスは、partsメソッドで参照できるハッシュの値として格納されている。
338
+ #Yuki#renderで描画する際、配列の先頭から順に、要素に対応するインスタンスを描画する(つまり、配列の後ろにある方が前に描画される
339
+ #(例):[:a, :b, :c]の順に並んでいたら、:cが指すインスタンスが一番前に描画される。
340
+ #
341
+ #返却値:: 描画対象リスト
342
+ def visibles
343
+ @visibles.names
344
+ end
345
+
346
+ #===オブジェクトを登録する
347
+ #[[Yukiスクリプトとして利用可能]]
348
+ #オブジェクトをパーツnameとして登録する。
349
+ #Yuki::parts[name]で参照可能
350
+ #_name_:: パーツ名(シンボル)
351
+ #_parts_:: 登録対象のインスタンス
352
+ #
353
+ #返却値:: 自分自身を返す
354
+ def regist_parts(name, parts)
355
+ @parts[name] = parts
356
+ return self
357
+ end
358
+
359
+ #===表示・描画対象のテキストボックスを選択する
360
+ #[[Yukiスクリプトとして利用可能]]
361
+ #_box_:: テキストボックスのインスタンス
362
+ #
363
+ #返却値:: 自分自身を返す
364
+ def select_textbox(box)
365
+ @text_box = box
366
+ return self
367
+ end
368
+
369
+ #===表示・描画対象のコマンドボックスを選択する
370
+ #[[Yukiスクリプトとして利用可能]]
371
+ #_box_:: テキストボックスのインスタンス
372
+ #
373
+ #返却値:: 自分自身を返す
374
+ def select_commandbox(box)
375
+ @command_box = box
376
+ return self
377
+ end
378
+
379
+ #===テキストボックスを取得する
380
+ #[[Yukiスクリプトとして利用可能]]
381
+ #テキストボックスが登録されていないときはnilを返す
382
+ #返却値:: テキストボックスのインスタンス
383
+ def textbox
384
+ return @text_box
385
+ end
386
+
387
+ #===コマンドボックスを取得する
388
+ #[[Yukiスクリプトとして利用可能]]
389
+ #コマンドボックスが登録されていないときはnilを返す
390
+ #返却値:: コマンドボックスのインスタンス
391
+ def commandbox
392
+ return @command_box
393
+ end
394
+
395
+ #===オブジェクトの登録を解除する
396
+ #[[Yukiスクリプトとして利用可能]]
397
+ #パーツnameとして登録されているオブジェクトを登録から解除する。
398
+ #_name_:: パーツ名(シンボル)
399
+ #
400
+ #返却値:: 自分自身を返す
401
+ def remove_parts(name)
402
+ @parts.delete(name)
403
+ return self
404
+ end
405
+
406
+ #===パーツで指定したオブジェクトを先頭に表示する
407
+ #[[Yukiスクリプトとして利用可能]]
408
+ #描画時に、指定したパーツを描画する
409
+ #すでにshowメソッドで表示指定している場合は、先頭に表示させる
410
+ #_names_:: パーツ名(シンボル)、複数指定可能(指定した順番に描画される)
411
+ #返却値:: 自分自身を返す
412
+ def show(*names)
413
+ names.each{|name|
414
+ @visibles.add(name, @parts[name])
415
+ @parts[name].show
416
+ }
417
+ return self
418
+ end
419
+
420
+ #===パーツで指定したオブジェクトを隠蔽する
421
+ #[[Yukiスクリプトとして利用可能]]
422
+ #描画時に、指定したパーツを描画させないよう指定する
423
+ #_names_:: パーツ名(シンボル)、複数指定可能
424
+ #返却値:: 自分自身を返す
425
+ def hide(*names)
426
+ names.each{|name|
427
+ @parts[name].hide
428
+ @visibles.delete(name)
429
+ }
430
+ return self
431
+ end
432
+
433
+ #===パーツで指定したオブジェクトの処理を開始する
434
+ #[[Yukiスクリプトとして利用可能]]
435
+ #nameで指定したパーツが持つ処理(例:アニメーション)を開始する。
436
+ #(但し、パーツで指定したオブジェクトがstartメソッドを持つことが条件)
437
+ #_name_:: パーツ名(シンボル)
438
+ #返却値:: 自分自身を返す
439
+ def start(name)
440
+ @parts[name].start
441
+ return self
442
+ end
443
+
444
+ #===パーツで指定したオブジェクトを再生する
445
+ #[[Yukiスクリプトとして利用可能]]
446
+ #nameで指定したパーツを再生(例:BGM)する。
447
+ #(但し、パーツで指定したオブジェクトがplayメソッドを持つことが条件)
448
+ #_name_:: パーツ名(シンボル)
449
+ #返却値:: 自分自身を返す
450
+ def play(name)
451
+ @parts[name].play
452
+ return self
453
+ end
454
+
455
+ #===パーツで指定したオブジェクトの処理を停止する
456
+ #[[Yukiスクリプトとして利用可能]]
457
+ #nameで指定したパーツが持つ処理を停止する。
458
+ #(但し、パーツで指定したオブジェクトがstopメソッドを持つことが条件)
459
+ #_name_:: パーツ名(シンボル)
460
+ #返却値:: 自分自身を返す
461
+ def stop(name)
462
+ @parts[name].stop
463
+ return self
464
+ end
465
+
466
+ #===遷移図の処理が終了するまで待つ
467
+ #[[Yukiスクリプトとして利用可能]]
468
+ #nameで指定した遷移図の処理が終了するまで、プロットを停止する
469
+ #_name_: 遷移図名(シンボル)
470
+ #返却値:: 自分自身を返す
471
+ def wait_by_finish(name)
472
+ until @parts[name].finish?
473
+ @update_inner.call(self)
474
+ end
475
+ return self
476
+ end
477
+
478
+ #===別のYukiエンジンを実行する
479
+ #[[Yukiスクリプトとして利用可能]]
480
+ #もう一つのYukiエンジンを実行させ、並行実行させることができる
481
+ #ウインドウの上にウインドウを表示したりするときに、このメソッドを使う
482
+ #renderメソッドで描画する際は、自分のインスタンスが描画した直後に描画される
483
+ #自分自身を実行しようとするとMiyakoValueError例外が発生する
484
+ #_yuki_:: 実行対象のYukiインスタンス(事前にsetupの呼び出しが必要)
485
+ #_plot_:: プロットインスタンス。すでにsetupなどで登録しているときはnilを渡す
486
+ #_params_:: プロット実行開始時に、プロットに渡す引数
487
+ #返却値:: 自分自身を返す
488
+ def over_exec(yuki, plot, *params)
489
+ raise MiyakoValueError, "This Yuki engine is same as self!" if yuki.eql?(self)
490
+ @over_yuki = yuki
491
+ @over_yuki.start_plot(plot, *params)
492
+ return self
493
+ end
494
+
495
+ #===別のYukiエンジンの実行が終わるまで待つ
496
+ #[[Yukiスクリプトとして利用可能]]
497
+ #over_execを呼び出した時、処理がすぐに次の行へ移るため、
498
+ #over_execの処理が終了するのを待たせるためのメソッド
499
+ #返却値:: 自分自身を返す
500
+ def wait_over_exec
501
+ @over_exec = true
502
+ while @over_yuki && @over_yuki.executing?
503
+ @over_yuki.update
504
+ Fiber.yield
505
+ end
506
+ return self
507
+ end
508
+
509
+ #===シーンのセットアップ時に実行する処理
510
+ #
511
+ #ブロック引数として、テキストボックスの変更などの処理をブロック内に記述することが出来る。
512
+ #引数の数とブロック引数の数が違っていれば例外が発生する
513
+ #_params_:: ブロックに渡す引数リスト(ブロックを渡しているときのみ)
514
+ #返却値:: 自分自身を返す
515
+ def setup(*params, &proc)
516
+ @exec_plot = nil
517
+
518
+ @executing = false
519
+
520
+ @pausing = false
521
+ @selecting = false
522
+ @waiting = false
523
+
524
+ @pause_release = false
525
+ @select_ok = false
526
+ @select_cancel = false
527
+ @select_amount = [0, 0]
528
+ @mouse_amount = nil
529
+
530
+ @result = nil
531
+ @plot_result = nil
532
+
533
+ @now_page = nil
534
+ @first_page = nil
535
+
536
+ raise MiyakoProcError, "Aagument count is not same block parameter count!" if proc && proc.arity.abs != params.length
537
+ instance_exec(*params, &proc) if proc
538
+
539
+ return self
540
+ end
541
+
542
+ #===実行するプロットと登録する
543
+ #_plot_proc_:: プロットの実行部をインスタンス化したオブジェクト
544
+ #返却値:: 自分自身を返す
545
+ def select_plot(plot_proc)
546
+ @exec_plot = plot_proc
547
+ return self
548
+ end
549
+
550
+ #===プロット処理を実行する(明示的に呼び出す必要がある場合)
551
+ #引数もしくはブロックで指定したプロット処理を非同期に実行する。
552
+ #呼び出し可能なプロットは以下の3種類。(上から優先度が高い順)
553
+ #プロットが見つからなければ例外が発生する
554
+ #
555
+ #1)引数prot_proc(Procクラスのインスタンス)
556
+ #
557
+ #2)引数として渡したブロック
558
+ #
559
+ #3)select_plotメソッドで登録したブロック(Procクラスのインスタンス)
560
+ #
561
+ #_plot_proc_:: プロットの実行部をインスタンス化したオブジェクト。省略時はnil(paramsを指定するときは必ず設定すること)
562
+ #_params_:: プロットに引き渡す引数リスト
563
+ #返却値:: 自分自身を返す
564
+ def start_plot(plot_proc = nil, *params, &plot_block)
565
+ raise MiyakoValueError, "Yuki Error! Textbox is not selected!" unless @text_box
566
+ raise MiyakoProcError, "Aagument count is not same block parameter count!" if plot_proc && plot_proc.arity.abs != params.length
567
+ raise MiyakoProcError, "Aagument count is not same block parameter count!" if plot_block && plot_block.arity.abs != params.length
568
+ raise MiyakoProcError, "Aagument count is not same block parameter count!" if @exec_plot && @exec_plot.arity.abs != params.length
569
+ @executing_fiber = Fiber.new{ plot_facade(plot_proc, *params, &plot_block) }
570
+ @executing_fiber.resume
571
+ return self
572
+ end
573
+
574
+ #===プロット処理を更新する
575
+ #ポーズ中、コマンド選択中、 Yuki#wait メソッドによるウェイトの状態確認を行う。
576
+ #プロット処理の実行確認は出来ない
577
+ def update
578
+ return unless @executing
579
+ return @over_yuki.update if @over_yuki && @over_yuki.executing? && !@over_exec
580
+ update_plot_input
581
+ pausing if @pausing
582
+ selecting if @selecting
583
+ waiting if @waiting
584
+ @pause_release = false
585
+ @select_ok = false
586
+ @select_cancel = false
587
+ @select_amount = [0, 0]
588
+ @executing_fiber.resume
589
+ end
590
+
591
+ #===プロット用ブロックをYukiへ渡すためのインスタンスを作成する
592
+ #プロット用に用意したブロック(ブロック引数無し)を、Yukiでの選択結果や移動先として利用できる
593
+ #インスタンスに変換する
594
+ #返却値:: ブロックをオブジェクトに変換したものを返す
595
+ def to_plot(&plot)
596
+ return plot
597
+ end
598
+
599
+ #===プロット処理に使用する入力情報を更新する
600
+ #ポーズ中、コマンド選択中に使用する入力デバイスの押下状態を更新する
601
+ #(但し、プロット処理の実行中にのみ更新する)
602
+ #Yuki#update メソッドをそのまま使う場合は呼び出す必要がないが、 Yuki#exec_plot メソッドを呼び出す
603
+ #プロット処理の場合は、メインスレッドから明示的に呼び出す必要がある
604
+ #返却値:: nil を返す
605
+ def update_plot_input
606
+ return nil if @over_yuki && @over_yuki.executing?
607
+ return nil unless @executing
608
+ if @pausing && @release_checks.inject(false){|r, c| r |= c.call }
609
+ @pause_release = true
610
+ elsif @selecting
611
+ @select_ok = true if @ok_checks.inject(false){|r, c| r |= c.call }
612
+ @select_cancel = true if @cancel_checks.inject(false){|r, c| r |= c.call }
613
+ @select_amount = @key_amount_proc.call
614
+ @mouse_amount = @mouse_amount_proc.call
615
+ end
616
+ return nil
617
+ end
618
+
619
+ def plot_facade(plot_proc = nil, *params, &plot_block) #:nodoc:
620
+ @plot_result = nil
621
+ @executing = true
622
+ exec_plot = @exec_plot
623
+ @plot_result = plot_proc ? self.instance_exec(*params, &plot_proc) :
624
+ block_given? ? self.instance_exec(*params, &plot_block) :
625
+ exec_plot ? self.instance_exec(*params, &exec_plot) :
626
+ raise(MiyakoProcError, "Cannot find plot!")
627
+ @executing = false
628
+ end
629
+
630
+ #===プロット処理中に別のプロットを呼び出す
631
+ #呼び出し可能なプロットは以下の2種類。(上から優先度が高い順)
632
+ #
633
+ #1)引数prot_proc(Procクラスのインスタンス)
634
+ #
635
+ #2)引数として渡したブロック
636
+ #
637
+ #_plot_proc_:: プロットの実行部をインスタンス化したオブジェクト
638
+ #返却値:: プロットの実行結果を返す
639
+ def call_plot(plot_proc = nil, &plot_block)
640
+ return plot_proc ? self.instance_exec(&plot_proc) :
641
+ self.instance_exec(&plot_block)
642
+ end
643
+
644
+ #===プロット処理が実行中かどうかを確認する
645
+ #返却値:: プロット処理実行中の時はtrueを返す
646
+ def executing?
647
+ return @executing
648
+ end
649
+
650
+ #===ポーズ解除問い合わせメソッド配列を初期状態に戻す
651
+ #返却値:: 自分自身を返す
652
+ def reset_release_checks
653
+ @release_checks = @release_checks_default.dup
654
+ return self
655
+ end
656
+
657
+ #===コマンド選択決定問い合わせメソッド配列を初期状態に戻す
658
+ #返却値:: 自分自身を返す
659
+ def reset_ok_checks
660
+ @ok_checks = @ok_checks_default.dup
661
+ return self
662
+ end
663
+
664
+ #===コマンド選択キャンセル問い合わせメソッド配列を初期状態に戻す
665
+ #返却値:: 自分自身を返す
666
+ def reset_cancel_checks
667
+ @cancel_checks = @cancel_checks_default.dup
668
+ return self
669
+ end
670
+
671
+ #===ポーズ前後処理メソッド配列を初期状態に戻す
672
+ #pre_pause/post_pauseの処理を初期状態([])に戻す
673
+ #返却値:: 自分自身を返す
674
+ def reset_pre_post_release
675
+ @pre_pause = []
676
+ @post_pause = []
677
+ return self
678
+ end
679
+
680
+ #===コマンド選択前後処理メソッド配列を初期状態に戻す
681
+ #pre_command/post_commandの処理を初期状態([])に戻す
682
+ #返却値:: 自分自身を返す
683
+ def reset_pre_post_command
684
+ @pre_command = []
685
+ @post_command = []
686
+ return self
687
+ end
688
+
689
+ #===コマンド選択キャンセル前後処理メソッド配列を初期状態に戻す
690
+ #pre_cancel/post_cancelの処理を初期状態([])に戻す
691
+ #返却値:: 自分自身を返す
692
+ def reset_pre_post_cancel
693
+ @pre_acncel = []
694
+ @post_cancel = []
695
+ return self
696
+ end
697
+
698
+ #===ブロック評価中、ポーズ解除問い合わせメソッド配列を置き換える
699
+ #同時に、ポーズ時処理(Yuki#pre_pause)、ポーズ解除時処理(Yuki#post_pause)を引数で設定できる。
700
+ #ブロックの評価が終われば、メソッド配列・ポーズ時処理・ポーズ解除時処理を元に戻す
701
+ #procs:: 置き換えるメソッド配列(callメソッドを持ち、true/falseを返すメソッドの配列)
702
+ #pre_proc:: ポーズ開始時に実行させるProc(デフォルトは[](何もしない))
703
+ #post_proc:: ポーズ解除時に実行させるProc(デフォルトは[](何もしない))
704
+ #返却値:: 自分自身を返す
705
+ def release_checks_during(procs, pre_procs = [], post_procs = [])
706
+ raise MiyakoProcError, "Can't find block!" unless block_given?
707
+ backup = [@release_checks, @pre_pause, @post_pause]
708
+ @release_checks, @pre_pause, @post_pause = procs, pre_proc, post_proc
709
+ yield
710
+ @release_checks, @pre_pause, @post_pause = backup.pop(3)
711
+ return self
712
+ end
713
+
714
+ #===ブロック評価中、コマンド選択決定問い合わせメソッド配列を置き換える
715
+ #同時に、コマンド選択開始時処理(Yuki#pre_command)、コマンド選択終了時処理(Yuki#post_command)を引数で設定できる。
716
+ #ブロックの評価が終われば、メソッド配列・コマンド選択開始時処理・コマンド選択終了時処理を元に戻す
717
+ #procs:: 置き換えるメソッド配列(callメソッドを持ち、true/falseを返すメソッドの配列)
718
+ #pre_proc:: コマンド選択開始時に実行させるProc(デフォルトは[](何もしない))
719
+ #post_proc:: コマンド選択決定時に実行させるProc(デフォルトは[](何もしない))
720
+ #返却値:: 自分自身を返す
721
+ def ok_checks_during(procs, pre_procs = [], post_procs = [])
722
+ raise MiyakoProcError, "Can't find block!" unless block_given?
723
+ backup = [@ok_checks, @pre_command, @post_command]
724
+ @ok_checks, @pre_command, @post_command = procs, pre_proc, post_proc
725
+ yield
726
+ @ok_checks, @pre_command, @post_command = backup.pop(3)
727
+ return self
728
+ end
729
+
730
+ #===ブロック評価中、コマンド選択キャンセル問い合わせメソッド配列を置き換える
731
+ #同時に、コマンド選択開始時処理(Yuki#pre_cancel)、コマンド選択終了時処理(Yuki#post_cancel)を引数で設定できる。
732
+ #ブロックの評価が終われば、メソッド配列・コマンド選択開始時処理・コマンド選択終了時処理を元に戻す
733
+ #procs:: 置き換えるメソッド配列(callメソッドを持ち、true/falseを返すメソッドの配列)
734
+ #pre_proc:: コマンド選択開始時に実行させるProc(デフォルトは[](何もしない))
735
+ #post_proc:: コマンド選択キャンセル時に実行させるProc(デフォルトは[](何もしない))
736
+ #返却値:: 自分自身を返す
737
+ def cancel_checks_during(procs, pre_procs = [], post_procs = [])
738
+ raise MiyakoProcError, "Can't find block!" unless block_given?
739
+ backup = [@cancel_checks, @pre_cancel, @post_cancel]
740
+ @cancel_checks, @pre_cancel, @post_cancel = procs, pre_proc, post_proc
741
+ yield
742
+ @cancel_checks, @pre_cancel, @post_cancel = backup.pop(3)
743
+ return self
744
+ end
745
+
746
+ #===プロットの処理結果を返す
747
+ #[[Yukiスクリプトとして利用可能]]
748
+ #プロット処理の結果を返す。
749
+ #まだ結果が得られていない場合はnilを得る
750
+ #プロット処理が終了していないのに結果を得られるので注意!
751
+ #返却値:: プロットの処理結果
752
+ def result
753
+ return @plot_result
754
+ end
755
+
756
+ #===プロット処理の結果を設定する
757
+ #[[Yukiスクリプトとして利用可能]]
758
+ #_ret_:: 設定する結果。デフォルトはnil
759
+ #返却値:: 自分自身を返す
760
+ def result=(ret = nil)
761
+ @plot_result = ret
762
+ return self
763
+ end
764
+
765
+ #===結果がシーンかどうかを問い合わせる
766
+ #[[Yukiスクリプトとして利用可能]]
767
+ #結果がシーン(シーンクラス名)のときはtrueを返す
768
+ #対象の結果は、選択結果、プロット処理結果ともに有効
769
+ #返却値:: 結果がシーンかどうか(true/false)
770
+ def is_scene?(result)
771
+ return (result.class == Class && result.include?(Story::Scene))
772
+ end
773
+
774
+ #===結果がシナリオかどうかを問い合わせる
775
+ #[[Yukiスクリプトとして利用可能]]
776
+ #結果がシナリオ(メソッド)のときはtrueを返す
777
+ #対象の結果は、選択結果、プロット処理結果ともに有効
778
+ #返却値:: 結果がシナリオかどうか(true/false)
779
+ def is_scenario?(result)
780
+ return (result.kind_of?(Proc) || result.kind_of?(Method))
781
+ end
782
+
783
+ #===コマンド選択がキャンセルされたときの結果を返す
784
+ #[[Yukiスクリプトとして利用可能]]
785
+ #返却値:: キャンセルされたときはtrue、されていないときはfalseを返す
786
+ def canceled?
787
+ return result == @cancel
788
+ end
789
+
790
+ #===ブロックを条件として設定する
791
+ #[[Yukiスクリプトとして利用可能]]
792
+ #メソッドをMethodクラスのインスタンスに変換する
793
+ #_block_:: シナリオインスタンスに変換したいメソッド名(シンボル)
794
+ #返却値:: シナリオインスタンスに変換したメソッド
795
+ def condition(&block)
796
+ return block
797
+ end
798
+
799
+ #===コマンド選択中の問い合わせメソッド
800
+ #[[Yukiスクリプトとして利用可能]]
801
+ #返却値:: コマンド選択中の時はtrueを返す
802
+ def selecting?
803
+ return @selecting
804
+ end
805
+
806
+ #===Yuki#waitメソッドによる処理待ちの問い合わせメソッド
807
+ #[[Yukiスクリプトとして利用可能]]
808
+ #返却値:: 処理待ちの時はtrueを返す
809
+ def waiting?
810
+ return @waiting
811
+ end
812
+
813
+ #===メッセージ送り待ちの問い合わせメソッド
814
+ #[[Yukiスクリプトとして利用可能]]
815
+ #返却値:: メッセージ送り待ちの時はtrueを返す
816
+ def pausing?
817
+ return @pausing
818
+ end
819
+
820
+ #===条件に合っていればポーズをかける
821
+ #[[Yukiスクリプトとして利用可能]]
822
+ #引数で設定した条件(Proc,メソッドインスタンス,ブロック)を評価した結果、trueのときはポーズを行い、
823
+ #condの値がnilで、ブロックが渡されていないときは何もしない
824
+ #falseのときは改行してプロットの処理を継続する
825
+ #_cond_:: 条件を示すオブジェクト(返却値はtrue/false)。デフォルトはnil(渡されたブロックを評価する)
826
+ #返却値:: 自分自身を返す
827
+ def wait_by_cond(cond = nil)
828
+ return yield ? pause_and_clear : cr if block_given?
829
+ return cond.call ? pause_and_clear : cr if cond
830
+ return self
831
+ end
832
+
833
+ #===テキストボックスに文字を表示する方法を指定する
834
+ #引数に、:charを渡すと1文字ごと、:stringを渡すと文字列ごとに表示される。それ以外を指定したときは例外が発生
835
+ #ブロックを渡せば、ブロックの評価中のみ設定が有効になる。
836
+ #ブロック評価終了後、呼び出し前の設定に戻る
837
+ #_mode_:: テキストの表示方法。:charのときは文字ごと、:stringのときは文字列ごとに表示される。それ以外を指定したときは例外が発生
838
+ #返却値:: 自分自身を返す
839
+ def text_method(mode)
840
+ raise MiyakoValueError, "undefined text_mode! #{mode}" unless [:char,:string].include?(mode)
841
+ backup = @text_method_name
842
+ @text_method_name = mode
843
+ if block_given?
844
+ yield
845
+ @text_method_name = backup
846
+ end
847
+ return self
848
+ end
849
+
850
+ #===テキストボックスに文字を表示する
851
+ #[[Yukiスクリプトとして利用可能]]
852
+ #テキストボックスとして用意している画像に文字を描画する。
853
+ #描画する単位(文字単位、文字列単位)によって、挙動が違う。
854
+ #(文字単位の時)
855
+ #Yuki#text_by_charメソッドと同じ挙動。
856
+ #(文字列単位の時)
857
+ #Yuki#text_by_strメソッドと同じ挙動。
858
+ #デフォルトは文字単位。
859
+ #引数txtの値は、内部で1文字ずつ分割され、1文字描画されるごとに、
860
+ #update_textメソッドが呼び出され、続けてYuki#start_plotもしくはYuki#updateメソッド呼び出し直後に戻る
861
+ #_txt_:: 表示させるテキスト
862
+ #返却値:: 自分自身を返す
863
+ def text(txt)
864
+ return self if txt.eql?(self)
865
+ return self if txt.empty?
866
+ return @text_methods[@text_method_name].call(txt)
867
+ end
868
+
869
+ #===テキストボックスに文字を1文字ずつ表示する
870
+ #[[Yukiスクリプトとして利用可能]]
871
+ #引数txtの値は、内部で1文字ずつ分割され、1文字描画されるごとに、
872
+ #update_textメソッドが呼び出され、続けてYuki#start_plotもしくはYuki#updateメソッド呼び出し直後に戻る
873
+ #注意として、改行が文字列中にあれば改行、タブやフィードが文字列中にあれば、nilを返す。
874
+ #_txt_:: 表示させるテキスト
875
+ #返却値:: 自分自身を返す
876
+ def text_by_char(txt)
877
+ return self if txt.eql?(self)
878
+ txt.chars{|ch|
879
+ if /[\n\r]/.match(ch)
880
+ next wait_by_cond(@is_outer_height)
881
+ elsif @text_box.locate.x + @text_box.font.text_size(ch)[0] >= @text_box.textarea.w
882
+ wait_by_cond(@is_outer_height)
883
+ elsif /[\t\f]/.match(ch)
884
+ next nil
885
+ end
886
+ @text_box.draw_text(ch)
887
+ @update_text.call(self, ch)
888
+ Fiber.yield
889
+ }
890
+ return self
891
+ end
892
+
893
+ #===テキストボックスに文字を表示する
894
+ #[[Yukiスクリプトとして利用可能]]
895
+ #文字列が描画されるごとに、update_textメソッドが呼び出され、
896
+ #続けてYuki#start_plotもしくはYuki#updateメソッド呼び出し直後に戻る
897
+ #注意として、改行が文字列中にあれば改行、タブやフィードが文字列中にあれば、nilを返す。
898
+ #_txt_:: 表示させるテキスト
899
+ #返却値:: 自分自身を返す
900
+ def text_by_str(txt)
901
+ return self if txt.eql?(self)
902
+ use_cr = false
903
+ until txt.empty? do
904
+ if /[\n\r]/.match(txt)
905
+ tmp = Regexp.last_match.pre_match
906
+ txt = Regexp.last_match.post_match
907
+ use_cr = true
908
+ elsif @text_box.locate.x + @text_box.font.text_size(txt)[0] >= @text_box.textarea.w
909
+ w = (@text_box.textarea.w - @text_box.locate.x) / @text_box.font.size
910
+ tmp = txt.slice!(0,w)
911
+ use_cr = true
912
+ elsif /[\t\f]/.match(txt)
913
+ next nil
914
+ else
915
+ tmp = txt
916
+ txt = ""
917
+ end
918
+ @text_box.draw_text(tmp)
919
+ self.cr if use_cr
920
+ @update_text.call(self, tmp)
921
+ Fiber.yield
922
+ use_cr = false
923
+ end
924
+ return self
925
+ end
926
+
927
+ def is_outer_height #:nodoc:
928
+ return @text_box.locate.y + @text_box.max_height >= @text_box.textarea.h
929
+ end
930
+
931
+ private :is_outer_height
932
+
933
+ #===文字色を変更する
934
+ #[[Yukiスクリプトとして利用可能]]
935
+ #ブロック内で指定した文字列を、指定の色で描画する
936
+ #_color_:: 文字色
937
+ #返却値:: 自分自身を返す
938
+ def color(color, &block)
939
+ @text_box.color_during(Color.to_rgb(color)){ text block.call }
940
+ return self
941
+ end
942
+
943
+ #===ブロック評価中、行中の表示位置を変更する
944
+ #[[Yukiスクリプトとして利用可能]]
945
+ #ブロックを評価している間だけ、デフォルトの縦の表示位置を変更する
946
+ #変更できる値は、:top、:middle、:bottomの3種類。
947
+ #ブロックを渡していないときはエラーを返す
948
+ #_valign_:: 文字の縦の位置(top, middle, bottom)
949
+ #返却値:: 自分自身を返す
950
+ def valign_during(valign)
951
+ raise MiyakoProcError, "Can't find block!" unless block_given?
952
+ oalign, @valign = @valign, valign
953
+ yield
954
+ @valign = oalign
955
+ return self
956
+ end
957
+
958
+ #===文字の大きさを変更する
959
+ #[[Yukiスクリプトとして利用可能]]
960
+ #ブロック内で指定した文字列を、指定の大きさで描画する
961
+ #_size_:: 文字の大きさ(整数)
962
+ #_valign_:: 文字の縦の位置(top, middle, bottom)。デフォルトは:middle(Yuki#valign=,Yuki#valign_duringで変更可能)
963
+ #返却値:: 自分自身を返す
964
+ def size(size, valign = @valign, &block)
965
+ @text_box.font_size_during(size){
966
+ @text_box.margin_during(@text_box.margin_height(valign)){ text block.call }
967
+ }
968
+ return self
969
+ end
970
+
971
+ #===太文字を描画する
972
+ #[[Yukiスクリプトとして利用可能]]
973
+ #ブロック内で指定した文字列を太文字で表示する
974
+ #(使用すると文字の端が切れてしまう場合あり!)
975
+ #返却値:: 自分自身を返す
976
+ def bold(&block)
977
+ @text_box.font_bold{ text block.call }
978
+ return self
979
+ end
980
+
981
+ #===斜体文字を描画する
982
+ #[[Yukiスクリプトとして利用可能]]
983
+ #ブロック内で指定した文字列を斜体で表示する
984
+ #(使用すると文字の端が切れてしまう場合あり!)
985
+ #返却値:: 自分自身を返す
986
+ def italic(&block)
987
+ @text_box.font_italic{ text block.call }
988
+ return self
989
+ end
990
+
991
+ #===下線付き文字を描画する
992
+ #[[Yukiスクリプトとして利用可能]]
993
+ #ブロック内で指定した文字列を下線付きで表示する
994
+ #返却値:: 自分自身を返す
995
+ def under_line(&block)
996
+ @text_box.font_under_line{ text block.call }
997
+ return self
998
+ end
999
+
1000
+ #===改行を行う
1001
+ #[[Yukiスクリプトとして利用可能]]
1002
+ #開業後にupdate_crテンプレートメソッドが1回呼ばれる
1003
+ #_tm_:: 改行回数。デフォルトは1
1004
+ #返却値:: 自分自身を返す
1005
+ def cr(tm = 1)
1006
+ tm.times{|n|
1007
+ @text_box.cr
1008
+ @update_cr.call(self)
1009
+ }
1010
+ return self
1011
+ end
1012
+
1013
+ #===テキストボックスの内容を消去する
1014
+ #[[Yukiスクリプトとして利用可能]]
1015
+ #開業後にupdate_clearテンプレートメソッドが1回呼ばれる
1016
+ #返却値:: 自分自身を返す
1017
+ def clear
1018
+ @text_box.clear
1019
+ @update_clear.call(self)
1020
+ return self
1021
+ end
1022
+
1023
+ #===ポーズを行う
1024
+ #[[Yukiスクリプトとして利用可能]]
1025
+ #ポーズが行われると、ポーズ用のカーソルが表示される
1026
+ #所定のボタンを押すとポーズが解除され、カーソルが消える
1027
+ #解除後は、プロットの続きを処理する
1028
+ #引数無しのブロックを渡せば、ポーズ開始前に行いたい処理を施すことが出来る
1029
+ #ポーズ中、update_innerメソッドを呼び出し、続けて、処理をYuki#startもしくはYuki#update呼び出し直後に戻す
1030
+ #Yuki#updateが呼び出されてもポーズ中の場合は、再び上記の処理を繰り返す
1031
+ #(たとえば、一定時間後に自動的にポーズ解除する場合、そのタイマーを開始させるなど)
1032
+ #返却値:: 自分自身を返す
1033
+ def pause
1034
+ @pre_pause.each{|proc| proc.call}
1035
+ yield if block_given?
1036
+ @text_box.pause
1037
+ @pausing = true
1038
+ while @pausing
1039
+ @update_inner.call(self)
1040
+ Fiber.yield
1041
+ end
1042
+ @post_pause.each{|proc| proc.call}
1043
+ return self
1044
+ end
1045
+
1046
+ def pausing #:nodoc:
1047
+ return unless @pause_release
1048
+ @text_box.release
1049
+ @pausing = false
1050
+ @pause_release = false
1051
+ end
1052
+
1053
+ #===ポーズをかけて、テキストボックスの内容を消去する
1054
+ #[[Yukiスクリプトとして利用可能]]
1055
+ #ポーズをかけ、ポーズを解除するときにテキストボックスの内容を消去する
1056
+ #返却値:: 自分自身を返す
1057
+ def pause_and_clear
1058
+ return pause.clear
1059
+ end
1060
+
1061
+ #===コマンドを表示する
1062
+ #[[Yukiスクリプトとして利用可能]]
1063
+ #表示対象のコマンド群をCommand構造体の配列で示す。
1064
+ #キャンセルのときの結果も指定可能(既定ではキャンセル不可状態)
1065
+ #body_selectedをnilにした場合は、bodyと同一となる
1066
+ #body_selectedを文字列を指定した場合は、文字色が赤色になることに注意
1067
+ #引数無しのブロックを渡せば、コマンド選択開始前に、決定判別・キャンセル判別に必要な前処理を施すことが出来る
1068
+ #選択中、update_innerメソッドを呼び出し、続けて、処理をYuki#startもしくはYuki#update呼び出し直後に戻す
1069
+ #Yuki#updateが呼び出されても選択中の場合は、再び上記の処理を繰り返す
1070
+ #_command_list_:: 表示するコマンド群。各要素はCommand構造体の配列
1071
+ #_cancel_to_:: キャンセルボタンを押したときの結果。デフォルトはnil(キャンセル無効)
1072
+ #_chain_block_:: コマンドの表示方法。TextBox#create_choices_chainメソッド参照
1073
+ #返却値:: 自分自身を返す
1074
+ def command(command_list, cancel_to = Canceled, &chain_block)
1075
+ raise MiyakoValueError, "Yuki Error! Commandbox is not selected!" unless @command_box
1076
+ @cancel = cancel_to
1077
+
1078
+ choices = []
1079
+ command_list.each{|cm|
1080
+ if (cm[:condition] == nil || cm[:condition].call)
1081
+ cm_array = [cm[:body], cm[:body_selected], cm[:result]]
1082
+ methods = cm.methods
1083
+ cm_array << (methods.include?(:end_select_proc) ? cm[:end_select_proc] : nil)
1084
+ choices.push(cm_array)
1085
+ end
1086
+ }
1087
+ return self if choices.length == 0
1088
+
1089
+ @pre_command.each{|proc| proc.call}
1090
+ @pre_cancel.each{|proc| proc.call}
1091
+ yield if block_given?
1092
+ @command_box.command(@command_box.create_choices_chain(choices, &chain_block))
1093
+ @result = nil
1094
+ @selecting = true
1095
+ while @selecting
1096
+ @update_inner.call(self)
1097
+ Fiber.yield
1098
+ end
1099
+ @post_cancel.each{|proc| proc.call}
1100
+ @post_command.each{|proc| proc.call}
1101
+ return self
1102
+ end
1103
+
1104
+ def selecting #:nodoc:
1105
+ return unless @selecting
1106
+ return unless @command_box.selecting?
1107
+ @selecting_procs.each{|sp|
1108
+ sp.call(@select_ok, @select_cansel, @select_amount, @mouse_amount)
1109
+ }
1110
+ if @select_ok
1111
+ @result = @command_box.result
1112
+ @command_box.finish_command
1113
+ @text_box.release
1114
+ @selecting = false
1115
+ reset_selecting
1116
+ elsif @select_cancel
1117
+ @result = @cancel
1118
+ @command_box.finish_command
1119
+ @text_box.release
1120
+ @selecting = false
1121
+ reset_selecting
1122
+ elsif @select_amount != [0,0]
1123
+ @command_box.move_cursor(*@select_amount)
1124
+ reset_selecting
1125
+ elsif @mouse_amount
1126
+ @command_box.attach_cursor(*@mouse_amount.to_a)
1127
+ reset_selecting
1128
+ end
1129
+ end
1130
+
1131
+ def reset_selecting #:nodoc:
1132
+ @select_ok = false
1133
+ @select_cancel = false
1134
+ @select_amount = [0, 0]
1135
+ end
1136
+
1137
+ #===コマンドの選択結果を返す
1138
+ #[[Yukiスクリプトとして利用可能]]
1139
+ #コマンド選択の結果を返す。
1140
+ #まだ結果が得られていない場合はnilを得る
1141
+ #プロット処理・コマンド選択が終了していないのに結果を得られるので注意!
1142
+ #返却値:: コマンドの選択結果
1143
+ def select_result
1144
+ return @result
1145
+ end
1146
+
1147
+ #===プロットの処理を待機する
1148
+ #[[Yukiスクリプトとして利用可能]]
1149
+ #指定の秒数(少数可)、プロットの処理を待機する。
1150
+ #待機中、update_innerメソッドを呼び出し、続けて、処理をYuki#startもしくはYuki#update呼び出し直後に戻す
1151
+ #Yuki#updateが呼び出されても待機中の場合は、再び上記の処理を繰り返す
1152
+ #_length_:: 待機する長さ。単位は秒。少数可。
1153
+ #返却値:: 自分自身を返す
1154
+ def wait(length)
1155
+ @waiting_timer = WaitCounter.new(length)
1156
+ @waiting_timer.start
1157
+ @waiting = true
1158
+ while @waiting
1159
+ @update_inner.call(self)
1160
+ Fiber.yield
1161
+ end
1162
+ return self
1163
+ end
1164
+
1165
+ def waiting #:nodoc:
1166
+ return if @waiting_timer.waiting?
1167
+ @waiting = false
1168
+ end
1169
+
1170
+ #===シナリオ上の括り(ページ)を実装する
1171
+ #[[Yukiスクリプトとして利用可能]]
1172
+ #シナリオ上、「このプロットの明示的な範囲」を示すために使用する(セーブ時の再現位置の指定など)
1173
+ #Yuki#select_first_pageメソッドで開始位置が指定されている場合、以下の処理を行う。
1174
+ #(1)select_first_pageメソッドで指定されたページから処理する。それまでのページは無視される
1175
+ #(2)開始ページを処理する前に、select_first_pageメソッドの内容をクリアする(nilに変更する)
1176
+ #このメソッドはブロックが必須。ブロックがないと例外が発生する。
1177
+ #_name_:: ページ名。select_first_pageメソッドは、この名前を検索する。また、now_pageメソッドの返却値でもある
1178
+ #_use_pause_::ページの処理が終了した後、必ずpauseメソッドを呼び出すかどうかのフラグ。デフォルトはtrue
1179
+ #返却値:: select_first_pageメソッドで指定されていないページのときはnil、指定されているページの場合は引数nameの値
1180
+ def page(name, use_pause = true)
1181
+ raise MiyakoProcError, "Yuki#page needs block!" unless block_given?
1182
+ return nil if (@first_page && name != @first_page)
1183
+ @first_page = nil
1184
+ @now_page = name
1185
+ yield
1186
+ pause if use_pause
1187
+ @now_page = nil
1188
+ return name
1189
+ end
1190
+
1191
+ #===シナリオ上の現在のページを返す
1192
+ #[[Yukiスクリプトとして利用可能]]
1193
+ #呼び出し当時、シナリオ上、pageメソッドでくくられていない場合は、nilを返す
1194
+ #返却値:: ページ名
1195
+ def now_page
1196
+ return @now_page
1197
+ end
1198
+
1199
+ #===プロット上の最初に実行するページを指定知る
1200
+ #[[Yukiスクリプトとして利用可能]]
1201
+ #但し、ページ名を指定しないときはnilを指定する。
1202
+ #_name_:: 最初に実行するページ名
1203
+ def select_first_page(name)
1204
+ @first_page = name
1205
+ end
1206
+
1207
+ #===インスタンスで使用しているオブジェクトを解放する
1208
+ def dispose
1209
+ @update_inner = nil
1210
+ @update_text = nil
1211
+ @update_cr = nil
1212
+ @update_clear = nil
1213
+
1214
+ @executing_fiber = nil
1215
+
1216
+ @parts.clear
1217
+ @parts = nil
1218
+ @visibles.clear
1219
+ @visibles = nil
1220
+ @vars.clear
1221
+ @vars = nil
1222
+
1223
+ @is_outer_height = nil
1224
+ end
1225
+ end
1226
+ end