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.
- data/README +977 -0
- data/Rakefile +7 -0
- data/img/cursor.png +0 -0
- data/img/cursors.png +0 -0
- data/img/dice.png +0 -0
- data/img/wait_cursor.png +0 -0
- data/img/win_base.png +0 -0
- data/img/window.png +0 -0
- data/install_miyako.rb +75 -0
- data/lib/Miyako/API/audio.rb +198 -0
- data/lib/Miyako/API/basic_data.rb +431 -0
- data/lib/Miyako/API/bitmap.rb +35 -0
- data/lib/Miyako/API/choices.rb +308 -0
- data/lib/Miyako/API/collision.rb +444 -0
- data/lib/Miyako/API/diagram.rb +573 -0
- data/lib/Miyako/API/drawing.rb +110 -0
- data/lib/Miyako/API/fixedmap.rb +315 -0
- data/lib/Miyako/API/font.rb +384 -0
- data/lib/Miyako/API/input.rb +440 -0
- data/lib/Miyako/API/layout.rb +451 -0
- data/lib/Miyako/API/map.rb +403 -0
- data/lib/Miyako/API/map_event.rb +198 -0
- data/lib/Miyako/API/modules.rb +109 -0
- data/lib/Miyako/API/movie.rb +151 -0
- data/lib/Miyako/API/parts.rb +154 -0
- data/lib/Miyako/API/plane.rb +131 -0
- data/lib/Miyako/API/screen.rb +257 -0
- data/lib/Miyako/API/shape.rb +362 -0
- data/lib/Miyako/API/sprite.rb +338 -0
- data/lib/Miyako/API/sprite_animation.rb +461 -0
- data/lib/Miyako/API/spriteunit.rb +113 -0
- data/lib/Miyako/API/story.rb +224 -0
- data/lib/Miyako/API/textbox.rb +496 -0
- data/lib/Miyako/API/viewport.rb +435 -0
- data/lib/Miyako/API/yuki.rb +779 -0
- data/lib/Miyako/EXT/miyako_cairo.rb +60 -0
- data/lib/Miyako/EXT/raster_scroll.rb +138 -0
- data/lib/Miyako/EXT/slides.rb +136 -0
- data/lib/Miyako/miyako.rb +172 -0
- data/miyako.png +0 -0
- data/miyako_banner.png +0 -0
- data/miyako_no_katana/extconf.rb +34 -0
- data/miyako_no_katana/miyako_no_katana.c +3301 -0
- data/sample/Animation1/m1ku.rb +89 -0
- data/sample/Animation1/m1ku_arm_0.png +0 -0
- data/sample/Animation1/m1ku_arm_1.png +0 -0
- data/sample/Animation1/m1ku_arm_2.png +0 -0
- data/sample/Animation1/m1ku_arm_3.png +0 -0
- data/sample/Animation1/m1ku_back.jpg +0 -0
- data/sample/Animation1/m1ku_body.png +0 -0
- data/sample/Animation1/m1ku_eye_0.png +0 -0
- data/sample/Animation1/m1ku_eye_1.png +0 -0
- data/sample/Animation1/m1ku_eye_2.png +0 -0
- data/sample/Animation1/m1ku_eye_3.png +0 -0
- data/sample/Animation1/m1ku_hair_front.png +0 -0
- data/sample/Animation1/m1ku_hair_rear.png +0 -0
- data/sample/Animation1/readme.txt +72 -0
- data/sample/Animation2/lex.rb +95 -0
- data/sample/Animation2/lex_back.png +0 -0
- data/sample/Animation2/lex_body.png +0 -0
- data/sample/Animation2/lex_roadroller.png +0 -0
- data/sample/Animation2/lex_wheel_0.png +0 -0
- data/sample/Animation2/lex_wheel_1.png +0 -0
- data/sample/Animation2/lex_wheel_2.png +0 -0
- data/sample/Animation2/readme.txt +72 -0
- data/sample/Animation2/song_title.png +0 -0
- data/sample/Diagram_sample/back.png +0 -0
- data/sample/Diagram_sample/chr01.png +0 -0
- data/sample/Diagram_sample/chr02.png +0 -0
- data/sample/Diagram_sample/cursor.png +0 -0
- data/sample/Diagram_sample/diagram_sample_yuki2.rb +283 -0
- data/sample/Diagram_sample/readme.txt +87 -0
- data/sample/Diagram_sample/wait_cursor.png +0 -0
- data/sample/Room3/blue.rb +250 -0
- data/sample/Room3/ending.rb +175 -0
- data/sample/Room3/green.rb +185 -0
- data/sample/Room3/image/akamatsu.png +0 -0
- data/sample/Room3/image/aoyama.png +0 -0
- data/sample/Room3/image/congra.png +0 -0
- data/sample/Room3/image/congratulation.png +0 -0
- data/sample/Room3/image/congratulation_bg.png +0 -0
- data/sample/Room3/image/cursor.png +0 -0
- data/sample/Room3/image/midori.png +0 -0
- data/sample/Room3/image/mittsu_no_oheya.png +0 -0
- data/sample/Room3/image/mittsu_no_oheya_logo.png +0 -0
- data/sample/Room3/image/room_blue.png +0 -0
- data/sample/Room3/image/room_green.png +0 -0
- data/sample/Room3/image/room_red.png +0 -0
- data/sample/Room3/image/start.png +0 -0
- data/sample/Room3/image/three_doors.png +0 -0
- data/sample/Room3/image/wait_cursor.png +0 -0
- data/sample/Room3/main.rb +102 -0
- data/sample/Room3/main_component.rb +58 -0
- data/sample/Room3/readme.txt +76 -0
- data/sample/Room3/red.rb +200 -0
- data/sample/Room3/room3.rb +26 -0
- data/sample/Room3/title.rb +171 -0
- data/sample/fixed_map_test/cursor.png +0 -0
- data/sample/fixed_map_test/fixed_map_sample.rb +149 -0
- data/sample/fixed_map_test/map.csv +19 -0
- data/sample/fixed_map_test/map_01.png +0 -0
- data/sample/fixed_map_test/map_sample.rb +121 -0
- data/sample/fixed_map_test/mapchip.csv +23 -0
- data/sample/fixed_map_test/monster.png +0 -0
- data/sample/fixed_map_test/readme.txt +72 -0
- data/sample/map_test/chara.rb +50 -0
- data/sample/map_test/chr1.png +0 -0
- data/sample/map_test/cursor.png +0 -0
- data/sample/map_test/main_parts.rb +48 -0
- data/sample/map_test/main_scene.rb +137 -0
- data/sample/map_test/map.png +0 -0
- data/sample/map_test/map2.png +0 -0
- data/sample/map_test/map_layer.csv +127 -0
- data/sample/map_test/map_manager.rb +92 -0
- data/sample/map_test/map_test.rb +23 -0
- data/sample/map_test/mapchip.csv +21 -0
- data/sample/map_test/oasis.rb +65 -0
- data/sample/map_test/readme.txt +87 -0
- data/sample/map_test/route.rb +144 -0
- data/sample/map_test/sea.png +0 -0
- data/sample/map_test/town.rb +68 -0
- data/sample/map_test/wait_cursor.png +0 -0
- data/sample/map_test/window.png +0 -0
- data/win/miyako_no_katana.so +0 -0
- metadata +194 -0
@@ -0,0 +1,315 @@
|
|
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 'csv'
|
24
|
+
require 'forwardable'
|
25
|
+
|
26
|
+
module Miyako
|
27
|
+
#==スクロールしないマップクラス
|
28
|
+
class FixedMap
|
29
|
+
include Layout
|
30
|
+
|
31
|
+
@@idx_ix = [-1, 2, 4]
|
32
|
+
@@idx_iy = [-1, 0, 6]
|
33
|
+
|
34
|
+
attr_reader :name, :map_layers, :pos, :w, :h
|
35
|
+
|
36
|
+
#==あとで書く
|
37
|
+
class FixedMapLayer #:nodoc: all
|
38
|
+
extend Forwardable
|
39
|
+
|
40
|
+
@@use_chip_list = Hash.new(nil)
|
41
|
+
|
42
|
+
attr_accessor :mapchip_units
|
43
|
+
attr_reader :pos
|
44
|
+
|
45
|
+
def round(v, max) #:nodoc:
|
46
|
+
v = max + (v % max) if v < 0
|
47
|
+
v %= max if v >= max
|
48
|
+
return v
|
49
|
+
end
|
50
|
+
|
51
|
+
def reSize #:nodoc:
|
52
|
+
@cw = @real_size.w % @ow == 0 ? @real_size.w / @ow : (@real_size.w + @ow - 1)/ @ow + 1
|
53
|
+
@ch = @real_size.h % @oh == 0 ? @real_size.h / @oh : (@real_size.h + @oh - 1)/ @oh + 1
|
54
|
+
end
|
55
|
+
|
56
|
+
def initialize(mapchip, mapdat, layer_size, pos) #:nodoc:
|
57
|
+
@mapchip = mapchip
|
58
|
+
@pos = pos.dup
|
59
|
+
@size = layer_size.dup
|
60
|
+
@ow = @mapchip.chip_size.w
|
61
|
+
@oh = @mapchip.chip_size.h
|
62
|
+
@real_size = Size.new(@size.w * @ow, @size.h * @oh)
|
63
|
+
@mapdat = mapdat
|
64
|
+
@baseimg = nil
|
65
|
+
@baseimg = @mapchip.chip_image
|
66
|
+
@units = nil
|
67
|
+
@visible = false
|
68
|
+
@divpx = get_div_array(0, @real_size.w, @ow)
|
69
|
+
@divpy = get_div_array(0, @real_size.h, @oh)
|
70
|
+
@modpx = get_mod_array(0, @real_size.w, @ow)
|
71
|
+
@modpy = get_mod_array(0, @real_size.h, @oh)
|
72
|
+
@modpx2 = get_mod_array(0, @size.w * 2 + 1, @size.w)
|
73
|
+
@modpy2 = get_mod_array(0, @size.h * 2 + 1, @size.h)
|
74
|
+
@cdivsx = get_div_array(0, @mapchip.chips, @mapchip.size.w)
|
75
|
+
@cmodsx = get_mod_array(0, @mapchip.chips, @mapchip.size.w)
|
76
|
+
@cdivsy = get_div_array(0, @mapchip.chips, @mapchip.size.h)
|
77
|
+
@cmodsy = get_mod_array(0, @mapchip.chips, @mapchip.size.h)
|
78
|
+
@cdivsx = @cdivsx.map{|v| v * @ow }
|
79
|
+
@cdivsy = @cdivsy.map{|v| v * @oh }
|
80
|
+
@cmodsx = @cmodsx.map{|v| v * @ow }
|
81
|
+
@cmodsy = @cmodsy.map{|v| v * @oh }
|
82
|
+
@mapchip_units = Array.new(@mapchip.chips){|idx|
|
83
|
+
SpriteUnitFactory.create(:bitmap=>@baseimg.bitmap,
|
84
|
+
:ox => (idx % @mapchip.size.w) * @ow, :oy => (idx / @mapchip.size.w) * @oh,
|
85
|
+
:ow => @ow, :oh => @oh)
|
86
|
+
}
|
87
|
+
reSize
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_div_array(s, t, v) #:nodoc:
|
91
|
+
a = Array.new
|
92
|
+
(s..t).each{|i| a.push(i / v)}
|
93
|
+
return a
|
94
|
+
end
|
95
|
+
|
96
|
+
def get_mod_array(s, t, v) #:nodoc:
|
97
|
+
a = Array.new
|
98
|
+
(s..t).each{|i| a.push(i % v)}
|
99
|
+
return a
|
100
|
+
end
|
101
|
+
|
102
|
+
def convert_position(x, y) #:nodoc:
|
103
|
+
return Point.new(@modpx2[round(x, @size.w)],
|
104
|
+
@modpy2[round(y, @size.h)])
|
105
|
+
end
|
106
|
+
|
107
|
+
def get_code(x, y) #:nodoc:
|
108
|
+
pos = convert_position(x, y)
|
109
|
+
return @mapdat[pos.y][pos.x]
|
110
|
+
end
|
111
|
+
|
112
|
+
def dispose #:nodoc:
|
113
|
+
@mapdat = nil
|
114
|
+
@baseimg = nil
|
115
|
+
end
|
116
|
+
|
117
|
+
def_delegators(:@size, :w, :h)
|
118
|
+
end
|
119
|
+
|
120
|
+
#===あとで書く
|
121
|
+
#_mapchip_:: あとで書く
|
122
|
+
#_layer_csv_:: あとで書く
|
123
|
+
#_event_manager_:: MapEventManagerクラスのインスタンス
|
124
|
+
#_pos_:: あとで書く
|
125
|
+
#返却値:: あとで書く
|
126
|
+
def initialize(mapchip, layer_csv, event_manager, pos = Point.new(0, 0))
|
127
|
+
init_layout
|
128
|
+
@em = event_manager.dup
|
129
|
+
@em.set(self)
|
130
|
+
@mapchip = mapchip
|
131
|
+
@pos = Point.new(*(pos.to_a))
|
132
|
+
@coll = Collision.new(Rect.new(0, 0, 0, 0), Point.new(0, 0))
|
133
|
+
layer_data = CSV.readlines(layer_csv)
|
134
|
+
|
135
|
+
raise MiyakoError, "This file is not Miyako Map Layer file! : #{layer_csv}" unless layer_data.shift[0] == "Miyako Maplayer"
|
136
|
+
|
137
|
+
tmp = layer_data.shift # 空行の空読み込み
|
138
|
+
|
139
|
+
layer_size = Size.new(tmp[0].to_i, tmp[1].to_i)
|
140
|
+
@w = layer_size.w * @mapchip.chip_size.w
|
141
|
+
@h = layer_size.h * @mapchip.chip_size.h
|
142
|
+
|
143
|
+
layers = layer_data.shift[0].to_i
|
144
|
+
|
145
|
+
brlist = {}
|
146
|
+
layers.times{|n|
|
147
|
+
name = layer_data.shift[0]
|
148
|
+
if name == "<event>"
|
149
|
+
name = :event
|
150
|
+
else
|
151
|
+
name = /\<(\d+)\>/.match(name).to_a[1].to_i
|
152
|
+
end
|
153
|
+
values = []
|
154
|
+
layer_size.h.times{|y|
|
155
|
+
values << layer_data.shift.map{|m| m.to_i}
|
156
|
+
}
|
157
|
+
brlist[name] = values
|
158
|
+
}
|
159
|
+
|
160
|
+
@map_layers = Array.new
|
161
|
+
@event_layer = nil
|
162
|
+
|
163
|
+
if brlist.has_key?(:event)
|
164
|
+
@event_layer = Array.new
|
165
|
+
brlist[:event].each_with_index{|ly, y|
|
166
|
+
ly.each_with_index{|code, x|
|
167
|
+
next unless @em.include?(code)
|
168
|
+
@event_layer.push(@em.create(code, x * @mapchip.chip_size.w, y * @mapchip.chip_size.h))
|
169
|
+
}
|
170
|
+
}
|
171
|
+
layers -= 1
|
172
|
+
end
|
173
|
+
@map_layers = []
|
174
|
+
layers.times{|i|
|
175
|
+
br = brlist[i].map{|b| b.map{|bb| bb >= @mapchip.chips ? -1 : bb } }
|
176
|
+
@map_layers.push(FixedMapLayer.new(@mapchip, br, layer_size, pos))
|
177
|
+
}
|
178
|
+
set_layout_size(@w, @h)
|
179
|
+
end
|
180
|
+
|
181
|
+
#===マップにイベントを追加する
|
182
|
+
#_code_:: イベント番号(FixedMap.newメソッドで渡したイベント番号に対応)
|
183
|
+
#_x_:: マップ上の位置(x方向)
|
184
|
+
#_y_:: マップ常温位置(y方向)
|
185
|
+
#返却値:: 自分自身を返す
|
186
|
+
def add_event(code, x, y)
|
187
|
+
return self unless @em.include?(code)
|
188
|
+
@event_layer.push(@em.create(code, x, y))
|
189
|
+
return self
|
190
|
+
end
|
191
|
+
|
192
|
+
def update_layout_position #:nodoc:
|
193
|
+
d = Point.new(@layout.pos[0]-@pos.x, @layout.pos[1]-@pos.y)
|
194
|
+
@pos.move_to(*@layout.pos)
|
195
|
+
@map_layers.each{|ml| ml.pos.move_to(*@pos) }
|
196
|
+
end
|
197
|
+
|
198
|
+
def [](idx) #:nodoc:
|
199
|
+
return @map_layers[idx]
|
200
|
+
end
|
201
|
+
|
202
|
+
#===あとで書く
|
203
|
+
#_idx_:: あとで書く
|
204
|
+
#_x_:: あとで書く
|
205
|
+
#_y_:: あとで書く
|
206
|
+
#返却値:: あとで書く
|
207
|
+
def get_code_real(idx, x, y)
|
208
|
+
code = @map_layers[idx].get_code((x-@pos[0]) / @mapchip.chip_size[0], (y-@pos[1]) / @mapchip.chip_size[1])
|
209
|
+
yield code if block_given?
|
210
|
+
return code
|
211
|
+
end
|
212
|
+
|
213
|
+
#===あとで書く
|
214
|
+
#_idx_:: あとで書く
|
215
|
+
#_x_:: あとで書く
|
216
|
+
#_y_:: あとで書く
|
217
|
+
#返却値:: あとで書く
|
218
|
+
def get_code(idx, x, y)
|
219
|
+
code = @map_layers[idx].get_code(x, y)
|
220
|
+
yield code if block_given?
|
221
|
+
return code
|
222
|
+
end
|
223
|
+
|
224
|
+
#===あとで書く
|
225
|
+
#_idx_:: あとで書く
|
226
|
+
#_code_:: あとで書く
|
227
|
+
#_base_:: あとで書く
|
228
|
+
#返却値:: あとで書く
|
229
|
+
def set_mapchip_base(idx, code, base)
|
230
|
+
@map_layers[idx].mapchip_units[code] = base
|
231
|
+
return self
|
232
|
+
end
|
233
|
+
|
234
|
+
#===あとで書く
|
235
|
+
#_type_:: あとで書く
|
236
|
+
#_rect_:: あとで書く
|
237
|
+
#_collision_:: あとで書く
|
238
|
+
#返却値:: あとで書く
|
239
|
+
def get_amount_by_rect(type, rect, collision)
|
240
|
+
mma = MapMoveAmount.new([], collision.direction.dup)
|
241
|
+
return mma if(mma.amount[0] == 0 && mma.amount[1] == 0)
|
242
|
+
dx, dy = collision.direction[0]*collision.amount[0], collision.direction[1]*collision.amount[1]
|
243
|
+
x, y = rect[0]-@pos[0], rect[1]-@pos[1]
|
244
|
+
collision.pos = Point.new(x, y)
|
245
|
+
px1, px2 = (x+dx) / @mapchip.chip_size[0], (x+rect[2]-1+dx) / @mapchip.chip_size[0]
|
246
|
+
py1, py2 = (y+dy) / @mapchip.chip_size[1], (y+rect[3]-1+dy) / @mapchip.chip_size[1]
|
247
|
+
(py1..py2).each{|py|
|
248
|
+
rpy = py * @mapchip.chip_size[1]
|
249
|
+
(px1..px2).each{|px|
|
250
|
+
rpx = px * @mapchip.chip_size[0]
|
251
|
+
@map_layers.each_with_index{|ml, idx|
|
252
|
+
code = ml.get_code(px, py)
|
253
|
+
next if code == -1 # not use chip
|
254
|
+
@coll = @mapchip.collision_table[type][code].dup
|
255
|
+
@coll.pos = Point.new(rpx, rpy)
|
256
|
+
atable = @mapchip.access_table[type][code]
|
257
|
+
if @coll.into?(collision)
|
258
|
+
mma.amount[0] = mma.amount[0] & atable[@@idx_ix[collision.direction[0]]]
|
259
|
+
mma.amount[1] = mma.amount[1] & atable[@@idx_iy[collision.direction[1]]]
|
260
|
+
mma.collisions << [idx, code, :into]
|
261
|
+
end
|
262
|
+
}
|
263
|
+
}
|
264
|
+
}
|
265
|
+
mma.amount[0] *= collision.amount[0]
|
266
|
+
mma.amount[1] *= collision.amount[1]
|
267
|
+
yield mma if block_given?
|
268
|
+
return mma
|
269
|
+
end
|
270
|
+
|
271
|
+
#===現在の画面の最大の大きさを矩形で取得する
|
272
|
+
#但し、FixedMapの場合は最大の大きさ=画面の大きさなので、rectと同じ値が得られる
|
273
|
+
#返却値:: 画像の大きさ(Rect構造体のインスタンス)
|
274
|
+
def broad_rect
|
275
|
+
return self.rect
|
276
|
+
end
|
277
|
+
|
278
|
+
#===あとで書く
|
279
|
+
#返却値:: あとで書く
|
280
|
+
def chipSize
|
281
|
+
return @mapchip.chip_size
|
282
|
+
end
|
283
|
+
|
284
|
+
#===あとで書く
|
285
|
+
#返却値:: あとで書く
|
286
|
+
def final
|
287
|
+
@event_layer.each{|e| e.final } if @event_layer
|
288
|
+
end
|
289
|
+
|
290
|
+
#===あとで書く
|
291
|
+
#返却値:: あとで書く
|
292
|
+
def dispose
|
293
|
+
@map_layers.each{|l|
|
294
|
+
l.dispose
|
295
|
+
l = nil
|
296
|
+
}
|
297
|
+
@map_layers = Array.new
|
298
|
+
if @event_layer
|
299
|
+
@event_layer.each{|e| e.dispose }
|
300
|
+
@event_layer = nil
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
def re_size #:nodoc:
|
305
|
+
@map_layers.each{|l| l.reSize }
|
306
|
+
return self
|
307
|
+
end
|
308
|
+
|
309
|
+
#===マップに登録しているイベントインスタンス(マップイベント)を取得する
|
310
|
+
#返却値:: マップイベントの配列
|
311
|
+
def events
|
312
|
+
return @event_layer || []
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
@@ -0,0 +1,384 @@
|
|
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
|
+
# フォント関連クラス(群)
|
24
|
+
module Miyako
|
25
|
+
|
26
|
+
=begin rdoc
|
27
|
+
==フォント管理クラス
|
28
|
+
=end
|
29
|
+
class Font
|
30
|
+
extend Forwardable
|
31
|
+
|
32
|
+
attr_reader :size, :line_skip, :height, :ascent, :descent
|
33
|
+
attr_accessor :color, :use_shadow, :shadow_color, :shadow_margin, :vspace, :draw_type
|
34
|
+
|
35
|
+
@@font_cache = {}
|
36
|
+
|
37
|
+
@@name_2_font_path = Hash.new
|
38
|
+
|
39
|
+
@@font_base_path = Hash.new
|
40
|
+
@@font_base_path["win"] = ENV['SystemRoot'] ? ["./", ENV['SystemRoot'].tr("\\", "/") + "/fonts/"] : ["./"]
|
41
|
+
@@font_base_path["linux"] = ["./", "/usr/share/fonts/", "/usr/X11R6/lib/X11/fonts/"]
|
42
|
+
@@font_base_path["mac_osx"] = ["./", "~/Library/Fonts/", "/Library/Fonts/", "/System/Library/Fonts/",
|
43
|
+
"/ライブラリ/Fonts/", "/システム/ライブラリ/Fonts/"]
|
44
|
+
|
45
|
+
@@font_base_name = Hash.new
|
46
|
+
@@font_base_name["win"] = [{:serif=>"msmincho.ttc", :sans_serif=>"meiryo.ttc"},
|
47
|
+
{:serif=>"msmincho.ttc", :sans_serif=>"msgothic.ttc"},
|
48
|
+
{:serif=>"VL-Gothic-Regular.ttf", :sans_serif=>"VL-Gothic-Regular.ttf"},
|
49
|
+
{:serif=>"umeplus-gothic.ttf", :sans_serif=>"umeplus-gothic.ttf"}]
|
50
|
+
@@font_base_name["linux"] = [{:serif=>"sazanami-mincho.ttf", :sans_serif=>"sazanami-gothic.ttf"},
|
51
|
+
{:serif=>"VL-Gothic-Regular.ttf", :sans_serif=>"VL-Gothic-Regular.ttf"},
|
52
|
+
{:serif=>"umeplus-gothic.ttf", :sans_serif=>"umeplus-gothic.ttf"}]
|
53
|
+
@@font_base_name["mac_osx"] = [{:serif=>"Hiragino Mincho Pro W3.otf", :sans_serif=>"Hiragino Kaku Gothic Pro W3.otf"},
|
54
|
+
{:serif=>"Hiragino Mincho Pro W6.otf", :sans_serif=>"Hiragino Kaku Gothic Pro W6.otf"},
|
55
|
+
{:serif=>"ヒラギノ明朝 Pro W3.otf", :sans_serif=>"ヒラギノ角ゴ Pro W3.otf"},
|
56
|
+
{:serif=>"ヒラキ゛ノ明朝 Pro W3.otf", :sans_serif=>"ヒラキ゛ノ角コ゛ Pro W3.otf"},
|
57
|
+
{:serif=>"ヒラギノ明朝 Pro W6.otf", :sans_serif=>"ヒラギノ角ゴ Pro W6.otf"},
|
58
|
+
{:serif=>"ヒラキ゛ノ明朝 Pro W6.otf", :sans_serif=>"ヒラキ゛ノ角コ゛ Pro W6.otf"},
|
59
|
+
{:serif=>"VL-Gothic-Regular.ttf", :sans_serif=>"VL-Gothic-Regular.ttf"},
|
60
|
+
{:serif=>"umeplus-gothic.ttf", :sans_serif=>"umeplus-gothic.ttf"}]
|
61
|
+
|
62
|
+
def Font.search_font_path_file(hash, path) #:nodoc:
|
63
|
+
Dir.glob(path+"*"){|d|
|
64
|
+
hash = Font.search_font_path_file(hash, d+"/") if test(?d, d)
|
65
|
+
d = Iconv.conv("UTF-8-MAC", "UTF-8", d.toutf8) if Miyako.getOSName == "mac_osx" # MacOSXはパス名がUTF-8固定のため
|
66
|
+
d = d.tr("\\", "\/")
|
67
|
+
hash[$1] = d if (d =~ /\/([^\/\.]+\.tt[fc])\z/ || d =~ /\/([^\/\.]+\.otf)\z/) # MacOSX対応
|
68
|
+
}
|
69
|
+
return hash
|
70
|
+
end
|
71
|
+
|
72
|
+
def Font.create_font_path #:nodoc:
|
73
|
+
osn = Miyako::getOSName
|
74
|
+
@@font_base_path[osn].each{|path|
|
75
|
+
path = Iconv.conv("UTF-8-MAC", "UTF-8", path.toutf8) if Miyako.getOSName == "mac_osx" # MacOSXはパス名がUTF-8固定のため
|
76
|
+
path = path.tr("\\", "\/")
|
77
|
+
@@name_2_font_path = Font.search_font_path_file(@@name_2_font_path, path)
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
def Font.findFontPath(fname) #:nodoc:
|
82
|
+
fname = Iconv.conv("UTF-8-MAC", "UTF-8", fname.toutf8) if Miyako.getOSName == "mac_osx" # MacOSXはパス名がUTF-8固定のため
|
83
|
+
return @@name_2_font_path.fetch(fname, nil)
|
84
|
+
end
|
85
|
+
|
86
|
+
def Font.get_font_inner(fname, fpath, size=16) #:nodoc:
|
87
|
+
if Miyako.getOSName == "mac_osx" # MacOSXはパス名がUTF-8固定のため
|
88
|
+
fname = Iconv.conv("UTF-8-MAC", "UTF-8", fname.toutf8)
|
89
|
+
fpath = Iconv.conv("UTF-8-MAC", "UTF-8", fpath.toutf8)
|
90
|
+
end
|
91
|
+
@@font_cache[fname] ||= {}
|
92
|
+
@@font_cache[fname][size] ||= SDL::TTF.open(fpath, size)
|
93
|
+
return @@font_cache[fname][size]
|
94
|
+
end
|
95
|
+
|
96
|
+
def init_height #:nodoc:
|
97
|
+
@line_skip = @font.line_skip
|
98
|
+
@height = @font.height
|
99
|
+
@ascent = @font.ascent
|
100
|
+
@descent = @font.descent
|
101
|
+
end
|
102
|
+
|
103
|
+
private :init_height
|
104
|
+
|
105
|
+
#===インスタンス生成
|
106
|
+
#_fname_:: フォントファイル名(フォントファミリー名不可)。システムフォントのときはディレクトリ指定不要
|
107
|
+
#_size_:: フォントの大きさ。単位はピクセル。デフォルトは 16
|
108
|
+
#返却値:: 生成されたインスタンスを返す
|
109
|
+
def initialize(fname, size=16)
|
110
|
+
@size = size
|
111
|
+
@color = [255, 255, 255]
|
112
|
+
@fname = fname
|
113
|
+
@vspace = 0
|
114
|
+
@bold = false
|
115
|
+
@italic = false
|
116
|
+
@under_line = false
|
117
|
+
@draw_type = :mild
|
118
|
+
@fpath = Font.findFontPath(@fname) or raise MiyakoError, "Cannot Find Font! : #{@fname}"
|
119
|
+
@font = Font.get_font_inner(@fname, @fpath, @size)
|
120
|
+
@font.style = SDL::TTF::STYLE_NORMAL
|
121
|
+
init_height
|
122
|
+
@draw_text = {:solid => self.method(:_draw_text), :mild => self.method(:_draw_text_mild)}
|
123
|
+
@use_shadow = false
|
124
|
+
@shadow_color = [128, 128, 128]
|
125
|
+
@shadow_margin = [2, 2]
|
126
|
+
@unit = SpriteUnitFactory.create
|
127
|
+
end
|
128
|
+
|
129
|
+
#===フォントの大きさを変更する
|
130
|
+
#_sz_:: 変更するフォントの大きさ(単位:ピクセル)
|
131
|
+
#返却値:: 変更されたフォントのインスタンス
|
132
|
+
def size=(sz)
|
133
|
+
@size = sz
|
134
|
+
@font = Font.get_font_inner(@fname, @fpath, @size)
|
135
|
+
@font.style = (@bold ? SDL::TTF::STYLE_BOLD : 0) | (@italic ? SDL::TTF::STYLE_ITALIC : 0) | (@under_line ? SDL::TTF::STYLE_UNDERLINE : 0)
|
136
|
+
init_height
|
137
|
+
return self
|
138
|
+
end
|
139
|
+
|
140
|
+
#===ブロック評価中のみ、フォントの大きさを変更する
|
141
|
+
#_sz_:: 変更するフォントの大きさ(単位:ピクセル)
|
142
|
+
#返却値:: 自分自身を返す
|
143
|
+
def size_during(sz)
|
144
|
+
raise MiyakoError, "not given block!" unless block_given?
|
145
|
+
tsize = @size
|
146
|
+
self.size = sz
|
147
|
+
yield
|
148
|
+
self.size = tsize
|
149
|
+
return self
|
150
|
+
end
|
151
|
+
|
152
|
+
#===ブロック評価中のみ、フォントの文字の色を変更する
|
153
|
+
#_color_:: 変更する色([r,g,b]の3要素の配列(値:0~255))
|
154
|
+
#返却値:: 自分自身を返す
|
155
|
+
def color_during(color)
|
156
|
+
raise MiyakoError, "not given block!" unless block_given?
|
157
|
+
tcolor, self.color = @color, color
|
158
|
+
yield
|
159
|
+
self.color = tcolor
|
160
|
+
return self
|
161
|
+
end
|
162
|
+
|
163
|
+
#===ブロック評価中のみ、影文字文字の色・マージンを変更する
|
164
|
+
#また、ブロック評価中は影文字が強制的に有効になる
|
165
|
+
#_color_:: 変更する色([r,g,b]の3要素の配列(値:0~255))、デフォルトはFont#shadow_colorメソッドの値([128,128,128])
|
166
|
+
#_margin_:: 変更する色(2要素の整数の配列、デフォルトはFont#shadow_marginメソッドの値([2,2])
|
167
|
+
#返却値:: 自分自身を返す
|
168
|
+
def shadow_during(color = @shadow_color, margin = @shadow_margin)
|
169
|
+
raise MiyakoError, "not given block!" unless block_given?
|
170
|
+
tflag, @use_shadow = @use_shadow, true
|
171
|
+
tcolor, @shadow_color = @shadow_color, color
|
172
|
+
tmargin, @shadow_margin = @shadow_margin, margin
|
173
|
+
yield
|
174
|
+
@use_shadow = tflag
|
175
|
+
@shadow_color = tcolor
|
176
|
+
@shadow_margin = tmargin
|
177
|
+
return self
|
178
|
+
end
|
179
|
+
|
180
|
+
#===指定したピクセル数のフォントが十分(欠けることなく)収まるピクセル数を取得する
|
181
|
+
#_size_:: フォントの大きさ(単位:ピクセル)
|
182
|
+
#返却値:: 算出されたピクセル数
|
183
|
+
def get_fit_size(size)
|
184
|
+
path = Font.findFontPath(@fname)
|
185
|
+
font = SDL::TTF.open(path, size)
|
186
|
+
return (size.to_f * (size.to_f / font.line_skip.to_f)).to_i
|
187
|
+
end
|
188
|
+
|
189
|
+
#===フォントサイズ(yやjなどの下にはみ出る箇所も算出)を取得する
|
190
|
+
#返却値:: 算出されたフォントサイズ
|
191
|
+
def line_height
|
192
|
+
return @line_skip + @vspace + (@use_shadow ? @shadow_margin[1] : 0)
|
193
|
+
end
|
194
|
+
|
195
|
+
#===フォントインスタンスを解放する
|
196
|
+
def dispose
|
197
|
+
@font = nil
|
198
|
+
end
|
199
|
+
|
200
|
+
#===フォントの属性をbold(太文字)に設定する
|
201
|
+
#ブロックを渡したときは、ブロック評価中のみ太字になる
|
202
|
+
#文字が領域外にはみ出る場合があるので注意!
|
203
|
+
#返却値:: 自分自身
|
204
|
+
def bold
|
205
|
+
if block_given?
|
206
|
+
tbold, self.bold = self.bold?, true
|
207
|
+
yield
|
208
|
+
self.bold = tbold
|
209
|
+
else
|
210
|
+
self.bold = true
|
211
|
+
end
|
212
|
+
return self
|
213
|
+
end
|
214
|
+
|
215
|
+
#===フォントのbold属性の有無を返す
|
216
|
+
#返却値:: bold属性かどうか(true/false)
|
217
|
+
def bold?
|
218
|
+
return @bold
|
219
|
+
end
|
220
|
+
|
221
|
+
#===フォントのbold属性を設定する
|
222
|
+
#_f_:: bold属性かどうか(true/false)
|
223
|
+
def bold=(f)
|
224
|
+
@bold = f
|
225
|
+
@font.style |= SDL::TTF::STYLE_BOLD
|
226
|
+
@font.style -= SDL::TTF::STYLE_BOLD unless @bold
|
227
|
+
return self
|
228
|
+
end
|
229
|
+
|
230
|
+
#===フォントの属性をitalic(斜め)に設定する
|
231
|
+
#ブロックを渡したときは、ブロック評価中のみ斜体文字になる
|
232
|
+
#文字が領域外にはみ出る場合があるので注意!
|
233
|
+
#返却値:: 自分自身
|
234
|
+
def italic
|
235
|
+
if block_given?
|
236
|
+
titalic, self.italic = self.italic?, true
|
237
|
+
yield
|
238
|
+
self.italic = titalic
|
239
|
+
else
|
240
|
+
self.italic = true
|
241
|
+
end
|
242
|
+
return self
|
243
|
+
end
|
244
|
+
|
245
|
+
#===フォントのitalic属性の有無を返す
|
246
|
+
#返却値:: italic属性かどうか(true/false)
|
247
|
+
def italic?
|
248
|
+
return @italic
|
249
|
+
end
|
250
|
+
|
251
|
+
#===フォントのitalic属性を設定する
|
252
|
+
#_f_:: italic属性かどうか(true/false)
|
253
|
+
def italic=(f)
|
254
|
+
@italic = f
|
255
|
+
@font.style |= SDL::TTF::STYLE_ITALIC
|
256
|
+
@font.style -= SDL::TTF::STYLE_ITALIC unless @italic
|
257
|
+
return self
|
258
|
+
end
|
259
|
+
|
260
|
+
#===フォントの属性をunder_line(下線)に設定する
|
261
|
+
#ブロックを渡したときは、ブロック評価中のみ下線付き文字になる
|
262
|
+
#返却値:: 自分自身
|
263
|
+
def under_line
|
264
|
+
if block_given?
|
265
|
+
tunder_line, self.under_line = self.under_line?, true
|
266
|
+
yield
|
267
|
+
self.under_line = tunder_line
|
268
|
+
else
|
269
|
+
self.under_line = true
|
270
|
+
end
|
271
|
+
return self
|
272
|
+
end
|
273
|
+
|
274
|
+
#===フォントのunder_line属性の有無を返す
|
275
|
+
#返却値:: under_line属性かどうか(true/false)
|
276
|
+
def under_line?
|
277
|
+
return @under_line
|
278
|
+
end
|
279
|
+
|
280
|
+
#===フォントのunder_line属性を設定する
|
281
|
+
#_f_:: under_line属性かどうか(true/false)
|
282
|
+
def under_line=(f)
|
283
|
+
@under_line = f
|
284
|
+
@font.style |= SDL::TTF::STYLE_UNDERLINE
|
285
|
+
@font.style -= SDL::TTF::STYLE_UNDERLINE unless @under_line
|
286
|
+
return self
|
287
|
+
end
|
288
|
+
|
289
|
+
#===フォントの属性をすべてクリアする
|
290
|
+
#_f_:: 自分自身
|
291
|
+
def normal
|
292
|
+
@font.style = 0
|
293
|
+
return self
|
294
|
+
end
|
295
|
+
|
296
|
+
#===文字列を描画する
|
297
|
+
#対象のスプライトに文字列を描画する
|
298
|
+
#_dst_:: 描画先スプライト
|
299
|
+
#_str_:: 描画する文字列
|
300
|
+
#_x_:: 描画位置x軸
|
301
|
+
#_y_:: 描画位置Y軸
|
302
|
+
def draw_text(dst, str, x, y)
|
303
|
+
str = str.toutf8
|
304
|
+
str = Iconv.conv("UTF-8-MAC", "UTF-8", str) if Miyako.getOSName == "mac_osx"
|
305
|
+
return @draw_text[@draw_type][dst, str, x, y]
|
306
|
+
end
|
307
|
+
|
308
|
+
def _draw_text(dst, str, x, y) #:nodoc:
|
309
|
+
@font.drawSolidUTF8(dst.bitmap, str, x + @shadow_margin[0], y + @shadow_margin[1], @shadow_color[0], @shadow_color[1], @shadow_color[2]) if @use_shadow
|
310
|
+
@font.drawSolidUTF8(dst.bitmap, str, x, y, @color[0], @color[1], @color[2])
|
311
|
+
return x + @font.textSize(str)[0]
|
312
|
+
end
|
313
|
+
|
314
|
+
def _draw_text_mild(dst, str, x, y) #:nodoc:
|
315
|
+
src = @font.renderBlendedUTF8(str, @color[0], @color[1], @color[2])
|
316
|
+
if src
|
317
|
+
if @use_shadow
|
318
|
+
src2 = @font.renderBlendedUTF8(str, @shadow_color[0], @shadow_color[1], @shadow_color[2])
|
319
|
+
SpriteUnitFactory.apply(@unit, {:bitmap=>src2, :ow=>src2.w, :oh=>src2.h})
|
320
|
+
Miyako::Bitmap.blit_aa!(@unit, dst.to_unit, x+@shadow_margin[0], y+@shadow_margin[1])
|
321
|
+
end
|
322
|
+
SpriteUnitFactory.apply(@unit, {:bitmap=>src, :ow=>src.w, :oh=>src.h})
|
323
|
+
Miyako::Bitmap.blit_aa!(@unit, dst.to_unit, x, y)
|
324
|
+
else
|
325
|
+
return x
|
326
|
+
end
|
327
|
+
return x + @font.textSize(str)[0]
|
328
|
+
end
|
329
|
+
|
330
|
+
#===文字列描画したときの大きさを取得する
|
331
|
+
#現在のフォントの設定で指定の文字列を描画したとき、予想される描画サイズを返す。実際に描画は行われない。
|
332
|
+
#_txt_:: 算出したい文字列
|
333
|
+
#返却値:: 文字列を描画したときの大きさ([w,h]の配列)
|
334
|
+
def text_size(txt)
|
335
|
+
return [txt.chars.inject(0){|r, c| r += (c.length == 1 ? @size >> 1 : @size) } + (@use_shadow ? @shadow_margin[0] : 0),
|
336
|
+
self.line_height]
|
337
|
+
end
|
338
|
+
|
339
|
+
#===指定した高さで描画する際のマージンを求める
|
340
|
+
#現在のフォントの設定で指定の文字列を描画したとき、予想される描画サイズを返す。実際に描画は行われない。
|
341
|
+
#第1引数に渡す"align"は、以下の3種類のシンボルのどれかを渡す
|
342
|
+
#:top:: 上側に描画(マージンはゼロ)
|
343
|
+
#:middle:: 中間に描画
|
344
|
+
#:bottom:: 下部に描画
|
345
|
+
#
|
346
|
+
#_align_:: 描画位置
|
347
|
+
#_height_:: 描画する高さ
|
348
|
+
#返却値:: マージンの値
|
349
|
+
def margin_height(align, height)
|
350
|
+
case align
|
351
|
+
when :top
|
352
|
+
return 0
|
353
|
+
when :middle
|
354
|
+
return (height - self.line_height) >> 1
|
355
|
+
when :bottom
|
356
|
+
return height - self.line_height
|
357
|
+
end
|
358
|
+
#else
|
359
|
+
raise MiyakoError, "Illegal margin_height align! : #{align}"
|
360
|
+
end
|
361
|
+
|
362
|
+
Font.create_font_path
|
363
|
+
|
364
|
+
#===Serifフォント(明朝フォント)を取得する
|
365
|
+
#マルチプラットフォームのソフトを作る際、OS間の差異を吸収するため、共通の名称でフォントインスタンスを取得するときに使う(主に明朝フォント)
|
366
|
+
#返却値:: OSごとに設定されたフォントイン寸タンス(フォントサイズは16)
|
367
|
+
def Font::serif
|
368
|
+
filename = @@font_base_name[Miyako::getOSName].detect{|base| Font.findFontPath(base[:serif]) }[:serif]
|
369
|
+
return Font.new(filename)
|
370
|
+
end
|
371
|
+
|
372
|
+
#===Sans Serifフォント(ゴシックフォント)を取得する
|
373
|
+
#マルチプラットフォームのソフトを作る際、OS間の差異を吸収するため、共通の名称でフォントインスタンスを取得するときに使う(主にゴシックフォント)
|
374
|
+
#返却値:: OSごとに設定されたフォントイン寸タンス(フォントサイズは16)
|
375
|
+
def Font::sans_serif
|
376
|
+
filename = @@font_base_name[Miyako::getOSName].detect{|base| Font.findFontPath(base[:sans_serif]) }[:sans_serif]
|
377
|
+
return Font.new(filename)
|
378
|
+
end
|
379
|
+
|
380
|
+
def Font::system_font #:nodoc:
|
381
|
+
return Font.serif
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|