Skip to content

Instantly share code, notes, and snippets.

@mirichi
Last active August 29, 2015 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mirichi/f76ec071ee842d99008b to your computer and use it in GitHub Desktop.
Save mirichi/f76ec071ee842d99008b to your computer and use it in GitHub Desktop.
Entityクラス3歩目
require 'dxruby'
# Spriteをツリー構造にして相対表現で扱うためのクラス
class Entity < Sprite
attr_accessor :parent, :children
def self.main_stage
@@main_stage
end
def self.update
@@main_stage.update
@@main_stage.recalc
@@main_stage.draw
end
def initialize(x=0, y=0, image=nil)
super(0, 0, image)
@children = []
@_x = x
@_y = y
@_z = 0
@_angle = 0
@_scale_x = 1
@_scale_y = 1
@_alpha = 0
end
# 子要素を追加する
def add_child(child)
@children << child
child.parent = self
child.target = self.target
self
end
# 子要素を取り外す
def remove_child(child)
@children.delete(child)
child.parent = nil
child.target = nil
self
end
def update
super
@children.each do |child|
child.update
end
self
end
def draw
super
@children.each do |child|
child.draw
end
self
end
# 以下の従来のパラメータは相対指定のメソッドに置き換えられ、絶対値はabs_でアクセスする
# ただし、再計算(Entity#recalc)しないとabs系の値は正しくならない。
alias_method :abs_x, :x
alias_method :abs_x=, :x=
alias_method :abs_y, :y
alias_method :abs_y=, :y=
alias_method :abs_z, :z
alias_method :abs_z=, :z=
alias_method :abs_angle, :angle
alias_method :abs_angle=, :angle=
alias_method :abs_scale_x, :scale_x
alias_method :abs_scale_x=, :scale_x=
alias_method :abs_scale_y, :scale_y
alias_method :abs_scale_y=, :scale_y=
alias_method :abs_alpha, :alpha
alias_method :abs_alpha=, :alpha=
def x;@_x;end
def x=(v);@_x = v;end
def y;@_y;end
def y=(v);@_y = v;end
def z;@_z;end
def z=(v);@_z = v;end
def angle;@_angle;end
def angle=(v);@_angle = v;end
def scale_x;@_scale_x;end
def scale_x=(v);@_scale_x = v;end
def scale_y;@_scale_y;end
def scale_y=(v);@_scale_y = v;end
def alpha;@_alpha;end
def alpha=(v);@_alpha = v;end
# 上位のパラメータを反映させ、末端オブジェクトまで絶対値を算出する
# 条件によって必要ない計算がいっぱいあるので高速化の余地は大きい
def recalc(z=0, angle=0, alpha=255, m=Matrix.new([[1,0,0],[0,1,0],[0,0,1]]))
if self.offset_sync
# offset_syncがtrueの場合は回転原点は相対位置(0,0)
cx = cy = 0
else
# 回転原点を取得する
cx = self.center_x || 0
cy = self.center_y || 0
end
# 回転中心座標
c = Vector.new(@_x + cx, @_y + cy)
# 親から引きついた行列を適用して座標を計算する
c = c * m
self.abs_x = c.x - cx
self.abs_y = c.y - cy
# その他パラメータは相対値を算出
self.abs_angle = @_angle + angle
self.abs_z = @_z + z
self.alpha = @_alpha / 255.0 * alpha / 255.0 * 255.0
# 子に引き継ぐ行列を計算
mp = Matrix.translation(-cx, -cy) * Matrix.rotation(@_angle) * Matrix.translation(cx + @_x, cy + @_y) * m
# 子の計算
@children.each do |child|
child.recalc(self.abs_z, self.abs_angle, self.alpha, mp)
end
self
end
# Entityのツリー構造を(ちょっと変だけどとりあえず)配列化する
# 配下のEntityをまとめて衝突判定する用
def to_a
if @children
ary = [self]
@children.map do |child|
ary << child.to_a
end
ary
else
self
end
end
@@main_stage = Entity.new
Window.after_call[:entity] = ->{Entity.update}
end
# 複数のEntityをグループ化するためだけのEntityGroupクラス
class EntityGroup < Entity
end
group = EntityGroup.new
a = Entity.new(200, 200, Image.new(100, 20, C_WHITE))
a.offset_sync = true
a.center_x = 10
a.center_y = 10
b = Entity.new(82, 0, Image.new(80, 16, C_RED))
b.offset_sync = true
b.center_x = 8
b.center_y = 8
a.add_child(b)
c = Entity.new(66, 0, Image.new(60, 12, C_GREEN))
c.offset_sync = true
c.center_x = 6
c.center_y = 6
b.add_child(c)
d = Entity.new(50, 0, Image.new(40, 8, C_BLUE))
d.offset_sync = true
d.center_x = 4
d.center_y = 4
c.add_child(d)
group.add_child(a)
Entity.main_stage.add_child(group)
s = Sprite.new
s.collision = [0, 0]
Window.loop do
a.angle += 0.5
b.angle += 1
c.angle += 2
d.angle += 3
s.x, s.y = Input.mouse_x, Input.mouse_y
if s === group.to_a
Window.draw_text(0, 0, "hit", Font.default)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment