cyross-ruby-miyako 2.0.5.1.0 → 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,300 +1,350 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
- =begin
4
- --
5
- Miyako v2.0
6
- Copyright (C) 2007-2009 Cyross Makoto
7
-
8
- This library is free software; you can redistribute it and/or
9
- modify it under the terms of the GNU Lesser General Public
10
- License as published by the Free Software Foundation; either
11
- version 2.1 of the License, or (at your option) any later version.
12
-
13
- This library is distributed in the hope that it will be useful,
14
- but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
- Lesser General Public License for more details.
17
-
18
- You should have received a copy of the GNU Lesser General Public
19
- License along with this library; if not, write to the Free Software
20
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
- ++
22
- =end
23
-
24
- module Miyako
25
-
26
- #==シーン実行クラス
27
- #用意したシーンインスタンスを実行
28
- class Story
29
- @@sub_scenes = [:sub_scene, :sub_routine]
30
- @@over_scenes = [:over_scene]
31
-
32
- def prev_label #:nodoc:
33
- return @prev_label
34
- end
35
-
36
- def next_label #:nodoc:
37
- return @next_label
38
- end
39
-
40
- def upper_label #:nodoc:
41
- return @stack.empty? ? nil : @stack.last[0]
42
- end
43
-
44
- #===インスタンスの作成
45
- #ストーリー情報の初期か
46
- #返却値:: 生成したインスタンス
47
- def initialize
48
- @prev_label = nil
49
- @next_label = nil
50
-
51
- @stack = []
52
- @fibers = [nil]
53
-
54
- @scene_cache = Hash.new
55
- @scene_cache_list = Array.new
56
- @scene_cache_max = 20
57
-
58
- @fiber = Proc.new{|sc, num|
59
- raise MiyakoError, "Illegal Script-label name! : #{sc}" unless Scene.has_scene?(sc.to_s)
60
- fnum = nil
61
- bk_nn = sc
62
- uu = sc.new(self)
63
- uu.init_inner(@prev_label, self.upper_label)
64
- uu.setup
65
- ret = true
66
- while ret do
67
- nn = uu.update
68
- uu.render
69
- if fnum && @fibers[fnum]
70
- @fibers[fnum].resume(true)
71
- elsif nn && !(nn.eql?(uu.class)) && @@over_scenes.include?(nn.scene_type)
72
- @fibers << Fiber.new(&@fiber)
73
- fnum = @fibers.length-1
74
- @fibers[fnum].resume(nn, fnum)
75
- n = bk_nn
76
- end
77
- break unless nn
78
- ret = Fiber.yield
79
- end
80
- uu.final
81
- uu.dispose
82
- if (fnum && @fibers[fnum])
83
- @fibers[fnum].resume(nil)
84
- @fibers[fnum] = nil
85
- fnum = nil
86
- end
87
- @fibers[num] = nil
88
- }
89
- end
90
-
91
- def get_scene(n, s) #:nodoc:
92
- class_symbol = n.to_s
93
- if @scene_cache_list.length == @scene_cache_max
94
- del_symbol = @scene_cache_list.shift
95
- @scene_cache[del_symbol].dispose
96
- @scene_cache.delete(del_symbol)
97
- end
98
- @scene_cache_list.delete(class_symbol)
99
- @scene_cache_list.push(class_symbol)
100
- @scene_cache[class_symbol] ||= n.new(self)
101
- return @scene_cache[class_symbol]
102
- end
103
-
104
- #===Storyの実行を始める
105
- #"obj.run(MainScene)"と記述すると、SceneモジュールをmixinしたMainSceneクラスのインスタンスを作成し、評価を始める
106
- #_n_:: 最初に実行するシーン名(クラス名を定数で)
107
- def run(n)
108
- return nil if n == nil
109
- u = nil
110
- on = nil
111
- @stack = Array.new # reset
112
- while n != nil
113
- @prev_label = on
114
- on = n
115
-
116
- raise MiyakoError, "Illegal Script-label name! : #{n}" unless Scene.has_scene?(n.to_s)
117
- raise MiyakoError, "This scene cannot use for Standard Scene! : #{n}" if n.scene_type != :scene
118
- u = get_scene(n, @stack.size) if u == nil
119
- u.init_inner(@prev_label, self.upper_label)
120
- u.setup
121
-
122
- loop do
123
- Input.update
124
- Screen.clear
125
- bk_n = on
126
- n = u.update
127
- u.render
128
- if @fibers.first
129
- raise MiyakoError, "Double over scene from root!" if n && @@over_scenes.include?(n.scene_type)
130
- @fibers.first.resume(true, 0)
131
- elsif n && @@over_scenes.include?(n.scene_type)
132
- @fibers.clear
133
- @fibers << Fiber.new(&@fiber)
134
- @fibers.first.resume(n, 0)
135
- n = bk_n
136
- end
137
- Screen.render
138
- break unless n && on.eql?(n)
139
- end
140
- u.next = n
141
- @next_label = n
142
- u.final
143
- if n == nil
144
- if @@sub_scenes.include?(u.class.scene_type) && @stack.empty? == false
145
- n, u = @stack.pop
146
- next
147
- end
148
- break
149
- elsif @@sub_scenes.include?(n.scene_type)
150
- @stack.push([on, u])
151
- u = nil
152
- else
153
- u = nil
154
- end
155
- end
156
- if @fibers.length > 0
157
- @fibers.each{|fiber| fiber.resume(nil) if fiber }
158
- end
159
- @scene_cache_list.each{|sy| @scene_cache[sy].dispose }
160
- @scene_cache.clear
161
- @scene_cache_list.clear
162
- end
163
-
164
- #==="over_scene"形式のシーンが実行中かどうか判別する
165
- #返却値:: "over_scene"形式のシーンが実行中の時はtrueを返す
166
- def over_scene_execute?
167
- return @now_fiber != nil
168
- end
169
-
170
- #===内部の情報を解放する
171
- def dispose
172
- @scene_cache.keys.each{|k| @scene_cache[del_symbol].dispose }
173
- end
174
-
175
- #==シーンモジュール
176
- #本モジュールをmixinすることにより、シーンを示すインスタンスを作成することができる
177
- #mixinするときに気をつけなければいけないのは、本モジュールでは以下のインスタンス変数・モジュール変数を
178
- #予約しているため、これらの変数の値を勝手に変えてはいけない
179
- #@@scenesモジュール変数(シーンクラス一覧が入っている配列)、@storyインスタンス変数(シーンを呼び出したStoryクラスインスタンス)
180
- #@nowインスタンス変数(現在評価しているシーンクラス)、@preインスタンス変数(一つ前に評価していたシーンクラス)
181
- #@upperインスタンス変数(sub_routineの呼び元シーンクラス)、@nextインスタンス変数(移動先のシーンクラス)
182
- #また、シーンには「シーン形式」がある。
183
- #種類は、シーケンスな移動が出来る「通常シーン」、終了したときに移動元に戻る「サブシーン」、
184
- #現在実行中のシーン上で並行に実行する「オーバーシーン」の3種類。
185
- #デフォルトは「通常シーン」となっている。
186
- #判別は、scene_typeクラスメソッドを呼び出すことで可能。デフォルトは、通常シーンを示すシンボル":scene"が返る。
187
- #形式を変えるには、scene_typeクラスメソッドをオーバーライドし、返却値を変える。
188
- #サブシーンの時はシンボル":sub_scene"、オーバーシーンのときはシンボル":over_scene"を返すように実装する
189
- #(注1)同じクラス名のシーンを繰り返し実行したいときは、いったん別のダミーシーンを介してから元のシーンへ移動する必要がある
190
- #(注2)オーバーシーン内では、シーンの移動が出来ないが、入れ子形式で別のオーバーシーンを積み上げる形なら移動可能。
191
- module Scene
192
- @@scenes = {}
193
-
194
- def Scene.included(c) #:nodoc:
195
- unless c.singleton_methods.include?(:scene_type)
196
- def c.scene_type
197
- return :scene
198
- end
199
- end
200
- @@scenes[c.to_s] = c
201
- end
202
-
203
- def Scene.scenes #:nodoc:
204
- return @@scenes
205
- end
206
-
207
- def Scene.has_scene?(s) #:nodoc:
208
- return @@scenes.has_key?(s)
209
- end
210
-
211
- def initialize(story, check_only=false) #:nodoc:
212
- return if check_only
213
- @story = story
214
- @now = self.class
215
- @prev = nil
216
- @upper = nil
217
- @next = nil
218
- self.init
219
- end
220
-
221
- def init_inner(p, u) #:nodoc:
222
- @prev = p
223
- @upper = u
224
- end
225
-
226
- #===シーン内で使用するオブジェクトの初期化テンプレートメソッド
227
- #シーン内で使用するインスタンスを生成するときなどにこのメソッドを実装する
228
- def init
229
- end
230
-
231
- #===シーン内で使用するオブジェクトの初期設定テンプレートメソッド
232
- #シーン内で使用するインスタンスの設定を行うときにこのメソッドを実装する
233
- #(シーン生成時に生成したインスタンスはキャッシュされ、再利用することができることに注意)
234
- def setup
235
- end
236
-
237
- #===シーンの情報を更新するテンプレートメソッド
238
- #
239
- #現在実行しているシーンを繰り返し実行する場合はインスタンス変数@nowを返すように実装する
240
- #nilを返すとシーンの処理を終了する(元のStory#runメソッド呼び出しの次に処理が移る)
241
- #但し、scene_typeメソッドの結果が:sub_routneのとき、移動元シーンに戻る
242
- #返却値:: 移動先シーンクラス
243
- def update
244
- return @now
245
- end
246
-
247
- #===シーンで指定しているインスタンスを画面に描画するテンプレートメソッド
248
- def render
249
- end
250
-
251
- #===シーン内で使用したオブジェクトの後始末を行うテンプレートメソッド
252
- #ここでは、解放処理(dispose)ではなく、終了処理(値を変更するなど)に実装する
253
- #setupメソッドと対になっているというイメージ
254
- def final
255
- end
256
-
257
- #===シーンに使用したデータの解放を記述するテンプレートメソッド
258
- #initメソッドと対になっているというイメージ
259
- def dispose
260
- end
261
-
262
- def next=(label) #:nodoc:
263
- @next = label
264
- end
265
-
266
- #==="over_scene"形式のシーンが実行中かどうか判別する
267
- #返却値:: "over_scene"形式のシーンが実行中の時はtrueを返す
268
- def over_scene_execute?
269
- return @story.over_scene_execute?
270
- end
271
-
272
- #===シーンの解説を返す(テンプレートメソッド)
273
- #Sceneモジュールをmixinしたとき、解説文を返す実装をしておくと、
274
- #Scene.#lisutupメソッドを呼び出したときに、noticeメソッドの結果を取得できる
275
- #返却値:: シーンの解説(文字列)
276
- def notice
277
- return ""
278
- end
279
-
280
- #===登録しているシーン一覧をリストアップする
281
- #リストの内容は、"シーンクラス名(文字列),シーンクラス(ポインタ),解説(noticeメソッドの内容)"という書式で取得できる
282
- #返却値:: リストアップしたシーンの配列
283
- def Scene.listup
284
- list = Array.new
285
- sns = @@scenes
286
- sns.keys.sort.each{|k| list.push("#{k}, #{sns[k]}, \"#{sns[k].notice}\"\n") }
287
- return list
288
- end
289
-
290
- #===Scene.#listupメソッドの内容をCSVファイルに保存する
291
- #_csvname_:: 保存するCSVファイルパス
292
- def Scene.listup2csv(csvfname)
293
- csvfname += ".csv" if csvfname !~ /\.csv$/
294
- list = self.listup
295
- File.open(csvfname, "w"){|f| list.each{|l| f.print l } }
296
- end
297
-
298
- end
299
- end
300
- end
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ =begin
4
+ --
5
+ Miyako v2.1
6
+ Copyright (C) 2007-2009 Cyross Makoto
7
+
8
+ This library is free software; you can redistribute it and/or
9
+ modify it under the terms of the GNU Lesser General Public
10
+ License as published by the Free Software Foundation; either
11
+ version 2.1 of the License, or (at your option) any later version.
12
+
13
+ This library is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
+ Lesser General Public License for more details.
17
+
18
+ You should have received a copy of the GNU Lesser General Public
19
+ License along with this library; if not, write to the Free Software
20
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
+ ++
22
+ =end
23
+
24
+ require 'singleton'
25
+
26
+ module Miyako
27
+ #==シーン実行クラス
28
+ #用意したシーンインスタンスを実行
29
+ class Story
30
+
31
+ @@sub_scenes = [:sub_scene, :sub_routine]
32
+ @@over_scenes = [:over_scene]
33
+
34
+ def prev_label #:nodoc:
35
+ return @prev_label
36
+ end
37
+
38
+ def next_label #:nodoc:
39
+ return @next_label
40
+ end
41
+
42
+ def upper_label #:nodoc:
43
+ return @stack.empty? ? nil : @stack.last[0]
44
+ end
45
+
46
+ #===インスタンスの作成
47
+ #ストーリー情報の初期か
48
+ #返却値:: 生成したインスタンス
49
+ def initialize
50
+ @prev_label = nil
51
+ @next_label = nil
52
+
53
+ @stack = []
54
+ @fibers = [nil]
55
+
56
+ @scene_cache = Hash.new
57
+ @scene_cache_list = Array.new
58
+ @scene_cache_max = 20
59
+
60
+ @fiber = Proc.new{|sc, num|
61
+ raise MiyakoValueError, "Illegal Script-label name! : #{sc}" unless Scene.has_scene?(sc.to_s)
62
+ fnum = nil
63
+ bk_nn = sc
64
+ uu = sc.new(self)
65
+ uu.init_inner(@prev_label, self.upper_label)
66
+ uu.setup
67
+ ret = true
68
+ while ret do
69
+ nn = uu.update
70
+ uu.render
71
+ if fnum && @fibers[fnum]
72
+ @fibers[fnum].resume(true)
73
+ elsif nn && !(nn.eql?(uu.class)) && @@over_scenes.include?(nn.scene_type)
74
+ @fibers << Fiber.new(&@fiber)
75
+ fnum = @fibers.length - 1
76
+ @fibers[fnum].resume(nn, fnum)
77
+ n = bk_nn
78
+ end
79
+ break unless nn
80
+ ret = Fiber.yield
81
+ end
82
+ uu.final
83
+ uu.dispose
84
+ if (fnum && @fibers[fnum])
85
+ @fibers[fnum].resume(nil)
86
+ @fibers[fnum] = nil
87
+ fnum = nil
88
+ end
89
+ @fibers[num] = nil
90
+ }
91
+ end
92
+
93
+ def initialize_copy(obj) #:nodoc:
94
+ @stack = @stack.dup
95
+ @fibers = @fibers.dup
96
+ @scene_cache = @scene_cache.dup
97
+ @scene_cache_list = @scene_cache_list.dup
98
+ end
99
+
100
+ def get_scene(n, s) #:nodoc:
101
+ class_symbol = n.to_s
102
+ if @scene_cache_list.length == @scene_cache_max
103
+ del_symbol = @scene_cache_list.shift
104
+ @scene_cache[del_symbol].dispose
105
+ @scene_cache.delete(del_symbol)
106
+ end
107
+ @scene_cache_list.delete(class_symbol)
108
+ @scene_cache_list.push(class_symbol)
109
+ @scene_cache[class_symbol] ||= n.new(self)
110
+ return @scene_cache[class_symbol]
111
+ end
112
+
113
+ #===Storyの実行を始める
114
+ #"obj.run(MainScene)"と記述すると、SceneモジュールをmixinしたMainSceneクラスのインスタンスを作成し、評価を始める
115
+ #_n_:: 最初に実行するシーン名(クラス名を定数で)
116
+ def run(n)
117
+ return nil if n == nil
118
+ u = nil
119
+ on = nil
120
+ @stack = Array.new # reset
121
+ while n != nil
122
+ @prev_label = on
123
+ on = n
124
+
125
+ raise MiyakoValueError, "Illegal Script-label name! : #{n}" unless Scene.has_scene?(n.to_s)
126
+ raise MiyakoValueError, "This scene cannot use for Standard Scene! : #{n}" if n.scene_type != :scene
127
+ u = get_scene(n, @stack.size) if u == nil
128
+ u.init_inner(@prev_label, self.upper_label)
129
+ u.setup
130
+
131
+ loop do
132
+ Audio.update
133
+ Input.update
134
+ Screen.clear
135
+ bk_n = on
136
+ n = u.update
137
+ u.render
138
+ if @fibers.first
139
+ raise MiyakoError, "Double over scene from root!" if n && @@over_scenes.include?(n.scene_type)
140
+ @fibers.first.resume(true, 0)
141
+ elsif n && @@over_scenes.include?(n.scene_type)
142
+ @fibers.clear
143
+ @fibers << Fiber.new(&@fiber)
144
+ @fibers.first.resume(n, 0)
145
+ n = bk_n
146
+ end
147
+ Screen.render
148
+ break unless n && on.eql?(n)
149
+ end
150
+ u.next = n
151
+ @next_label = n
152
+ u.final
153
+ if n.nil?
154
+ if @@sub_scenes.include?(u.class.scene_type) && @stack.empty? == false
155
+ n, u = @stack.pop
156
+ next
157
+ end
158
+ break
159
+ elsif @@sub_scenes.include?(n.scene_type)
160
+ @stack.push([on, u])
161
+ u = nil
162
+ else
163
+ u = nil
164
+ end
165
+ end
166
+ @fibers.each{|fiber| fiber.resume(nil) if fiber } if @fibers.length > 0
167
+ @scene_cache_list.each{|sy| @scene_cache[sy].dispose }
168
+ @scene_cache.clear
169
+ @scene_cache_list.clear
170
+ end
171
+
172
+ #==="over_scene"形式のシーンが実行中かどうか判別する
173
+ #返却値:: "over_scene"形式のシーンが実行中の時はtrueを返す
174
+ def over_scene_execute?
175
+ return @now_fiber != nil
176
+ end
177
+
178
+ #===内部の情報を解放する
179
+ def dispose
180
+ @scene_cache.keys.each{|k| @scene_cache[del_symbol].dispose }
181
+ end
182
+
183
+ #==シーン情報格納のための構造体
184
+ ScenePool = Struct.new(:story, :prev, :next, :upper)
185
+
186
+ #==シーンモジュール
187
+ #本モジュールをmixinすることにより、シーンを示すインスタンスを作成することができる
188
+ #mixinするときに気をつけなければいけないのは、本モジュールでは以下の
189
+ #モジュール変数を
190
+ #予約しているため、これらの変数の値を勝手に変えてはいけない
191
+ #・@@scenesモジュール変数(シーンクラス一覧が入っているハッシュ)
192
+ #・@@poolモジュール変数(シーン情報が入っているハッシュ)
193
+ #(互換性のために@nowを残しているが、now_sceneのみを使うときは値を上書きしてもかまわない))
194
+ #また、シーンには「シーン形式」がある。
195
+ #種類は、シーケンスな移動が出来る「通常シーン」、終了したときに移動元に戻る「サブシーン」、
196
+ #現在実行中のシーン上で並行に実行する「オーバーシーン」の3種類。
197
+ #デフォルトは「通常シーン」となっている。
198
+ #判別は、scene_typeクラスメソッドを呼び出すことで可能。デフォルトは、
199
+ #通常シーンを示すシンボル":scene"が返る。
200
+ #形式を変えるには、scene_typeクラスメソッドをオーバーライドし、返却値を変える。
201
+ #サブシーンの時はシンボル":sub_scene"、オーバーシーンのときは
202
+ #シンボル":over_scene"を返すように実装する
203
+ #(注1)同じクラス名のシーンを繰り返し実行したいときは、いったん別のダミーシーンを
204
+ #介してから元のシーンへ移動する必要がある
205
+ #(注2)オーバーシーン内では、シーンの移動が出来ないが、入れ子形式で
206
+ #別のオーバーシーンを積み上げる形なら移動可能。
207
+ module Scene
208
+ @@scenes = {}
209
+ @@pool = {}
210
+
211
+ def Scene.included(c) #:nodoc:
212
+ unless c.singleton_methods.include?(:scene_type)
213
+ def c.scene_type
214
+ return :scene
215
+ end
216
+ end
217
+ @@scenes[c.to_s] = c
218
+ end
219
+
220
+ def Scene.scenes #:nodoc:
221
+ return @@scenes
222
+ end
223
+
224
+ def Scene.has_scene?(s) #:nodoc:
225
+ return @@scenes.has_key?(s)
226
+ end
227
+
228
+ def initialize(story, check_only=false) #:nodoc:
229
+ return if check_only
230
+ @@pool[self.object_id] = ScenePool.new(story, nil, nil, nil)
231
+ @now = self.now_scene
232
+ self.init
233
+ end
234
+
235
+ def init_inner(p, u) #:nodoc:
236
+ @@pool[self.object_id].prev = p
237
+ @@pool[self.object_id].upper = u
238
+ end
239
+
240
+ #===前回実行したシーンを返す
241
+ #前回実行しているシーンをクラス名で返す
242
+ #但し、最初のシーンの場合はnilを返す
243
+ #返却値:: 前回実行したシーン名(Classクラスインスタンス)
244
+ def story
245
+ return @@pool[self.object_id].story
246
+ end
247
+
248
+ #===サブルーチンの呼び元シーンを返す
249
+ #サブルーチンを呼び出したシーンをクラス名で返す
250
+ #サブルーチンではないときはnilを返す
251
+ #返却値:: 前回実行したシーン名(Classクラスインスタンス)
252
+ def upper_scene
253
+ return @@pool[self.object_id].upper
254
+ end
255
+
256
+ def next_scene #:nodoc:
257
+ return @@pool[self.object_id].next
258
+ end
259
+
260
+ #===前回実行したシーンを返す
261
+ #前回実行しているシーンをクラス名で返す
262
+ #但し、最初のシーンの場合はnilを返す
263
+ #返却値:: 前回実行したシーン名(Classクラスインスタンス)
264
+ def prev_scene
265
+ return @@pool[self.object_id].prev
266
+ end
267
+
268
+ #===現在実行中のシーンを返す
269
+ #現在実行しているシーンをクラス名で返す
270
+ #返却値:: 前回実行したシーン名(Classクラスインスタンス)
271
+ def now_scene
272
+ return self.class
273
+ end
274
+
275
+ #===シーン内で使用するオブジェクトの初期化テンプレートメソッド
276
+ #シーン内で使用するインスタンスを生成するときなどにこのメソッドを実装する
277
+ def init
278
+ end
279
+
280
+ #===シーン内で使用するオブジェクトの初期設定テンプレートメソッド
281
+ #シーン内で使用するインスタンスの設定を行うときにこのメソッドを実装する
282
+ #(シーン生成時に生成したインスタンスはキャッシュされ、再利用することができることに注意)
283
+ def setup
284
+ end
285
+
286
+ #===シーンの情報を更新するテンプレートメソッド
287
+ #
288
+ #現在実行しているシーンを繰り返し実行する場合はインスタンス変数@nowを返すように実装する
289
+ #nilを返すとシーンの処理を終了する(元のStory#runメソッド呼び出しの次に処理が移る)
290
+ #但し、scene_typeメソッドの結果が:sub_routneのとき、移動元シーンに戻る
291
+ #返却値:: 移動先シーンクラス
292
+ def update
293
+ return now_scene
294
+ end
295
+
296
+ #===シーンで指定しているインスタンスを画面に描画するテンプレートメソッド
297
+ def render
298
+ end
299
+
300
+ #===シーン内で使用したオブジェクトの後始末を行うテンプレートメソッド
301
+ #ここでは、解放処理(dispose)ではなく、終了処理(値を変更するなど)に実装する
302
+ #setupメソッドと対になっているというイメージ
303
+ def final
304
+ end
305
+
306
+ #===シーンに使用したデータの解放を記述するテンプレートメソッド
307
+ #initメソッドと対になっているというイメージ
308
+ def dispose
309
+ end
310
+
311
+ def next=(label) #:nodoc:
312
+ @@pool[self.object_id].next = label
313
+ end
314
+
315
+ #==="over_scene"形式のシーンが実行中かどうか判別する
316
+ #返却値:: "over_scene"形式のシーンが実行中の時はtrueを返す
317
+ def over_scene_execute?
318
+ return @story.over_scene_execute?
319
+ end
320
+
321
+ #===シーンの解説を返す(テンプレートメソッド)
322
+ #Sceneモジュールをmixinしたとき、解説文を返す実装をしておくと、
323
+ #Scene.#lisutupメソッドを呼び出したときに、noticeメソッドの結果を取得できる
324
+ #返却値:: シーンの解説(文字列)
325
+ def notice
326
+ return ""
327
+ end
328
+
329
+ #===登録しているシーン一覧をリストアップする
330
+ #リストの内容は、"シーンクラス名(文字列),シーンクラス(ポインタ),
331
+ #解説(noticeメソッドの内容)"という書式で取得できる
332
+ #返却値:: リストアップしたシーンの配列
333
+ def Scene.listup
334
+ list = Array.new
335
+ sns = @@scenes
336
+ sns.keys.sort.each{|k| list.push("#{k}, #{sns[k]}, \"#{sns[k].notice}\"\n") }
337
+ return list
338
+ end
339
+
340
+ #===Scene.#listupメソッドの内容をCSVファイルに保存する
341
+ #_csvname_:: 保存するCSVファイルパス
342
+ def Scene.listup2csv(csvfname)
343
+ csvfname += ".csv" if csvfname !~ /\.csv$/
344
+ list = self.listup
345
+ File.open(csvfname, "w"){|f| list.each{|l| f.print l } }
346
+ end
347
+
348
+ end
349
+ end
350
+ end