-
-
Save mirichi/f76ec071ee842d99008b to your computer and use it in GitHub Desktop.
Entityクラス3歩目
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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