Class: Engine::GameObject

Inherits:
Object
  • Object
show all
Defined in:
lib/engine/game_object.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name = "Game Object", pos: Vector[0, 0, 0], rotation: 0, scale: Vector[1, 1, 1], components: [], parent: nil) ⇒ GameObject

Returns a new instance of GameObject.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/engine/game_object.rb', line 13

def initialize(name = "Game Object", pos: Vector[0, 0, 0], rotation: 0, scale: Vector[1, 1, 1], components: [], parent: nil)
  GameObject.object_spawned(self)
  @pos = Vector[pos[0], pos[1], pos[2] || 0]
  if rotation.is_a?(Numeric)
    @rotation = Vector[0, 0, rotation]
  else
    @rotation = rotation
  end
  @scale = scale
  @name = name
  @components = components.select { |component| !component.renderer? && !component.ui_renderer? }
  @renderers = components.select { |component| component.renderer? }
  @ui_renderers = components.select { |component| component.ui_renderer? }
  @created_at = Time.now
  @parent = parent
  parent.add_child(self) if parent

  components.each { |component| component.set_game_object(self) }
  components.each(&:start)
end

Instance Attribute Details

#componentsObject

Returns the value of attribute components.



11
12
13
# File 'lib/engine/game_object.rb', line 11

def components
  @components
end

#created_atObject

Returns the value of attribute created_at.



11
12
13
# File 'lib/engine/game_object.rb', line 11

def created_at
  @created_at
end

#nameObject

Returns the value of attribute name.



11
12
13
# File 'lib/engine/game_object.rb', line 11

def name
  @name
end

#parentObject

Returns the value of attribute parent.



11
12
13
# File 'lib/engine/game_object.rb', line 11

def parent
  @parent
end

#posObject

Returns the value of attribute pos.



11
12
13
# File 'lib/engine/game_object.rb', line 11

def pos
  @pos
end

#renderersObject

Returns the value of attribute renderers.



11
12
13
# File 'lib/engine/game_object.rb', line 11

def renderers
  @renderers
end

#rotationObject

Returns the value of attribute rotation.



11
12
13
# File 'lib/engine/game_object.rb', line 11

def rotation
  @rotation
end

#scaleObject

Returns the value of attribute scale.



11
12
13
# File 'lib/engine/game_object.rb', line 11

def scale
  @scale
end

#ui_renderersObject

Returns the value of attribute ui_renderers.



11
12
13
# File 'lib/engine/game_object.rb', line 11

def ui_renderers
  @ui_renderers
end

Class Method Details

.destroy_allObject



179
180
181
182
183
# File 'lib/engine/game_object.rb', line 179

def self.destroy_all
  GameObject.objects.dup.each do |object|
    object.destroy! unless object.destroyed?
  end
end

.destroyed_objectsObject



214
215
216
# File 'lib/engine/game_object.rb', line 214

def self.destroyed_objects
  @destroyed_objects ||= []
end

.erase_destroyed_objectsObject



154
155
156
157
158
159
# File 'lib/engine/game_object.rb', line 154

def self.erase_destroyed_objects
  destroyed_objects.each do |object|
    object._erase!
  end
  @destroyed_objects = []
end

.mesh_renderersObject



194
195
196
197
198
# File 'lib/engine/game_object.rb', line 194

def self.mesh_renderers
  GameObject.objects.flat_map do |object|
    object.renderers
  end
end

.method_added(name) ⇒ Object



5
6
7
8
9
# File 'lib/engine/game_object.rb', line 5

def self.method_added(name)
  @methods ||= Set.new
  return if name == :initialize || name == :destroyed?
  @methods.add(name)
end

.object_spawned(object) ⇒ Object



206
207
208
# File 'lib/engine/game_object.rb', line 206

def self.object_spawned(object)
  objects << object
end

.objectsObject



210
211
212
# File 'lib/engine/game_object.rb', line 210

def self.objects
  @objects ||= []
end

.render_ui(delta_time) ⇒ Object



200
201
202
203
204
# File 'lib/engine/game_object.rb', line 200

def self.render_ui(delta_time)
  GameObject.objects.each do |object|
    object.ui_renderers.each { |renderer| renderer.update(delta_time) }
  end
end

.update_all(delta_time) ⇒ Object



185
186
187
188
189
190
191
192
# File 'lib/engine/game_object.rb', line 185

def self.update_all(delta_time)
  GameObject.objects.each do |object|
    object.components.each { |component| component.update(delta_time) }
  end
  
  Component.erase_destroyed_components
  GameObject.erase_destroyed_objects
end

Instance Method Details

#_erase!Object



144
145
146
147
148
149
150
151
152
# File 'lib/engine/game_object.rb', line 144

def _erase!
  GameObject.objects.delete(self)
  parent.children.delete(self) if parent
  name = @name
  self.class.instance_variable_get(:@methods).each do |method|
    singleton_class.send(:undef_method, method)
    singleton_class.send(:define_method, method) { raise "This object has been destroyed: #{name}" }
  end
end

#add_child(child) ⇒ Object



42
43
44
45
# File 'lib/engine/game_object.rb', line 42

def add_child(child)
  child.parent = self
  children << child
end

#childrenObject



38
39
40
# File 'lib/engine/game_object.rb', line 38

def children
  @children ||= Set.new
end

#destroy!Object



133
134
135
136
137
138
139
140
141
142
# File 'lib/engine/game_object.rb', line 133

def destroy!
  return unless GameObject.objects.include?(self)
  children.each(&:destroy!)
  components.each(&:destroy!)
  ui_renderers.each(&:destroy!)
  renderers.each(&:destroy!)

  GameObject.destroyed_objects << self unless @destroyed
  @destroyed = true
end

#destroyed?Boolean

Returns:

  • (Boolean)


129
130
131
# File 'lib/engine/game_object.rb', line 129

def destroyed?
  @destroyed
end

#forwardObject



173
174
175
176
177
# File 'lib/engine/game_object.rb', line 173

def forward
  return @forward if @cached_forward_rotation == rotation
  @cached_forward_rotation = rotation.dup
  @forward = local_to_world_direction(Vector[0, 0, 1])
end

#local_to_world_coordinate(local) ⇒ Object



77
78
79
80
81
# File 'lib/engine/game_object.rb', line 77

def local_to_world_coordinate(local)
  local_x4 = Matrix[[local[0], local[1], local[2], 1.0]]
  world = local_x4 * model_matrix
  Vector[world[0, 0], world[0, 1], world[0, 2]]
end

#local_to_world_direction(local) ⇒ Object



89
90
91
# File 'lib/engine/game_object.rb', line 89

def local_to_world_direction(local)
  local_to_world_coordinate(local) - pos
end

#model_matrixObject



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 'lib/engine/game_object.rb', line 99

def model_matrix
  cache_key = [@pos.dup, @rotation.dup, @scale.dup, @parent&.model_matrix&.to_a]
  @model_matrix = nil if @model_matrix_cache_key != cache_key
  @model_matrix_cache_key = cache_key
  @model_matrix ||=
    begin
      rot = rotation * Math::PI / 180

      cos_x = Math.cos(rot[0])
      cos_y = Math.cos(rot[1])
      cos_z = Math.cos(rot[2])

      sin_x = Math.sin(rot[0])
      sin_y = Math.sin(rot[1])
      sin_z = Math.sin(rot[2])

      Matrix[
        [scale[0] * (cos_y * cos_z), scale[0] * (-cos_y * sin_z), scale[0] * sin_y, 0],
        [scale[1] * (cos_x * sin_z + sin_x * sin_y * cos_z), scale[1] * (cos_x * cos_z - sin_x * sin_y * sin_z), scale[1] * -sin_x * cos_y, 0],
        [scale[2] * (sin_x * sin_z - cos_x * sin_y * cos_z), scale[2] * (sin_x * cos_z + cos_x * sin_y * sin_z), scale[2] * cos_x * cos_y, 0],
        [x, y, z, 1]
      ]
    end
  if parent
    @model_matrix * parent.model_matrix
  else
    @model_matrix
  end
end

#rightObject



167
168
169
170
171
# File 'lib/engine/game_object.rb', line 167

def right
  return @right if @cached_right_rotation == rotation
  @cached_right_rotation = rotation.dup
  @right = local_to_world_direction(Vector[1, 0, 0])
end

#rotate_around(axis, angle) ⇒ Object



93
94
95
96
97
# File 'lib/engine/game_object.rb', line 93

def rotate_around(axis, angle)
  rotation_quaternion = Quaternion.from_angle_axis(angle, axis)

  @rotation = (rotation_quaternion * Quaternion.from_euler(rotation)).to_euler
end

#to_sObject



34
35
36
# File 'lib/engine/game_object.rb', line 34

def to_s
  @name
end

#upObject



161
162
163
164
165
# File 'lib/engine/game_object.rb', line 161

def up
  return @up if @cached_up_rotation == rotation
  @cached_up_rotation = rotation.dup
  @up = local_to_world_direction(Vector[0, 1, 0])
end

#world_to_local_coordinate(world) ⇒ Object



83
84
85
86
87
# File 'lib/engine/game_object.rb', line 83

def world_to_local_coordinate(world)
  world_x4 = Matrix[[world[0], world[1], world[2], 1.0]]
  local = world_x4 * model_matrix.inverse
  Vector[local[0, 0], local[0, 1], local[0, 2]]
end

#xObject



53
54
55
# File 'lib/engine/game_object.rb', line 53

def x
  @pos[0]
end

#x=(value) ⇒ Object



57
58
59
# File 'lib/engine/game_object.rb', line 57

def x=(value)
  @pos = Vector[value, y, z]
end

#yObject



61
62
63
# File 'lib/engine/game_object.rb', line 61

def y
  @pos[1]
end

#y=(value) ⇒ Object



65
66
67
# File 'lib/engine/game_object.rb', line 65

def y=(value)
  @pos = Vector[x, value, z]
end

#zObject



69
70
71
# File 'lib/engine/game_object.rb', line 69

def z
  @pos[2]
end

#z=(value) ⇒ Object



73
74
75
# File 'lib/engine/game_object.rb', line 73

def z=(value)
  @pos = Vector[x, y, value]
end