コードがものすごくアレなSpriteGroupクラス

行列とベクトルを使っているのでDXRuby1.1系専用となるが、SpriteGroupクラスを作ったので公開しとく。
機能としてはSpriteオブジェクトを配列にして複数保持し、任意の描画位置と回転原点を指定して保持Spriteすべての座標と画像を回転描画できる。そんだけ。
遅そうだしわかりにくいし意味不明な感じになってしまっているので、参考にしてもらうのがいいのかどうかはわからない。晒しあげって感じのニュアンスで。

require 'dxruby'

class Sprite
  attr_accessor :x, :y, :image
  attr_reader :param

  [:z, :angle, :scalex, :scaley, :centerx, :centery, :blend, :alpha].each do |key|
    eval(<<-EOS)
      def #{key}
        @param[:#{key}]
      end
      def #{key}=(val)
        @param[:#{key}] = val
      end
    EOS
  end

  def initialize
    @param = {}
    @x = 0
    @y = 0
    @image = nil
  end
end

module Window
  def self.drawSprite(spr, x = 0, y = 0)
    spr = [spr] if !spr.is_a?(Array)
    spr.each do |s|
      if s.is_a?(SpriteGroup)
        s.render(x, y)
      else
        Window.drawEx(x + s.x, y + s.y, s.image, s.param)
      end
    end
  end
end

class SpriteGroup
  attr_accessor :x, :y, :sprites, :centerx, :centery

  def initialize(spr = nil)
    @sprites = spr
    @matrix = Matrix.new([
      [1,0,0],
      [0,1,0],
      [0,0,1]
    ])
    @angle = 0
    @x = 0
    @y = 0
    @centerx = 0.0
    @centery = 0.0
  end

  def render(x, y)
    @sprites.each do |s|
      temp = Matrix.new([
        [1, 0, 0],
        [0, 1, 0],
        [s.image.width/2.0 - @centerx, s.image.height/2.0 - @centery, 1]
      ]) * @matrix * Matrix.new([
        [1, 0, 0],
        [0, 1, 0],
        [-s.image.width/2.0 + @centerx, -s.image.height/2.0 + @centery, 1]
      ])
      vec = Vector.new(s.x, s.y, 1) * temp
      param = s.param.dup
      param[:angle] = (param[:angle] || 0.0) + @angle
      Window.drawEx(x + @x + vec.x, y + @y + vec.y, s.image, param)
    end
  end

  def angle
    @angle
  end

  def angle=(val)
    cos = Math.cos(val * Math::PI / 180)
    sin = Math.sin(val * Math::PI / 180)
    @matrix = Matrix.new([
      [ cos, sin, 0],
      [-sin, cos, 0],
      [  0,    0, 1]
    ])
    @angle = val
  end
end

s1 = Sprite.new
s1.image = Image.new(50,50,[255,255,0])
s1.x = s1.y = 0
s2 = Sprite.new
s2.image = Image.new(50,50,[255,0,255])
s2.x = s2.y = 100
s3 = Sprite.new
s3.image = Image.new(50,50,[255,255,255])
s3.x = s3.y = 200

# SpriteGroupのcenterx/yはSpriteGroupの原点x/yからの相対回転中心
sg = SpriteGroup.new
sg.sprites = [s1, s2, s3] # Spriteの配列を入れる
sg.centerx = sg.centery = 125
sg.x = sg.y = 100

Window.loop do 
  sg.angle += 1
  Window.drawSprite(sg)
end