cyross-ruby-miyako 2.0.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 (125) hide show
  1. data/README +977 -0
  2. data/Rakefile +7 -0
  3. data/img/cursor.png +0 -0
  4. data/img/cursors.png +0 -0
  5. data/img/dice.png +0 -0
  6. data/img/wait_cursor.png +0 -0
  7. data/img/win_base.png +0 -0
  8. data/img/window.png +0 -0
  9. data/install_miyako.rb +75 -0
  10. data/lib/Miyako/API/audio.rb +198 -0
  11. data/lib/Miyako/API/basic_data.rb +431 -0
  12. data/lib/Miyako/API/bitmap.rb +35 -0
  13. data/lib/Miyako/API/choices.rb +308 -0
  14. data/lib/Miyako/API/collision.rb +444 -0
  15. data/lib/Miyako/API/diagram.rb +573 -0
  16. data/lib/Miyako/API/drawing.rb +110 -0
  17. data/lib/Miyako/API/fixedmap.rb +315 -0
  18. data/lib/Miyako/API/font.rb +384 -0
  19. data/lib/Miyako/API/input.rb +440 -0
  20. data/lib/Miyako/API/layout.rb +451 -0
  21. data/lib/Miyako/API/map.rb +403 -0
  22. data/lib/Miyako/API/map_event.rb +198 -0
  23. data/lib/Miyako/API/modules.rb +109 -0
  24. data/lib/Miyako/API/movie.rb +151 -0
  25. data/lib/Miyako/API/parts.rb +154 -0
  26. data/lib/Miyako/API/plane.rb +131 -0
  27. data/lib/Miyako/API/screen.rb +257 -0
  28. data/lib/Miyako/API/shape.rb +362 -0
  29. data/lib/Miyako/API/sprite.rb +338 -0
  30. data/lib/Miyako/API/sprite_animation.rb +461 -0
  31. data/lib/Miyako/API/spriteunit.rb +113 -0
  32. data/lib/Miyako/API/story.rb +224 -0
  33. data/lib/Miyako/API/textbox.rb +496 -0
  34. data/lib/Miyako/API/viewport.rb +435 -0
  35. data/lib/Miyako/API/yuki.rb +779 -0
  36. data/lib/Miyako/EXT/miyako_cairo.rb +60 -0
  37. data/lib/Miyako/EXT/raster_scroll.rb +138 -0
  38. data/lib/Miyako/EXT/slides.rb +136 -0
  39. data/lib/Miyako/miyako.rb +172 -0
  40. data/miyako.png +0 -0
  41. data/miyako_banner.png +0 -0
  42. data/miyako_no_katana/extconf.rb +34 -0
  43. data/miyako_no_katana/miyako_no_katana.c +3301 -0
  44. data/sample/Animation1/m1ku.rb +89 -0
  45. data/sample/Animation1/m1ku_arm_0.png +0 -0
  46. data/sample/Animation1/m1ku_arm_1.png +0 -0
  47. data/sample/Animation1/m1ku_arm_2.png +0 -0
  48. data/sample/Animation1/m1ku_arm_3.png +0 -0
  49. data/sample/Animation1/m1ku_back.jpg +0 -0
  50. data/sample/Animation1/m1ku_body.png +0 -0
  51. data/sample/Animation1/m1ku_eye_0.png +0 -0
  52. data/sample/Animation1/m1ku_eye_1.png +0 -0
  53. data/sample/Animation1/m1ku_eye_2.png +0 -0
  54. data/sample/Animation1/m1ku_eye_3.png +0 -0
  55. data/sample/Animation1/m1ku_hair_front.png +0 -0
  56. data/sample/Animation1/m1ku_hair_rear.png +0 -0
  57. data/sample/Animation1/readme.txt +72 -0
  58. data/sample/Animation2/lex.rb +95 -0
  59. data/sample/Animation2/lex_back.png +0 -0
  60. data/sample/Animation2/lex_body.png +0 -0
  61. data/sample/Animation2/lex_roadroller.png +0 -0
  62. data/sample/Animation2/lex_wheel_0.png +0 -0
  63. data/sample/Animation2/lex_wheel_1.png +0 -0
  64. data/sample/Animation2/lex_wheel_2.png +0 -0
  65. data/sample/Animation2/readme.txt +72 -0
  66. data/sample/Animation2/song_title.png +0 -0
  67. data/sample/Diagram_sample/back.png +0 -0
  68. data/sample/Diagram_sample/chr01.png +0 -0
  69. data/sample/Diagram_sample/chr02.png +0 -0
  70. data/sample/Diagram_sample/cursor.png +0 -0
  71. data/sample/Diagram_sample/diagram_sample_yuki2.rb +283 -0
  72. data/sample/Diagram_sample/readme.txt +87 -0
  73. data/sample/Diagram_sample/wait_cursor.png +0 -0
  74. data/sample/Room3/blue.rb +250 -0
  75. data/sample/Room3/ending.rb +175 -0
  76. data/sample/Room3/green.rb +185 -0
  77. data/sample/Room3/image/akamatsu.png +0 -0
  78. data/sample/Room3/image/aoyama.png +0 -0
  79. data/sample/Room3/image/congra.png +0 -0
  80. data/sample/Room3/image/congratulation.png +0 -0
  81. data/sample/Room3/image/congratulation_bg.png +0 -0
  82. data/sample/Room3/image/cursor.png +0 -0
  83. data/sample/Room3/image/midori.png +0 -0
  84. data/sample/Room3/image/mittsu_no_oheya.png +0 -0
  85. data/sample/Room3/image/mittsu_no_oheya_logo.png +0 -0
  86. data/sample/Room3/image/room_blue.png +0 -0
  87. data/sample/Room3/image/room_green.png +0 -0
  88. data/sample/Room3/image/room_red.png +0 -0
  89. data/sample/Room3/image/start.png +0 -0
  90. data/sample/Room3/image/three_doors.png +0 -0
  91. data/sample/Room3/image/wait_cursor.png +0 -0
  92. data/sample/Room3/main.rb +102 -0
  93. data/sample/Room3/main_component.rb +58 -0
  94. data/sample/Room3/readme.txt +76 -0
  95. data/sample/Room3/red.rb +200 -0
  96. data/sample/Room3/room3.rb +26 -0
  97. data/sample/Room3/title.rb +171 -0
  98. data/sample/fixed_map_test/cursor.png +0 -0
  99. data/sample/fixed_map_test/fixed_map_sample.rb +149 -0
  100. data/sample/fixed_map_test/map.csv +19 -0
  101. data/sample/fixed_map_test/map_01.png +0 -0
  102. data/sample/fixed_map_test/map_sample.rb +121 -0
  103. data/sample/fixed_map_test/mapchip.csv +23 -0
  104. data/sample/fixed_map_test/monster.png +0 -0
  105. data/sample/fixed_map_test/readme.txt +72 -0
  106. data/sample/map_test/chara.rb +50 -0
  107. data/sample/map_test/chr1.png +0 -0
  108. data/sample/map_test/cursor.png +0 -0
  109. data/sample/map_test/main_parts.rb +48 -0
  110. data/sample/map_test/main_scene.rb +137 -0
  111. data/sample/map_test/map.png +0 -0
  112. data/sample/map_test/map2.png +0 -0
  113. data/sample/map_test/map_layer.csv +127 -0
  114. data/sample/map_test/map_manager.rb +92 -0
  115. data/sample/map_test/map_test.rb +23 -0
  116. data/sample/map_test/mapchip.csv +21 -0
  117. data/sample/map_test/oasis.rb +65 -0
  118. data/sample/map_test/readme.txt +87 -0
  119. data/sample/map_test/route.rb +144 -0
  120. data/sample/map_test/sea.png +0 -0
  121. data/sample/map_test/town.rb +68 -0
  122. data/sample/map_test/wait_cursor.png +0 -0
  123. data/sample/map_test/window.png +0 -0
  124. data/win/miyako_no_katana.so +0 -0
  125. metadata +194 -0
@@ -0,0 +1,779 @@
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
+ require 'thread'
24
+
25
+ #=シナリオ言語Yuki実装モジュール
26
+ module Miyako
27
+ #==Yuki本体クラス
28
+ #Yukiの内容をオブジェクト化したクラス
29
+ #Yukiのプロット処理を外部メソッドで管理可能
30
+ #プロットは、引数を一つ(Yuki2クラスのインスタンス)を取ったメソッドもしくはブロック
31
+ #として記述する。
32
+ class Yuki
33
+ #==キャンセルを示す構造体
34
+ #コマンド選択がキャンセルされたときに生成される構造体
35
+ Canseled = Struct.new(:dummy)
36
+
37
+ #==Yuki実行管理クラス(外部クラスからの管理用)
38
+ #実行中のYukiの管理を行うためのクラス
39
+ #インスタンスは、Yuki#getmanager メソッドを呼ぶことで取得する
40
+ class Manager
41
+ #===インスタンスの作成
42
+ #実際にインスタンスを生成するときは、Yuki#manager メソッドを呼ぶこと
43
+ #_yuki_:: 管理対象の Yuki モジュールを mixin したクラスのインスタンス
44
+ #_plot_proc_:: プロットメソッド・プロシージャインスタンス。デフォルトは nil
45
+ #_with_update_input_:: Yuki#updateメソッドを呼び出した時、同時にYuki#update_plot_inputメソッドを呼び出すかどうかを示すフラグ。デフォルトはfalse
46
+ #_use_thread_:: スレッドを使ったポーズやタイマー待ちの監視を行うかを示すフラグ。デフォルトはfalse
47
+ def initialize(yuki, plot_proc, with_update_input = true, use_thread = false)
48
+ @with_update_input = with_update_input
49
+ @use_thread = use_thread
50
+ @yuki_instance = yuki
51
+ @yuki_plot = plot_proc
52
+ end
53
+
54
+ #===プロット処理を開始する
55
+ def start
56
+ @yuki_instance.start_plot(@yuki_plot, @with_update_input, @use_thread)
57
+ end
58
+
59
+ #===入力更新処理を呼び出す
60
+ def update_input
61
+ @yuki_instance.update_plot_input
62
+ end
63
+
64
+ #===更新処理を呼び出す
65
+ def update
66
+ @yuki_instance.update
67
+ end
68
+
69
+ #===描画処理を呼び出す
70
+ def render
71
+ @yuki_instance.render
72
+ end
73
+
74
+ #===プロットの実行結果を返す
75
+ #返却値:: 実行結果を示すインスタンス。デフォルトは、現在実行しているシーンのインスタンス
76
+ def result
77
+ @yuki_instance.result
78
+ end
79
+
80
+ #===コマンド選択がキャンセルされたときの結果を返す
81
+ #返却値:: キャンセルされたときはtrue、されていないときはfalseを返す
82
+ def canseled?
83
+ return @yuki_instance.canseled?
84
+ end
85
+
86
+ #===プロット処理が実行中かの問い合わせメソッド
87
+ #返却値:: 実行中の時は true を返す
88
+ def executing?
89
+ return @yuki_instance.executing?
90
+ end
91
+
92
+ #===コマンド選択中の問い合わせメソッド
93
+ #返却値:: コマンド選択中の時はtrueを返す
94
+ def selecting?
95
+ return @yuki_instance.selecting?
96
+ end
97
+
98
+ #===Yuki#waitメソッドによる処理待ちの問い合わせメソッド
99
+ #返却値:: 処理待ちの時はtrueを返す
100
+ def waiting?
101
+ return @yuki_instance.waiting?
102
+ end
103
+
104
+ #===メッセージ送り待ちの問い合わせメソッド
105
+ #返却値:: メッセージ送り待ちの時はtrueを返す
106
+ def pausing?
107
+ return @yuki_instance.pausing?
108
+ end
109
+
110
+ #===Yukiオブジェクトが使用しているオブジェクトを解放する
111
+ def dispose
112
+ @yuki_instance.dispose
113
+ @yuki_instance = nil
114
+ end
115
+ end
116
+
117
+ #==コマンド構造体
118
+ #_body_:: コマンドの名称(移動する、調べるなど、アイコンなどの画像も可)
119
+ #_body_selected_:: 選択時コマンドの名称(移動する、調べるなど、アイコンなどの画像も可)(省略時は、bodyと同一)
120
+ #_condition_:: 表示条件(ブロック)。評価の結果、trueのときのみ表示
121
+ #_result_:: 選択結果(移動先シーンクラス名、シナリオ(メソッド)名他のオブジェクト)
122
+ Command = Struct.new(:body, :body_selected, :condition, :result)
123
+
124
+ attr_accessor :update_inner, :update_text
125
+ attr_reader :parts, :diagrams, :vars
126
+
127
+ #===Yukiを初期化する
128
+ def initialize
129
+ @yuki = { }
130
+ @yuki[:text_box] = nil
131
+ @yuki[:command_box] = nil
132
+
133
+ @yuki[:btn] = {:ok => :btn1, :cansel => :btn2, :release => :btn1 }
134
+
135
+ @yuki[:plot_thread] = nil
136
+
137
+ @yuki[:exec_plot] = false
138
+ @yuki[:with_update_input] = true
139
+
140
+ @yuki[:pausing] = false
141
+ @yuki[:selecting] = false
142
+ @yuki[:waiting] = false
143
+
144
+ @yuki[:pause_release] = false
145
+ @yuki[:select_ok] = false
146
+ @yuki[:select_cansel] = false
147
+ @yuki[:select_amount] = [0, 0]
148
+
149
+ @yuki[:result] = nil
150
+ @yuki[:plot_result] = nil
151
+
152
+ @update_inner = lambda{|yuki|}
153
+ @update_text = lambda{|yuki|}
154
+ @mutex = Mutex.new
155
+
156
+ @parts = {}
157
+ @visible = []
158
+ @diagrams = {}
159
+ @vars = {}
160
+
161
+ @is_outer_height = self.method(:is_outer_height)
162
+ end
163
+
164
+ #===Yuki#showで表示指定した画像を描画する
165
+ #描画順は、showメソッドで指定した順に描画される(先に指定した画像は後ろに表示される)
166
+ #返却値:: 自分自身を返す
167
+ def render
168
+ @visible.each{|name|
169
+ @parts[name].render if @parts.has_key?(name)
170
+ @diagrams[name].render if @diagrams.has_key?(name)
171
+ }
172
+ return self
173
+ end
174
+
175
+ #===オブジェクトを登録する
176
+ #オブジェクトをパーツnameとして登録する。
177
+ #Yuki::parts[name]で参照可能
178
+ #:name:: パーツ名(シンボル)
179
+ #:parts:: 登録対象のインスタンス
180
+ #
181
+ #返却値:: 自分自身を返す
182
+ def regist_parts(name, parts)
183
+ @parts[name] = parts
184
+ return self
185
+ end
186
+
187
+ #===表示・描画対象のテキストボックスを選択する
188
+ #:box:: テキストボックスのインスタンス
189
+ #
190
+ #返却値:: 自分自身を返す
191
+ def select_textbox(box)
192
+ @yuki[:text_box] = box
193
+ return self
194
+ end
195
+
196
+ #===表示・描画対象のコマンドボックスを選択する
197
+ #:box:: テキストボックスのインスタンス
198
+ #
199
+ #返却値:: 自分自身を返す
200
+ def select_commandbox(box)
201
+ @yuki[:command_box] = box
202
+ return self
203
+ end
204
+
205
+ #===遷移図を登録する
206
+ #遷移図をパーツnameとして登録する。
207
+ #遷移図を登録すると、update_inputメソッドがYuki2::update_plotメソッドを呼び出した時に
208
+ #自動的に呼び出される(renderメソッドは呼ばれないことに注意!)。
209
+ #Yuki::diagrams[name]で参照可能
210
+ #:name:: パーツ名(シンボル)
211
+ #:diagram:: 登録対象の遷移図インスタンス
212
+ #
213
+ #返却値:: 自分自身を返す
214
+ def regist_diagram(name, diagram)
215
+ @diagrams[name] = diagram
216
+ return self
217
+ end
218
+
219
+ #===オブジェクトの登録を解除する
220
+ #パーツnameとして登録されているオブジェクトを登録から解除する。
221
+ #:name:: パーツ名(シンボル)
222
+ #
223
+ #返却値:: 自分自身を返す
224
+ def remove_parts(name)
225
+ @parts.delete(name)
226
+ return self
227
+ end
228
+
229
+ #===遷移図の登録を解除する
230
+ #パーツnameとして登録されている遷移図を登録から解除する。
231
+ #:name:: パーツ名(シンボル)
232
+ #
233
+ #返却値:: 自分自身を返す
234
+ def remove_diagram(name)
235
+ @diagrams.delete(@parts[name])
236
+ return self
237
+ end
238
+
239
+ #===パーツで指定したオブジェクトを先頭に表示する
240
+ #描画時に、指定したパーツを描画する
241
+ #すでにshowメソッドで表示指定している場合は、先頭に表示させる
242
+ #:names:: パーツ名(シンボル)、複数指定可能(指定した順番に描画される)
243
+ #返却値:: 自分自身を返す
244
+ def show(*names)
245
+ names.each{|name|
246
+ @visible.delete(name)
247
+ @visible << name
248
+ }
249
+ return self
250
+ end
251
+
252
+ #===パーツで指定したオブジェクトを隠蔽する
253
+ #描画時に、指定したパーツを描画させないよう指定する
254
+ #:names:: パーツ名(シンボル)、複数指定可能
255
+ #返却値:: 自分自身を返す
256
+ def hide(*names)
257
+ names.each{|name| @visible.delete(name) }
258
+ return self
259
+ end
260
+
261
+ #===パーツで指定したオブジェクトの処理を開始する
262
+ #nameで指定したパーツが持つ処理を隠蔽する。
263
+ #(但し、パーツで指定したオブジェクトがstartメソッドを持つことが条件)
264
+ #:name:: パーツ名(シンボル)
265
+ #返却値:: 自分自身を返す
266
+ def start(name)
267
+ @parts[name].start
268
+ return self
269
+ end
270
+
271
+ #===パーツで指定したオブジェクトを再生する
272
+ #nameで指定したパーツを再生する。
273
+ #(但し、パーツで指定したオブジェクトがplayメソッドを持つことが条件)
274
+ #:name:: パーツ名(シンボル)
275
+ #返却値:: 自分自身を返す
276
+ def play(name)
277
+ @parts[name].play
278
+ return self
279
+ end
280
+
281
+ #===パーツで指定したオブジェクトの処理を停止する
282
+ #nameで指定したパーツが持つ処理を停止する。
283
+ #(但し、パーツで指定したオブジェクトがstopメソッドを持つことが条件)
284
+ #:name:: パーツ名(シンボル)
285
+ #返却値:: 自分自身を返す
286
+ def stop(name)
287
+ @parts[name].stop
288
+ return self
289
+ end
290
+
291
+ #===遷移図の処理が終了するまで待つ
292
+ #nameで指定した遷移図の処理が終了するまで、プロットを停止する
293
+ #:name:: 遷移図名(シンボル)
294
+ #返却値:: 自分自身を返す
295
+ def wait_by_finish(name)
296
+ until @parts[name].finish?
297
+ @update_inner.call(self)
298
+ Thread.pass unless Thread.current.eql?(Thread.main)
299
+ end
300
+ return self
301
+ end
302
+
303
+ #===各ボタンの設定リストを出力する
304
+ #コマンド決定・キャンセル時に使用するボタンの一覧をシンボルのハッシュとして返す。ハッシュの内容は以下の通り
305
+ #ハッシュキー:: 説明:: デフォルト
306
+ #:release:: メッセージ待ちを終了するときに押すボタン:: :btn1
307
+ #:ok:: コマンド選択で「決定」するときに押すボタン:: btn1
308
+ #:cansel:: コマンド選択で「キャンセル」するときに押すボタン:: btn2
309
+ #
310
+ #返却値:: ボタンの設定リスト
311
+ def button
312
+ return @yuki[:btn]
313
+ end
314
+
315
+ #===シーンのセットアップ時に実行する処理
316
+ #
317
+ #返却値:: あとで書く
318
+ def setup
319
+ @yuki[:plot_result] = nil
320
+
321
+ @yuki[:exec_plot] = false
322
+
323
+ @yuki[:pausing] = false
324
+ @yuki[:selecting] = false
325
+ @yuki[:waiting] = false
326
+
327
+ @yuki[:pause_release] = false
328
+ @yuki[:select_ok] = false
329
+ @yuki[:select_cansel] = false
330
+ @yuki[:select_amount] = [0, 0]
331
+
332
+ @yuki[:result] = nil
333
+ @yuki[:plot_result] = nil
334
+ end
335
+
336
+ #===プロット処理を実行する(明示的に呼び出す必要がある場合)
337
+ #引数もしくはブロックで指定したプロット処理を非同期に実行する。
338
+ #呼び出し可能なプロットは以下の3種類。(上から優先度が高い順)
339
+ #
340
+ #1)引数prot_proc(Procクラスのインスタンス)
341
+ #
342
+ #2)ブロック引数
343
+ #
344
+ #3)Yuki#plotメソッド
345
+ #
346
+ #_plot_proc_:: プロットの実行部をインスタンス化したオブジェクト
347
+ #_with_update_input_:: Yuki#updateメソッドを呼び出した時、同時にYuki#update_plot_inputメソッドを呼び出すかどうかを示すフラグ。デフォルトはfalse
348
+ #_use_thread_:: スレッドを使ったポーズやタイマー待ちの監視を行うかを示すフラグ。デフォルトはfalse
349
+ #返却値:: あとで書く
350
+ def start_plot(plot_proc = nil, with_update_input = true, use_thread = false, &plot_block)
351
+ raise MiyakoError, "Yuki Error! Textbox is not selected!" unless @yuki[:text_box]
352
+ raise MiyakoError, "Yuki Error! Plot must have one parameter!" if plot_proc && plot_proc.arity != 1
353
+ raise MiyakoError, "Yuki Error! Plot must have one parameter!" if plot_block && plot_block.arity != 1
354
+ @yuki[:text_box].exec{ plot_facade(plot_proc, &plot_block) }
355
+ until @yuki[:exec_plot] do; end
356
+ @yuki[:plot_thread] = Thread.new{ update_plot_thread } if use_thread
357
+ @yuki[:with_update_input] = with_update_input
358
+ return self
359
+ end
360
+
361
+ #===プロット処理を更新する
362
+ #ポーズ中、コマンド選択中、 Yuki#wait メソッドによるウェイトの状態確認を行う。
363
+ #プロット処理の実行確認は出来ない
364
+ def update
365
+ return unless @yuki[:exec_plot]
366
+ update_plot_input if @yuki[:with_update_input]
367
+ unless @yuki[:plot_thread]
368
+ pausing if @yuki[:pausing]
369
+ selecting if @yuki[:selecting]
370
+ waiting if @yuki[:waiting]
371
+ end
372
+ @diagrams.each_value{|dia|
373
+ dia.update_input
374
+ dia.update if dia.sync?
375
+ }
376
+ @mutex.lock
377
+ @yuki[:pause_release] = false
378
+ @yuki[:select_ok] = false
379
+ @yuki[:select_cansel] = false
380
+ @yuki[:select_amount] = [0, 0]
381
+ @mutex.unlock
382
+ end
383
+
384
+ def update_plot_thread #:nodoc:
385
+ while @yuki[:exec_plot]
386
+ pausing if @yuki[:pausing]
387
+ selecting if @yuki[:selecting]
388
+ waiting if @yuki[:waiting]
389
+ Thread.pass
390
+ end
391
+ end
392
+
393
+ #===プロット用メソッドをYukiへ渡すためのインスタンスを作成する
394
+ #プロット用に用意したメソッド(引数一つのメソッド)を、Yukiでの選択結果や移動先として利用できる
395
+ #インスタンスに変換する
396
+ #(指定のメソッドをMethodクラスのインスタンスに変換する)
397
+ #_instance_:: 対象のメソッドが含まれているインスタンス(レシーバ)
398
+ #_method_:: メソッド名(シンボルまたは文字列)
399
+ #返却値:: 生成したインスタンスを返す
400
+ def to_plot(instance, method)
401
+ return instance.method(method.to_sym)
402
+ end
403
+
404
+ #===プロット処理に使用する入力情報を更新する
405
+ #ポーズ中、コマンド選択中に使用する入力デバイスの押下状態を更新する
406
+ #(但し、プロット処理の実行中にのみ更新する)
407
+ #Yuki#update メソッドをそのまま使う場合は呼び出す必要がないが、 Yuki#exec_plot メソッドを呼び出す
408
+ #プロット処理の場合は、メインスレッドから明示的に呼び出す必要がある
409
+ #返却値:: nil を返す
410
+ def update_plot_input
411
+ return nil unless @yuki[:exec_plot]
412
+ if @yuki[:pausing] && Input.pushed_all?(@yuki[:btn][:ok])
413
+ @yuki[:pause_release] = true
414
+ elsif @yuki[:selecting]
415
+ @yuki[:select_ok] = true if Input.pushed_all?(@yuki[:btn][:ok])
416
+ @yuki[:select_cansel] = true if Input.pushed_all?(@yuki[:btn][:cansel])
417
+ @yuki[:select_amount] = Input.pushed_amount
418
+ end
419
+ return nil
420
+ end
421
+
422
+ #===プロット処理を外部クラスから管理するインスタンスを取得する
423
+ #
424
+ #1)引数prot_proc(Procクラスのインスタンス)
425
+ #
426
+ #2)ブロック引数
427
+ #
428
+ #3)Yuki#plotメソッド
429
+ #
430
+ #_plot_proc_:: プロットの実行部をインスタンス化したオブジェクト
431
+ #_with_update_input_:: Yuki#updateメソッドを呼び出した時、同時にYuki#update_plot_inputメソッドを呼び出すかどうかを示すフラグ。デフォルトはfalse
432
+ #_use_thread_:: スレッドを使ったポーズやタイマー待ちの監視を行うかを示すフラグ。デフォルトはfalse
433
+ #返却値:: YukiManager クラスのインスタンス
434
+ def manager(plot_proc = nil, with_update_input = true, use_thread = false, &plot_block)
435
+ return Manager.new(self, plot_proc || plot_block, with_update_input, use_thread)
436
+ end
437
+
438
+ def plot_facade(plot_proc = nil, &plot_block) #:nodoc:
439
+ @mutex.lock
440
+ @yuki[:plot_result] = nil
441
+ @yuki[:exec_plot] = true
442
+ @mutex.unlock
443
+ @yuki[:plot_result] = plot_proc ? plot_proc.call(self) : plot_block.call(self)
444
+ @diagrams.each_value{|dia| dia.stop }
445
+ @mutex.lock
446
+ @yuki[:exec_plot] = false
447
+ if @yuki[:plot_thread]
448
+ @yuki[:plot_thread].join
449
+ @yuki[:plot_thread] = nil
450
+ end
451
+ @mutex.unlock
452
+ end
453
+
454
+ #===プロット処理が実行中かどうかを確認する
455
+ #返却値:: プロット処理実行中の時はtrueを返す
456
+ def executing?
457
+ return @yuki[:exec_plot]
458
+ end
459
+
460
+ #===プロットの処理結果を返す
461
+ #プロット処理の結果を返す。
462
+ #まだ結果が得られていない場合はnilを得る
463
+ #プロット処理が終了していないのに結果を得られるので注意!
464
+ #返却値:: プロットの処理結果
465
+ def result
466
+ return @yuki[:plot_result]
467
+ end
468
+
469
+ #===プロット処理の結果を設定する
470
+ #_ret_:: 設定する結果。デフォルトはnil
471
+ #返却値:: 自分自身を返す
472
+ def result=(ret = nil)
473
+ @yuki[:plot_result] = ret
474
+ return self
475
+ end
476
+
477
+ #===結果がシーンかどうかを問い合わせる
478
+ #結果がシーン(シーンクラス名)のときはtrueを返す
479
+ #対象の結果は、選択結果、プロット処理結果ともに有効
480
+ #返却値:: 結果がシーンかどうか(true/false)
481
+ def is_scene?(result)
482
+ return (result.class == Class && result.include?(Story::Scene))
483
+ end
484
+
485
+ #===結果がシナリオかどうかを問い合わせる
486
+ #結果がシナリオ(メソッド)のときはtrueを返す
487
+ #対象の結果は、選択結果、プロット処理結果ともに有効
488
+ #返却値:: 結果がシナリオかどうか(true/false)
489
+ def is_scenario?(result)
490
+ return (result.kind_of?(Proc) || result.kind_of?(Method))
491
+ end
492
+
493
+ #===コマンド選択がキャンセルされたときの結果を返す
494
+ #返却値:: キャンセルされたときはtrue、されていないときはfalseを返す
495
+ def canseled?
496
+ return result == @yuki[:cansel]
497
+ end
498
+
499
+ #===ブロックを条件として設定する
500
+ #メソッドをMethodクラスのインスタンスに変換する
501
+ #_block_:: シナリオインスタンスに変換したいメソッド名(シンボル)
502
+ #返却値:: シナリオインスタンスに変換したメソッド
503
+ def condition(&block)
504
+ return block
505
+ end
506
+
507
+ #===コマンド選択中の問い合わせメソッド
508
+ #返却値:: コマンド選択中の時はtrueを返す
509
+ def selecting?
510
+ return @yuki[:selecting]
511
+ end
512
+
513
+ #===Yuki#waitメソッドによる処理待ちの問い合わせメソッド
514
+ #返却値:: 処理待ちの時はtrueを返す
515
+ def waiting?
516
+ return @yuki[:waiting]
517
+ end
518
+
519
+ #===メッセージ送り待ちの問い合わせメソッド
520
+ #返却値:: メッセージ送り待ちの時はtrueを返す
521
+ def pausing?
522
+ return @yuki[:pausing]
523
+ end
524
+
525
+ #===条件に合っていればポーズをかける
526
+ #引数で設定した条件(Proc,メソッドインスタンス,ブロック)を評価した結果、trueのときはポーズを行い、
527
+ #condの値がnilで、ブロックが渡されていないときは何もしない
528
+ #falseのときは改行してプロットの処理を継続する
529
+ #_cond_:: 条件を示すオブジェクト(返却値はtrue/false)。デフォルトはnil(渡されたブロックを評価する)
530
+ #返却値:: 自分自身を返す
531
+ def wait_by_cond(cond = nil)
532
+ return yield ? pause_and_clear : cr if block_given?
533
+ return cond.call ? pause_and_clear : cr if cond
534
+ return self
535
+ end
536
+
537
+ #===テキストボックスに文字を表示する
538
+ #_txt_:: 表示させるテキスト
539
+ #返却値:: 自分自身を返す
540
+ def text(txt)
541
+ return self if txt.eql?(self)
542
+ txt.chars{|ch|
543
+ if /[\n\r]/.match(ch)
544
+ next wait_by_cond(@is_outer_height)
545
+ elsif @yuki[:text_box].locate.x + @yuki[:text_box].font.text_size(ch)[0] >= @yuki[:text_box].textarea.w
546
+ wait_by_cond(@is_outer_height)
547
+ elsif /[\t\f]/.match(ch)
548
+ next nil
549
+ end
550
+ @yuki[:text_box].draw_text(ch)
551
+ @update_text.call(self)
552
+ }
553
+ return self
554
+ end
555
+
556
+ def is_outer_height #:nodoc:
557
+ return @yuki[:text_box].locate.y + @yuki[:text_box].max_height >= @yuki[:text_box].textarea.h
558
+ end
559
+
560
+ private :is_outer_height
561
+
562
+ #===文字色を変更する
563
+ #ブロック内で指定した文字列を、指定の色で描画する
564
+ #_color_:: 文字色
565
+ #返却値:: 自分自身を返す
566
+ def color(color, &block)
567
+ @yuki[:text_box].color_during(Color.to_rgb(color)){ text block.call }
568
+ return self
569
+ end
570
+
571
+ #===文字の大きさを変更する
572
+ #ブロック内で指定した文字列を、指定の大きさで描画する
573
+ #_size_:: 文字の大きさ(整数)
574
+ #返却値:: 自分自身を返す
575
+ def size(size, &block)
576
+ @yuki[:text_box].font_size(size){
577
+ @yuki[:text_box].margin_during(@yuki[:text_box].margin_height(:middle)){ text block.call }
578
+ }
579
+ return self
580
+ end
581
+
582
+ #===太文字を描画する
583
+ #ブロック内で指定した文字列を太文字で表示する
584
+ #(使用すると文字の端が切れてしまう場合あり!)
585
+ #返却値:: 自分自身を返す
586
+ def bold(&block)
587
+ @yuki[:text_box].font_bold{ text block.call }
588
+ return self
589
+ end
590
+
591
+ #===斜体文字を描画する
592
+ #ブロック内で指定した文字列を斜体で表示する
593
+ #(使用すると文字の端が切れてしまう場合あり!)
594
+ #返却値:: 自分自身を返す
595
+ def italic(&block)
596
+ @yuki[:text_box].font_italic{ text block.call }
597
+ return self
598
+ end
599
+
600
+ #===下線付き文字を描画する
601
+ #ブロック内で指定した文字列を下線付きで表示する
602
+ #返却値:: 自分自身を返す
603
+ def under_line(&block)
604
+ @yuki[:text_box].font_under_line{ text block.call }
605
+ return self
606
+ end
607
+
608
+ #===改行を行う
609
+ #返却値:: 自分自身を返す
610
+ def cr
611
+ @yuki[:text_box].cr
612
+ return self
613
+ end
614
+
615
+ #===テキストボックスの内容を消去する
616
+ #返却値:: 自分自身を返す
617
+ def clear
618
+ @yuki[:text_box].clear
619
+ return self
620
+ end
621
+
622
+ #===ポーズを行う
623
+ #ポーズが行われると、ポーズ用のカーソルが表示される
624
+ #所定のボタンを押すとポーズが解除され、カーソルが消える
625
+ #解除後は、プロットの続きを処理する
626
+ #返却値:: 自分自身を返す
627
+ def pause
628
+ @yuki[:text_box].pause
629
+ @mutex.lock
630
+ @yuki[:pausing] = true
631
+ @mutex.unlock
632
+ while @yuki[:pausing]
633
+ @update_inner.call(self)
634
+ Thread.pass unless Thread.current.eql?(Thread.main)
635
+ end
636
+ return self
637
+ end
638
+
639
+ def pausing #:nodoc:
640
+ return unless @yuki[:pause_release]
641
+ @yuki[:text_box].release
642
+ @mutex.lock
643
+ @yuki[:pausing] = false
644
+ @yuki[:pause_release] = false
645
+ @mutex.unlock
646
+ end
647
+
648
+ #===ポーズをかけて、テキストボックスの内容を消去する
649
+ #ポーズをかけ、ポーズを解除するときにテキストボックスの内容を消去する
650
+ #返却値:: 自分自身を返す
651
+ def pause_and_clear
652
+ return pause.clear
653
+ end
654
+
655
+ #===コマンドを表示する
656
+ #表示対象のコマンド群をCommand構造体の配列で示す。
657
+ #キャンセルのときの結果も指定可能(既定ではキャンセル不可状態)
658
+ #body_selectedをnilにした場合は、bodyと同一となる
659
+ #body_selectedを文字列を指定した場合は、文字色が赤色になることに注意
660
+ #_command_list_:: 表示するコマンド群。各要素はCommand構造体の配列
661
+ #_cansel_to_:: キャンセルボタンを押したときの結果。デフォルトはnil(キャンセル無効)
662
+ #_chain_block_:: コマンドの表示方法。あとで書く
663
+ #返却値:: 自分自身を返す
664
+ def command(command_list, cansel_to = Canseled, &chain_block)
665
+ raise MiyakoError, "Yuki Error! Commandbox is not selected!" unless @yuki[:command_box]
666
+ @yuki[:cansel] = cansel_to
667
+
668
+ choices = []
669
+ command_list.each{|cm| choices.push([cm[:body], cm[:body_selected], cm[:result]]) if (cm[:condition] == nil || cm[:condition].call) }
670
+ return self if choices.length == 0
671
+
672
+ @yuki[:command_box].command(@yuki[:command_box].create_choices_chain(choices, &chain_block))
673
+ @mutex.lock
674
+ @yuki[:result] = nil
675
+ @yuki[:selecting] = true
676
+ @mutex.unlock
677
+ while @yuki[:selecting]
678
+ @update_inner.call(self)
679
+ Thread.pass unless Thread.current.eql?(Thread.main)
680
+ end
681
+ return self
682
+ end
683
+
684
+ def selecting #:nodoc:
685
+ return unless @yuki[:selecting]
686
+ exit if $miyako_debug_mode && Input.quit_or_escape?
687
+ if @yuki[:command_box].selecting?
688
+ if @yuki[:select_ok]
689
+ @mutex.lock
690
+ @yuki[:result] = @yuki[:command_box].result
691
+ @mutex.unlock
692
+ @yuki[:command_box].finish_command
693
+ @yuki[:text_box].release
694
+ @mutex.lock
695
+ @yuki[:selecting] = false
696
+ @mutex.unlock
697
+ reset_selecting
698
+ elsif @yuki[:select_cansel]
699
+ @mutex.lock
700
+ @yuki[:result] = @yuki[:cansel]
701
+ @mutex.unlock
702
+ @yuki[:command_box].finish_command
703
+ @yuki[:text_box].release
704
+ @mutex.lock
705
+ @yuki[:selecting] = false
706
+ @mutex.unlock
707
+ reset_selecting
708
+ elsif @yuki[:select_amount] != [0,0]
709
+ @yuki[:command_box].move_cursor(*@yuki[:select_amount])
710
+ reset_selecting
711
+ end
712
+ end
713
+ end
714
+
715
+ def reset_selecting #:nodoc:
716
+ @mutex.lock
717
+ @yuki[:select_ok] = false
718
+ @yuki[:select_cansel] = false
719
+ @yuki[:select_amount] = [0, 0]
720
+ @mutex.unlock
721
+ end
722
+
723
+ #===コマンドの選択結果を返す
724
+ #コマンド選択の結果を返す。
725
+ #まだ結果が得られていない場合はnilを得る
726
+ #プロット処理・コマンド選択が終了していないのに結果を得られるので注意!
727
+ #返却値:: コマンドの選択結果
728
+ def select_result
729
+ return @yuki[:result]
730
+ end
731
+
732
+ #===プロットの処理を待機する
733
+ #指定の秒数(少数可)、プロットの処理を待機する。
734
+ #_length_:: 待機する長さ。単位は秒。少数可。
735
+ #返却値:: 自分自身を返す
736
+ def wait(length)
737
+ @waiting_timer = WaitCounter.new(length)
738
+ @waiting_timer.start
739
+ @mutex.lock
740
+ @yuki[:waiting] = true
741
+ @mutex.unlock
742
+ while @yuki[:waiting]
743
+ @update_inner.call(self)
744
+ Thread.pass unless Thread.current.eql?(Thread.main)
745
+ end
746
+ return self
747
+ end
748
+
749
+ def waiting #:nodoc:
750
+ return if @waiting_timer.waiting?
751
+ @mutex.lock
752
+ @yuki[:waiting] = false
753
+ @mutex.unlock
754
+ end
755
+
756
+ #===インスタンスで使用しているオブジェクトを解放する
757
+ def dispose
758
+ @yuki.clear
759
+ @yuki = nil
760
+
761
+ @update_inner = nil
762
+ @update_text = nil
763
+ @mutex = nil
764
+
765
+ @parts.clear
766
+ @parts = nil
767
+ @visible.clear
768
+ @visible = nil
769
+ @diagrams.clear
770
+ @diagrams = nil
771
+ @vars.clear
772
+ @vars = nil
773
+
774
+ @is_outer_height = nil
775
+ end
776
+
777
+ private :button
778
+ end
779
+ end