2014/06/02(月) [n年前の日記]
#1 [dxruby][ruby][cg_tools] DXRubyとcairoでswfのシェイプを描画してみる実験
_2014/05/29
に、DXRubyでswfのシェイプを描画する実験をしたのだけど。あまりにも処理が遅い上に、描画も汚くてしょんぼりだったわけですが。
_cairo
と組み合わせて使えば、もっと速く、もっと綺麗にできるんじゃないかと思えたので試してみたり。
こんな感じになりました。右側が、cairoを使って描画した結果。 さすがに美しい…。cairo、凄いなあ。
ソースは以下。
_shapeparse_with_cairo.rb
データ一式も置いときます。
_swf_shape_parse_20140602.zip (434KB)
アンチエイリアスをかけながら描画してくれるライブラリなだけあって、さすがに綺麗。しかも、CPU負荷率を見る限りでは、自前で線描画や多角形塗りをするよりも、40倍ぐらい速くなりました。
それでもやっぱり、リアルタイムに描画するのは速度的に無理なので、実用にはならないのですけど。どう考えても、最初からレンダリング済みのビットマップ画像を用意しておくべきだなと。
更に、このやり方、現状ではかなりトホホな点があって。cairo で描画した後、結果を一旦 pngファイルでHDDに保存して、それを DXRuby の Image にロードし直していたりするわけで。
これがもし、cairo の Surface から、pngファイルとして書き出すべきバイナリデータを直接取得できれば…。あるいは、Surface内容をRGBAの配列で取得できれば、わざわざクソ遅いHDDにアクセスしなくても済むのですけど。残念ながら、そのようなメソッドは見つからなくて。
それにしても、swfのシェイプをこうして描画できるということは、svgも描画できたりするのかしら。たしか、svg を解析・描画する Rubyライブラリも存在していたはずなので、ちと試してみたいところ。
こんな感じになりました。右側が、cairoを使って描画した結果。 さすがに美しい…。cairo、凄いなあ。
ソースは以下。
_shapeparse_with_cairo.rb
require 'nokogiri' require 'dxruby' require 'cairo' require 'tempfile' require_relative 'bezierdraw' # swfのシェイプを解析してImageに描画するクラス(cairo使用版) # class ShapeParse DBG = false DBG2 = true TWIP = 20.0 attr_accessor :id attr_accessor :width attr_accessor :left attr_accessor :top attr_accessor :height attr_accessor :image attr_accessor :draw_data attr_accessor :clip_enable attr_accessor :surface attr_accessor :context def initialize(node, clip_enable = true) self.clip_enable = clip_enable self.id = node["objectID"].to_i puts "id[#{self.id}] #{node.name}" if DBG n = node.at(".//bounds/Rectangle") self.left = (n["left"].to_f / ShapeParse::TWIP).to_i self.top = (n["top"].to_f / ShapeParse::TWIP).to_i self.width = (n["right"].to_f / ShapeParse::TWIP).to_i self.height = (n["bottom"].to_f / ShapeParse::TWIP).to_i puts "size : (x,y)=#{self.left},#{self.top} (w,h)=#{self.width},#{self.height}" if DBG self.width = Window.width if self.width < Window.width self.height = Window.height if self.height < Window.height x0, y0 = 0, 0 x1, y1 = 0, 0 x2, y2 = 0, 0 f0_enable = true f1_enable = true l_enable = true fc = [[0, 0, 0, 0], [0, 0, 0, 0]] lc = [0, 0, 0, 0] lwidth = ShapeParse::TWIP lines = [] self.draw_data = [] n = node.at(".//shapes/Shape/edges").child while n != nil case n.name when "ShapeSetup" unless lines.empty? save_draw_data(lines, f0_enable, f1_enable, l_enable, lwidth, fc[0], fc[1], lc) lines = [] end s = "#{n.name} " x0 = n["x"].to_f if n.key?("x") y0 = n["y"].to_f if n.key?("y") f0_enable = (n["fillStyle0"] == "1")? true : false f1_enable = (n["fillStyle1"] == "1")? true : false l_enable = (n["lineStyle"] == "1")? true : false if false s += "(x,y)=#{x0/TWIP}, #{y0/TWIP} (" s += (f0_enable)? "f0 " : " " s += (f1_enable)? "f1 " : " " s += (l_enable)? "l" : " " s += ")" puts s end n.xpath(".//fillStyles").each do |nn| nn.xpath(".//Solid/color/Color").each_with_index do |m, i| fc[i] = get_color(m) end end n.xpath(".//lineStyles").each do |nn| nn.xpath(".//LineStyle").each do |m| lwidth = m["width"].to_i if m.key?("width") m.xpath(".//color//Color").each do |c| lc = get_color(c) end end end if n.key?("x") and n.key?("y") lines.push([x0, y0]) end when "CurveTo" # 二次ベジェ曲線 x1 = x0 + n["x1"].to_f y1 = y0 + n["y1"].to_f x2 = x1 + n["x2"].to_f y2 = y1 + n["y2"].to_f lst = BezierDraw.calc(x0, y0, x1, y1, x2, y2) lines.concat(lst.slice(1..-1)) x0 = x2 y0 = y2 when "LineTo" # 直線 x1 = x0 + n["x"].to_f y1 = y0 + n["y"].to_f lines.push([x1, y1]) x0 = x1 y0 = y1 else puts "!! Unknown Tag : #{n.name}" end n = n.next end draw(false) end # 色配列を取得 # # @param [Object] node 「Color」ノード # @return [Array] A,R,G,Bが入った配列 # def get_color(node) col = [255, 0, 0, 0] # ARGB ["alpha", "red", "green", "blue"].each_with_index do |s,i| col[i] = node[s].to_f if node.key?(s) end return col end # 描画用の直線データを記録 # # @param [Array] lines 直線データ配列 # @param [Boolean] fe0 塗り潰し0をするか否か # @param [Boolean] fe1 塗り潰し1をするか否か # @param [Boolean] le 線を描くか否か # @param [Number] lw 線幅 # @param [Array] fc0 塗り潰し0の色配列 # @param [Array] fc1 塗り潰し1の色配列 # @param [Array] lc1 線描画の色配列 # def save_draw_data(lines, fe0, fe1, le, lw, fc0, fc1, lc) np = [] ox, oy = nil, nil lines.each do |p| x, y = p x /= TWIP y /= TWIP np.push([x, y]) if x != ox or y != oy ox, oy = x, y end # 記録 self.draw_data.push([np, fe0, fe1, le, lw, fc0.dup, fc1.dup, lc.dup]) end # Imageオブジェクトに描画 # # @param [Boolean] clear_enable trueならImageをクリアしてから描画 # def draw(clear_enable = true, scale_x = 1.0, scale_y = 1.0) # self.image.clear if clear_enable # cairoのサーフェスを確保 self.surface = Cairo::ImageSurface.new(Cairo::FORMAT_ARGB32, self.width, self.height) self.context = Cairo::Context.new(surface) self.draw_data.each do |d| p, fe0, fe1, le, lw, fc0, fc1, lc = d np = [] p.each { |q| np.push([q[0] * scale_x, q[1] * scale_y]) } draw_line(self.context, np, fe0, fe1, le, lw, fc0, fc1, lc) end # 一時ファイル作成 temp = Tempfile.new(['shapeparse', '.png']) temp.binmode temp.close # pngファイルに出力 self.surface.write_to_png(temp.path) # DXRubyで読み込み self.image = Image.load(temp.path) temp.close(true) end # 色配列の数値を変換して返す # # @note 255までの値を持っていた色配列を、1.0までの値に変換する # # @param [Array] c 色配列ARGB # @return [Array] 色配列RGBA # def get_rgba(c) r = [] c.each do |n| m = n / 255.0 m = 0.0 if m < 0.0 m = 1.0 if m > 1.0 r.push(m) end return r[1], r[2], r[3], r[0] end # 多角形を描画 # # @param [Object] ct cairoのcontext # @param [Array] p 頂点座標が入った配列。 # @param [Boolean] f0_enable trueなら塗り潰し有、falseなら塗り潰し無 # @param [Boolean] f1_enable trueなら塗り潰し有、falseなら塗り潰し無 # @param [Boolean] l_enable trueなら線を描く、falseなら線を描かない # @param [Number] lwidth 線幅 # @param [Array] fc0 色配列。A,R,G,B # @param [Array] fc1 色配列。A,R,G,B # @param [Array] lc 色配列。A,R,G,B # def draw_line(ct, p, f0_enable, f1_enable, l_enable, lwidth, fc0, fc1, lc) return if (!f0_enable and !l_enable) ct.set_line_join(Cairo::LineJoin::ROUND) # 結合点の種類を指定 ct.set_line_cap(Cairo::LineCap::ROUND) # 線の終点の種類を指定 lw = lwidth / TWIP lw = 1.0 if lw < 1.0 # swfは1.0より細い線幅も1.0の線幅で描画するらしい ct.set_line_width(lw) # 線幅を指定 # 塗る色を指定 if f0_enable ct.set_source_rgba(get_rgba(fc0)) else ct.set_source_rgba(get_rgba(lc)) end x0 , y0 = p[0] ct.move_to(x0, y0) 1.step(p.size - 1, 1) do |i| ct.line_to(p[i][0], p[i][1]) end if f0_enable # 塗り潰し ct.fill_preserve end # 線を描画 ct.set_source_rgba(get_rgba(lc)) if l_enable ct.stroke end end if $0 == __FILE__ # ---------------------------------------- # 動作テスト font = Font.new(14) # swfmillで swf → xml変換したxmlを解析 # infile = "swfdata/test_pdr1.xml" infile = "swfdata/test_pdr2.xml" doc = Nokogiri::XML(File.open(infile)) {|cfg| cfg.noblanks} objs = Hash.new doc.xpath("//DefineShape3").each do |node| pdr = ShapeParse.new(node, false) # ベクターデータを解析して画像化 objs[pdr.id] = pdr end redraw_fg = false ang = 0 scale = 1.0 Window.bgcolor = [0, 190, 118] Window.fps = 60 # メインループ Window.loop do break if Input.keyPush?(K_ESCAPE) # Rキー押しでスケールを変えて再描画 redraw_fg = (Input.keyDown?(K_R))? true : false objs.each_value do |o| # ベクターデータを再描画できなくもないが、遅くて実用にならない o.draw(true, scale, scale) if redraw_fg Window.draw(0, 0, o.image) end s = "#{Window.real_fps} FPS / CPU: #{Window.getLoad.to_i}%" Window.drawFont(4, 4, s, font) ang += 10 scale = Math.cos(ang * Math::PI / 180.0) + 1.5 end end
データ一式も置いときます。
_swf_shape_parse_20140602.zip (434KB)
アンチエイリアスをかけながら描画してくれるライブラリなだけあって、さすがに綺麗。しかも、CPU負荷率を見る限りでは、自前で線描画や多角形塗りをするよりも、40倍ぐらい速くなりました。
それでもやっぱり、リアルタイムに描画するのは速度的に無理なので、実用にはならないのですけど。どう考えても、最初からレンダリング済みのビットマップ画像を用意しておくべきだなと。
更に、このやり方、現状ではかなりトホホな点があって。cairo で描画した後、結果を一旦 pngファイルでHDDに保存して、それを DXRuby の Image にロードし直していたりするわけで。
これがもし、cairo の Surface から、pngファイルとして書き出すべきバイナリデータを直接取得できれば…。あるいは、Surface内容をRGBAの配列で取得できれば、わざわざクソ遅いHDDにアクセスしなくても済むのですけど。残念ながら、そのようなメソッドは見つからなくて。
それにしても、swfのシェイプをこうして描画できるということは、svgも描画できたりするのかしら。たしか、svg を解析・描画する Rubyライブラリも存在していたはずなので、ちと試してみたいところ。
◎ メモリマップドファイルは使えないかな。 :
メモリ上に仮想ファイルシステムの類でも作れたら、HDDにアクセスしなくても済むんじゃないかと思えてきたのだけど。そういうことができるライブラリってあるのかしら。
_メモリマップトファイル - Wikipedia には、
_Rubyist Magazine - Ruby Library Report 【第 4 回】 Win32Utils
_djberg96/win32-mmap - GitHub
もしかして、Windows + Ruby なら、win32-mmap てのが使える…?
_メモリマップトファイル - Wikipedia には、
Ruby : Mmap というgem(ライブラリ)があり、メモリマップトファイルを実装している。という記述があったのだけど。
_Rubyist Magazine - Ruby Library Report 【第 4 回】 Win32Utils
_djberg96/win32-mmap - GitHub
もしかして、Windows + Ruby なら、win32-mmap てのが使える…?
◎ DXRuby + cairo の組み合わせ。 :
cairo の使い方については、
_rcairo 事始め - takihiro日記
を参考にさせてもらって試していたのですけど。せっかくだから、DXRuby で結果表示をするサンプルも置いときます。
_test_cairo1.rb
以下のような感じになります。
_test_cairo1.rb
# cairo のテスト # # 以下を参考にしました。 # # rcairo 事始め - takihiro日記 # http://d.hatena.ne.jp/takihiro/20100331/1269992290 require 'cairo' require 'dxruby' require 'tempfile' w, h = 640 - 32, 480 - 32 surface = Cairo::ImageSurface.new(w, h) context = Cairo::Context.new(surface) # 背景色を指定 context.set_source_rgba(0, 0, 0, 0) # 透明 context.rectangle(0, 0, w, h) context.fill # 四角を書く context.set_source_color(Cairo::Color::RED) x, y, rw, rh = 20, 20, w / 2, h / 2 context.rectangle(x, y, rw, rh) context.fill_preserve context.set_source_color(Cairo::Color::BLACK) context.stroke # 円を書く context.set_source_color(Cairo::Color::GREEN) r = h / 3 x, y, rw, rh = 100, 30, 50, 50 context.arc(w/2, h/2, r, 0, 2 * Math::PI) context.fill_preserve context.set_source_color(Cairo::Color::BLUE) context.stroke # 多角形 context.set_source_color(Cairo::Color::YELLOW) context.move_to(30, 30) context.line_to(20, 60) context.line_to(40, 80) context.line_to(80, 40) context.line_to(60, 30) context.line_to(30, 30) context.fill_preserve context.set_source_color(Cairo::Color::PURPLE) context.stroke # 重ねる画像を設定 surface2 = Cairo::ImageSurface.from_png('sample2.png') context.set_source(surface2, w - surface2.width - 24, h - surface2.height - 24) context.paint # 文字配置 context.set_source_rgb(255, 255, 255) context.font_size = 26 context.move_to(10, 150) context.show_text('文字') # フォントを指定してないので文字化けする context.move_to(10, 180) context.select_font_face('メイリオ', 0, 0) context.show_text('メイリオフォント') # ---------------------------------------- # 一時ファイルを作成 temp = Tempfile.new(['test', '.png']) temp.binmode temp.close # pngファイルに出力 surface.write_to_png(temp.path) # DXRubyで読み込み img = Image.load(temp.path) temp.close(true) # DXRubyで表示 Window.bgcolor = C_BLUE Window.loop do break if Input.keyPush?(K_ESCAPE) Window.draw(16, 16, img) end
以下のような感じになります。
[ ツッコむ ]
#2 [cg_tools] フリーで使えるドローソフトを試用してみたり
Drawgraphic 2 がちょっとアレなソフトだったので、もしかするとフリーソフトのほうがグッドだったりしないのかなと疑念が湧いて。ググっていたら、いくつかのドローソフトが気になったので、それぞれ試用してみたりして。
環境は、Windows7 x64。
ちなみに、自分、普段は、 _Inkscape 0.48.2 や _LibreOffice Draw を使ってます。
環境は、Windows7 x64。
ちなみに、自分、普段は、 _Inkscape 0.48.2 や _LibreOffice Draw を使ってます。
◎ Dynamic Draw を試用。 :
_Dynamic Draw
Drawgraphic 2 との比較だけど。
ただ、操作性については若干難有り。
そんな感じで、操作性・作業のしやすさに関しては、Drawgraphic 2 > Dynamic Draw > LibreOffice Draw、という印象。
他に気づいた点をメモ。
Drawgraphic 2 との比較だけど。
- ビットマップ画像保存時、背景を透明にして出力できる。(ファイル → 選択部品の画像をエクスポート、を選べばビットマップ画像として保存できる)
- ビットマップ画像保存時、アンチエイリアスを有効にして出力できる。
- svgエクスポートにも対応。
- 一瞬で起動する。爆速。
ただ、操作性については若干難有り。
- LibreOffice Draw ほど酷くはないけど、Drawgraphic 2 に比べると、色や線幅の指定が時々元に戻ってしまうので、連続での作業がしづらい。
- メニューの表記が独特・Windowsの一般的なアプリから乖離していて、パッと見で「難しそう」と感じてしまう。ショートカットキーの割り当てを強調して伝えたいのは理解できるけど…。「F.ファイル E.編集 V.表示」より、「ファイル(F) 編集(E) 表示(V)」のほうが良いのでは…。
- アイコンが全て白黒なので、ツールボタンの場所や定義が把握しにくい。昔の*NIX系ソフトでよく見かけた、ストイックなノリに近いというか。
そんな感じで、操作性・作業のしやすさに関しては、Drawgraphic 2 > Dynamic Draw > LibreOffice Draw、という印象。
他に気づいた点をメモ。
- 半透明塗りは無いらしい。
- アンチエイリアス有効、かつ、背景を透明にしてビットマップ画像を出力すると、境界が汚くなる。いわゆるフリンジ?が出ちゃう。
◎ グリッドをどの階層に描画するかという問題。 :
Drawgraphic 2 も、Dynamic Draw も、図形を塗り潰すとグリッドが隠れてしまって、途端に作業しづらくなるのだけど。
これが Inkscape なら、図形を塗り潰してもグリッド線が上に表示され続けるので、作業が快適だなと気付いたり。その代り(?)、Inkscape は全てがモッサリですが。
Drawgraphic 2 は、図形のアウトラインだけ描画するモード(ワイヤーフレーム表示)があるので、グリッドに頼った作業をするのであれば、そのモードで表示してしまうのもアリかなと。
たしか、FREEHAND にも簡易描画モードがあったような気がする。昔のドローソフトは、PCスペックが低くても作業できるようにするために、描画処理を軽くする仕様も求められたのだろうけど。結果的に、グリッドに頼った作業をする時も、回避策が存在している状態になったと言えるのかも。
Dynamic Draw には、アウトラインだけ描画するモードも、グリッドを最前面に描画する設定も、どちらも無いように見えました。
これが Inkscape なら、図形を塗り潰してもグリッド線が上に表示され続けるので、作業が快適だなと気付いたり。その代り(?)、Inkscape は全てがモッサリですが。
Drawgraphic 2 は、図形のアウトラインだけ描画するモード(ワイヤーフレーム表示)があるので、グリッドに頼った作業をするのであれば、そのモードで表示してしまうのもアリかなと。
たしか、FREEHAND にも簡易描画モードがあったような気がする。昔のドローソフトは、PCスペックが低くても作業できるようにするために、描画処理を軽くする仕様も求められたのだろうけど。結果的に、グリッドに頼った作業をする時も、回避策が存在している状態になったと言えるのかも。
Dynamic Draw には、アウトラインだけ描画するモードも、グリッドを最前面に描画する設定も、どちらも無いように見えました。
◎ ParaDrawを試用。 :
_ParaDraw
ただ、ベクターデータとして swf か pdr でしか保存できないあたりが厳しい…。
- グリッド表示・吸着機能がある。かつ、図形を塗り潰してもグリッドは手前に表示されてるので作業しやすい。
- ビットマップ画像保存時は背景を透明にすることもできる。
- アンチエイリアスもかかってる。
ただ、ベクターデータとして swf か pdr でしか保存できないあたりが厳しい…。
◎ pdr/swf/svg関係の変換ツール。 :
_PDR2SVG
pdr (ParaDraw形式) → svg変換ができる。試してみたところ、一部の線データが消滅(したように見えた)けど、そこそこsvgに変換してくれた。 _SVG終章 - パラフラノススメ - Yahoo!ブログ という記事によると、Flashとsvgは線の太さ(ストロークの太さ)について仕様が違うので再現は難しいらしい。
_SWF2SVG
swf → svg変換ができる。Adobe AIR製アプリ。 _FlashファイルからシェイプをSVGとして抜き出す - SWF2SVG MOONGIFT によると、コマンドラインツールだそうで、GUIは無し。以下のようなバッチファイルを、PATHの通ったところに置いて使ってみたり。
swf2svg.bat
pdr (ParaDraw形式) → svg変換ができる。試してみたところ、一部の線データが消滅(したように見えた)けど、そこそこsvgに変換してくれた。 _SVG終章 - パラフラノススメ - Yahoo!ブログ という記事によると、Flashとsvgは線の太さ(ストロークの太さ)について仕様が違うので再現は難しいらしい。
_SWF2SVG
swf → svg変換ができる。Adobe AIR製アプリ。 _FlashファイルからシェイプをSVGとして抜き出す - SWF2SVG MOONGIFT によると、コマンドラインツールだそうで、GUIは無し。以下のようなバッチファイルを、PATHの通ったところに置いて使ってみたり。
swf2svg.bat
@set SWF2SVGPATH="C:\Program Files (x86)\SWF2SVG\SWF2SVG.exe" %SWF2SVGPATH% %1 %2 %3 %4 %5 %6 %7 %8 %9こちらも比較的、swfの見た目を再現してくれた。
◎ J.S Draw を試用。 :
_J.S Draw
_すらすらプログラマー J.S Draw
操作性・作業のしやすさに関しては、LibreOffice Draw と似た感じで、現時点ではあまりよろしくなく。図形を置くたびに色設定その他がリセットされたり、図形を塗り潰すとグリッドが隠れてしまったりで。
鋭意開発中のソフトらしく、機能面はまだまだこれから、らしい。しかし、それでも…。
_すらすらプログラマー J.S Draw
操作性・作業のしやすさに関しては、LibreOffice Draw と似た感じで、現時点ではあまりよろしくなく。図形を置くたびに色設定その他がリセットされたり、図形を塗り潰すとグリッドが隠れてしまったりで。
鋭意開発中のソフトらしく、機能面はまだまだこれから、らしい。しかし、それでも…。
- 描画画面はアンチエイリアスがかかっている。
- 保存形式としてxmlが選べる。
[ ツッコむ ]
#3 [anime][neta] 「謎の支援者」ネタ
夢の中で、「盲目の美少女が、周囲からアレコレ助けてもらうのだけど、実はその周囲とは」てなネタを見て。目が覚めてから、ちょっと考え込んだり。
元ネタは、何だろうなあ…。
とりあえず、自分が夢でソレを見たのは、「HUNTERxHUNTER」の影響じゃないかなと思ったのだけど。学生時代にも、山口美由紀先生の短編作品でそういうのを見たような気もするし。子供の頃に、怪談の類でそういうネタを見ていたような気もするし。何にせよ、メジャーな元ネタ、様々なアレンジ作品があるような気がする。
「『周囲』の正体は何か?」という問いに対して、各人がどんな答えを出してくるかで、なんちゃって性格診断もできるかもしれないなと。幽霊だったり、ロボットだったり、モンスターだったり、あるいは、れっきとした人間だけど裏があったり、等々色々思いつくだろうけど。どれを思いついたのかで、その人の嗜好が分かりそう。真っ先に幽霊を思いつく人と、ロボットを思いつく人では、明らかに属性が違うだろから、「貴方は○○派です」と、テキトーな決めつけで分類して会話のネタにできたりしそう。ていうかソレってロールシャッハテストなのかな。
こういうネタは、小説だと表現しやすいのだろうな。「彼」「彼女」とだけ記述しておいて、実はこうだったのです、てな見せ方がしやすいし。小説は、本来の設定とは全く異なるイメージを読者が想像してしまうように、誘導することがたやすい。文字情報しかないから、意図的に誤解させる、という手管が使える。
漫画やアニメだと、ちょっと難しいよなと。「HUNTERxHUNTER」のように、本来そこにある状況をそのまま描く感じになって、怪談っぽい印象が随分と弱くなってしまう。
いや、違う見せ方もあるか…。当人の思い込みをそのまま視覚化しちゃうソレ。読者側はうっすらと状況が分かってるのに、提示されてる光景が異質なので、そのギャップでクラクラしてしまう。高野文子先生の「田辺のつる」…でしたっけか? あの見せ方。
別に、視覚的な見せ方で凝る必要はないのか…。「あしながおじさん」だって、謎の支援者ネタだよな…。
要するに、支援者の正体を隠しておいて、それを開示していくことで、話は作れるのだろうなと。自分が夢で見た「盲目の美少女」というソレは、支援者の姿を隠すために要する設定でしかなく。別の何かで隠せれば、それで済んでしまうのかも。
と、ここまで書いて、ふと思い出したけど。この手の元ネタは、「耳なし芳一」じゃないのかな…。
元ネタは、何だろうなあ…。
とりあえず、自分が夢でソレを見たのは、「HUNTERxHUNTER」の影響じゃないかなと思ったのだけど。学生時代にも、山口美由紀先生の短編作品でそういうのを見たような気もするし。子供の頃に、怪談の類でそういうネタを見ていたような気もするし。何にせよ、メジャーな元ネタ、様々なアレンジ作品があるような気がする。
「『周囲』の正体は何か?」という問いに対して、各人がどんな答えを出してくるかで、なんちゃって性格診断もできるかもしれないなと。幽霊だったり、ロボットだったり、モンスターだったり、あるいは、れっきとした人間だけど裏があったり、等々色々思いつくだろうけど。どれを思いついたのかで、その人の嗜好が分かりそう。真っ先に幽霊を思いつく人と、ロボットを思いつく人では、明らかに属性が違うだろから、「貴方は○○派です」と、テキトーな決めつけで分類して会話のネタにできたりしそう。ていうかソレってロールシャッハテストなのかな。
こういうネタは、小説だと表現しやすいのだろうな。「彼」「彼女」とだけ記述しておいて、実はこうだったのです、てな見せ方がしやすいし。小説は、本来の設定とは全く異なるイメージを読者が想像してしまうように、誘導することがたやすい。文字情報しかないから、意図的に誤解させる、という手管が使える。
漫画やアニメだと、ちょっと難しいよなと。「HUNTERxHUNTER」のように、本来そこにある状況をそのまま描く感じになって、怪談っぽい印象が随分と弱くなってしまう。
いや、違う見せ方もあるか…。当人の思い込みをそのまま視覚化しちゃうソレ。読者側はうっすらと状況が分かってるのに、提示されてる光景が異質なので、そのギャップでクラクラしてしまう。高野文子先生の「田辺のつる」…でしたっけか? あの見せ方。
別に、視覚的な見せ方で凝る必要はないのか…。「あしながおじさん」だって、謎の支援者ネタだよな…。
要するに、支援者の正体を隠しておいて、それを開示していくことで、話は作れるのだろうなと。自分が夢で見た「盲目の美少女」というソレは、支援者の姿を隠すために要する設定でしかなく。別の何かで隠せれば、それで済んでしまうのかも。
と、ここまで書いて、ふと思い出したけど。この手の元ネタは、「耳なし芳一」じゃないのかな…。
この記事へのツッコミ
[ ツッコミを読む(1) | ツッコむ ]
以上、1 日分です。
http://occult-atoaji.sakura.ne.jp/?p=8746