Class: SpriterSconParser

Inherits:
Object
  • Object
show all
Defined in:
spritersconparser.rb

Overview

Note:

DXRuby, json が必要

Note:

ruby spritersconparser.rb IN_FILE.scon で表示テストができます。

Spriter保存ファイル(.scon)を解析してアニメを描画するクラス

Examples:

DXRubyを使って描画する例

require 'dxruby'
require_relative 'spritersconparser'
ani = SpriterSconParser.new("img00/girl_spriter.scon")
ani.set_anime("default", "run")
Window.loop do
  ani.draw(320, 240 + 120)
  ani.update
end

Version:

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (SpriterSconParser) initialize(filepath)

コンストラクタ

Parameters:

  • filepath (String)

    Spriter保存ファイル(.scon)のパス



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'spritersconparser.rb', line 67

def initialize(filepath)
  f = open(filepath)
  @json_data = f.read
  f.close

  @anime_data = JSON.parse(@json_data)
  @entity_name = ""
  @anime_name = ""
  @anime_length = 0
  @animation = nil
  @entity_list = []
  @keyframe_list = []
  @keyframe = 0
  @keyframe_length = 0
  @current_time = 0
  @entity = {}
  @hflip = false
  @vflip = false
  @angle = 0

  @anime_data["entity"].each do |et|
    # pp et.keys
    # ["animation", "character_map", "id", "name", "obj_info"]

    adata = {}
    et["animation"].each do |a|
      # pp a.keys
      # ["gline", "id", "interval", "length", "mainline", "name", "timeline"]

      aname = a["name"]
      mls = arrange_mainline(a["mainline"])
      tls = arrange_timeline(a)
      adata[aname] = {
        :id => a["id"],
        :gline => a["gline"],
        :interval => a["interval"],
        :length => a["length"],
        :mainline => mls,
        :timeline => tls
      }
    end

    odata = arrange_objinfo(et["obj_info"])

    id, name = et["id"], et["name"]
    @entity[name] = {
      :id => id,
      :character_map => et["character_map"],
      :animation => adata,
      :obj_info => odata
    }
  end

  # dump_entity
  load_images(filepath, @anime_data["folder"])

  @entity_list = @entity.keys
  ename = @entity_list[0]
  aname = anime_list(ename)[0]
  set_anime(ename, aname)
end

Instance Attribute Details

- (Number) angle

Returns 全体の回転角度。単位は度。プラスで反時計回り。0-360の範囲

Returns:

  • (Number)

    全体の回転角度。単位は度。プラスで反時計回り。0-360の範囲



63
64
65
# File 'spritersconparser.rb', line 63

def angle
  @angle
end

- (Hash) animation

Returns アニメパターンが持つデータ

Returns:

  • (Hash)

    アニメパターンが持つデータ



42
43
44
# File 'spritersconparser.rb', line 42

def animation
  @animation
end

- (Integer) anime_length

Returns アニメの長さ(単位はms)

Returns:

  • (Integer)

    アニメの長さ(単位はms)



39
40
41
# File 'spritersconparser.rb', line 39

def anime_length
  @anime_length
end

- (String) anime_name

Returns アニメパターン名

Returns:

  • (String)

    アニメパターン名



36
37
38
# File 'spritersconparser.rb', line 36

def anime_name
  @anime_name
end

- (Integer) current_time

Returns 現在の時間。単位はms。(ただし実時間ではない)

Returns:

  • (Integer)

    現在の時間。単位はms。(ただし実時間ではない)



54
55
56
# File 'spritersconparser.rb', line 54

def current_time
  @current_time
end

- (Array<String>) entity_list

Returns entity名の配列

Returns:

  • (Array<String>)

    entity名の配列



30
31
32
# File 'spritersconparser.rb', line 30

def entity_list
  @entity_list
end

- (String) entity_name

Returns entity名

Returns:

  • (String)

    entity名



33
34
35
# File 'spritersconparser.rb', line 33

def entity_name
  @entity_name
end

- (Boolean) hflip

Returns 水平反転フラグ

Returns:

  • (Boolean)

    水平反転フラグ



57
58
59
# File 'spritersconparser.rb', line 57

def hflip
  @hflip
end

- (Integer) keyframe

Returns 現在のキーフレーム

Returns:

  • (Integer)

    現在のキーフレーム



48
49
50
# File 'spritersconparser.rb', line 48

def keyframe
  @keyframe
end

- (Integer) keyframe_length

Returns キーフレーム個数

Returns:

  • (Integer)

    キーフレーム個数



51
52
53
# File 'spritersconparser.rb', line 51

def keyframe_length
  @keyframe_length
end

- (Array<Hash>) keyframe_list

Returns 各キーフレームのIDと長さをハッシュにした配列

Returns:

  • (Array<Hash>)

    各キーフレームのIDと長さをハッシュにした配列



45
46
47
# File 'spritersconparser.rb', line 45

def keyframe_list
  @keyframe_list
end

- (Boolean) vflip

Returns 垂直反転フラグ

Returns:

  • (Boolean)

    垂直反転フラグ



60
61
62
# File 'spritersconparser.rb', line 60

def vflip
  @vflip
end

Instance Method Details

- (Array<String>) anime_list(entname)

アニメパターン名の配列を取得

Parameters:

  • entname (String)

    entity名

Returns:

  • (Array<String>)

    アニメパターン名の入った配列



317
318
319
# File 'spritersconparser.rb', line 317

def anime_list(entname)
  return @entity[entname][:animation].keys
end

- (Object) debug_draw_cross(x, y, col, z = 0)

開発用。指定された座標に十字を描画

Parameters:

  • x (Number)

    x座標

  • y (Number)

    y座標

  • col (Array)

    色配列。。それぞれ0から255の範囲で指定

  • z (Number) (defaults to: 0)

    描画優先順位



654
655
656
657
658
# File 'spritersconparser.rb', line 654

def debug_draw_cross(x, y, col, z = 0)
  w = 3
  Window.drawLine(x-w, y, x+w, y, col, z)
  Window.drawLine(x, y-w, x, y+w, col, z)
end

- (Object) debug_draw_grid(bx, by)

開発用。画面にグリッドを描画

Parameters:

  • bx (Number)

    原点描画x座標

  • by (Number)

    原点描画y座標



663
664
665
666
667
668
669
670
671
672
673
674
675
676
# File 'spritersconparser.rb', line 663

def debug_draw_grid(bx, by)
  w, h = Window.width, Window.height
  sw, sh = 16, 16
  c = 128
  col = [128, c, c, c]
  bx.step(w, sw) { |x| Window.drawLine(x, 0, x, h, col) }
  bx.step(0, -sw) { |x| Window.drawLine(x, 0, x, h, col) }
  by.step(h, sh) { |y| Window.drawLine(0, y, w, y, col) }
  by.step(0, -sh) { |y| Window.drawLine(0, y, w, y, col) }

  col = [128, 0, 0]
  Window.drawLine(bx, 0, bx, h, col)
  Window.drawLine(0, by, w, by, col)
end

- (Object) debug_dump_disp_image

開発用。使用画像を描画



635
636
637
638
639
640
641
642
643
644
645
646
647
# File 'spritersconparser.rb', line 635

def debug_dump_disp_image
  x, y = 128, 240
  @folder.each do |id, files|
    files.each do |fid, d|
      name = d["name"]
      w, h = d["width"], d["height"]
      px, py = d["pivot_x"], d["pivot_y"]
      Window.draw(x, y, d["image"])
      draw_cross_line(x + px, y + py, C_CYAN)
      x += 64
    end
  end
end

- (Object) dec_keyframe

キーフレームを1つ戻す



327
328
329
# File 'spritersconparser.rb', line 327

def dec_keyframe
  @keyframe = (@keyframe + @keyframe_length - 1) % @keyframe_length
end

- (Object) draw(bx, by, z = 0, bone_draw = false, kf_only = false)

アニメを描画

Parameters:

  • bx (Number)

    描画位置 x

  • by (Number)

    描画位置 y

  • z (Number) (defaults to: 0)

    描画優先順位。値が小さければ奥に、大きければ手前に描画

  • bone_draw (Boolean) (defaults to: false)

    trueならボーンも描画、falseなら画像のみ描画

  • kf_only (Boolean) (defaults to: false)

    trueならキーフレームのみ描画、falseなら補完して描画



591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
# File 'spritersconparser.rb', line 591

def draw(bx, by, z = 0, bone_draw = false, kf_only = false)
  ml = @animation[:mainline]["key"][@keyframe]
  ct = (kf_only)? 0 : @current_time

  # draw bone
  if bone_draw
    ml[:bone_ref].each_key do |id|
      d = timeline_now(ml, id, ct, true, kf_only)
      x = d[:x]
      y = d[:y]
      name = d[:name]
      if name != nil
        img = @entity[@entity_name][:obj_info][name][:image]
        Window.drawEx(bx + x, by - y, img, :z => z + 20,
                      :center_x => 0, :center_y => img.height / 2,
                      :scale_x => d[:scale_x], :scale_y => d[:scale_y],
                      :angle => -d[:angle], :offset_sync => true,
                      :alpha => d[:a] * 255)
        # debug_draw_cross(bx + x, by - y, C_CYAN, z + 21)
      end
    end
  end

  # draw image
  ml[:object_ref].each_key do |id|
    d = timeline_now(ml, id, ct, false, kf_only)
    imgdt = @folder[d[:folder]][d[:file]]
    img = imgdt[:image]
    x = d[:x]
    y = d[:y]
    pvx = (!imgdt.has_key?(:pivot_x) or d[:pivot_x] != 0.0)? d[:pivot_x] : imgdt[:pivot_x]
    pvy = (!imgdt.has_key?(:pivot_y) or d[:pivot_y] != 1.0)? d[:pivot_y] : imgdt[:pivot_y]
    pvx *= img.width
    pvy = (1.0 - pvy) * img.height
    Window.drawEx(bx + x, by - y, img, :z => z + d[:z_index],
                  :center_x => pvx, :center_y => pvy,
                  :scale_x => d[:scale_x], :scale_y => d[:scale_y],
                  :angle => -d[:angle], :offset_sync => true,
                  :alpha => d[:a] * 255)
    # debug_draw_cross(bx + x, by - y, C_CYAN, z + 21)
  end
end

- (Object) inc_keyframe

キーフレームを1つ進める



322
323
324
# File 'spritersconparser.rb', line 322

def inc_keyframe
  @keyframe = (@keyframe + 1) % @keyframe_length
end

- (Object) reset_time

現在時間とキーフレーム値をリセット



348
349
350
351
352
353
354
355
356
357
358
359
# File 'spritersconparser.rb', line 348

def reset_time
  @current_time = 0
  @keyframe = 0
  @animation = @entity[@entity_name][:animation][@anime_name]
  @anime_length = @animation[:length]
  @keyframe_length = @animation[:mainline]["key"].length
  @keyframe_list.clear
  @keyframe_length.times do |i|
    ml = @animation[:mainline]["key"][i]
    @keyframe_list.push({"id" => i, "time" => ml.fetch("time", 0).to_i})
  end
end

- (Object) set_anime(entname, aniname, h_flip = false, v_flip = false, angle = 0)

アニメパターンを指定する

Parameters:

  • entname (String)

    entity名

  • aniname (String)

    アニメパターン名

  • h_flip (Boolean) (defaults to: false)

    水平方向反転フラグ。trueなら反転、falseならそのまま

  • v_flip (Boolean) (defaults to: false)

    垂直方向反転フラグ。trueなら反転、falseならそのまま

  • angle (Boolean) (defaults to: 0)

    全体の回転角度(単位は度)



337
338
339
340
341
342
343
344
345
# File 'spritersconparser.rb', line 337

def set_anime(entname, aniname, h_flip = false, v_flip = false, angle = 0)
  @entity_name = entname
  @anime_name = aniname
  @animation = @entity[@entity_name][:animation][@anime_name]
  @hflip = h_flip
  @vflip = v_flip
  @angle = 0
  reset_time
end

- (Object) update(fps_value = 60.0, is_inc = true)

Note:

内部で管理してる現在時間等は、実際の時間ではない。 60FPSなら本来1フレームは16.67msだが、内部では16msで計算してる。 Spriterが、60FPSピッタリでデータを作成できないため。

Note:

呼んだ途端に1フレーム分進んでしまうので、 先頭フレームをちゃんと描画したいなら、 描画前ではなく描画後に呼んだほうがいい。

内部の現在時間を1フレーム分進める

Parameters:

  • fps_value (Number) (defaults to: 60.0)

    FPS値。デフォルトは60

  • is_inc (Boolean) (defaults to: true)

    trueなら1フレーム進める、falseなら1フレーム戻す



571
572
573
574
575
576
577
578
579
580
581
582
583
# File 'spritersconparser.rb', line 571

def update(fps_value = 60.0, is_inc = true)
  ct = @current_time
  iv = (1000.0 / fps_value.to_f).truncate
  if is_inc
    ct = ct + iv
    ct = 0 if ct >= @anime_length
  else
    ct = ct - iv
    ct += @anime_length if ct < 0
  end
  @current_time = ct
  @keyframe = get_keyframe_id(@current_time)
end