or2d 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,245 @@
1
+ module OR2D::Composites
2
+ # The Composite Sprite class is a composite entity that is made up of multiple sprites entities that behave as the composite layers.
3
+ class Sprite < OR2D::Composite
4
+ include OR2D::Animations::CompositeAnimations
5
+
6
+ # Constructs a new Composite Sprite object.
7
+ # @param options [Hash] a hash of options
8
+ def initialize(options)
9
+ super(options[:id] || "SpriteComposite_#{SecureRandom.uuid}")
10
+ if options[:layers]
11
+ options[:layers].each do |layer|
12
+ add_layer(layer[:type], layer, entity: layer[:entity])
13
+ end
14
+ else
15
+ add_layer(:sprite, options)
16
+ end
17
+ end
18
+
19
+ # Add a layer to the Sprite. This will also reorder the z-index of all other layers in the Sprite.
20
+ # @param type [Symbol] the type of Entity object to add
21
+ # @param options [Hash] a hash of options to pass to the Entity object
22
+ # @param entity [OR2D::Entity] an optional Entity object to add if the type is :entity
23
+ # @param position [Symbol] the position to add the layer to, either :top or :bottom
24
+ def add_layer(type, options, entity: nil, position: :top)
25
+ if @layers.empty?
26
+ super(type, options, entity: entity)
27
+ id = @layers.keys.first
28
+ elsif position == :top
29
+ super(type, options.merge(z: OR2D.game.entities[@layers.keys.first].resource.z + 1), entity: entity)
30
+ sort_by_z
31
+ id = @layers.keys.first
32
+ elsif position == :bottom
33
+ super(type, options.merge(z: OR2D.game.entities[@layers.keys.last].resource.z - 1), entity: entity)
34
+ sort_by_z
35
+ id = @layers.keys.last
36
+ else
37
+ add_layer(type, options, entity: entity, position: :top)
38
+ end
39
+
40
+ @layers[id][:offsets] = [options[:x_offset] || 0,
41
+ options[:y_offset] || 0,
42
+ options[:width_offset] || 0,
43
+ options[:height_offset] || 0]
44
+ apply_offsets(id)
45
+ id
46
+ end
47
+
48
+ # Remove a layer from the Sprite. This will also reorder the z-index of all other layers in the Sprite.
49
+ # @param id [String] the id of the layer to remove
50
+ def remove_layer(id)
51
+ super(id)
52
+ sort_by_z unless @layers.empty? || @layers.size == 1
53
+ end
54
+
55
+ # Bring a layer to the front of the Sprite. This will also reorder the z-index of all other layers in the Sprite.
56
+ # @param id [String] the id of the layer to bring to the front
57
+ def bring_to_front(id)
58
+ OR2D.game.entities[id].resource.z = OR2D.game.entities[@layers.keys.first].resource.z
59
+ @layers.each_key do |key|
60
+ next if key == id
61
+
62
+ OR2D.game.entities[key].resource.z -= 1
63
+ end
64
+ sort_by_z
65
+ end
66
+
67
+ # Send a layer to the back of the Sprite. This will also reorder the z-index of all other layers in the Sprite.
68
+ # @param id [String] the id of the layer to send to the back
69
+ def send_to_back(id)
70
+ OR2D.game.entities[id].resource.z = OR2D.game.entities[@layers.keys.last].resource.z
71
+ @layers.each_key do |key|
72
+ next if key == id
73
+
74
+ OR2D.game.entities[key].resource.z += 1
75
+ end
76
+ sort_by_z
77
+ end
78
+
79
+ # Swap the z-index of two layers in the Sprite. This will also reorder the z-index of all other layers in the Sprite.
80
+ # @param from_idx [String] the index of the id of the layer to swap
81
+ # @param to_idx [String] the index of the id of the layer to swap with
82
+ def swap(from_idx, to_idx)
83
+ from = @layers.keys[from_idx]
84
+ to = @layers.keys[to_idx]
85
+ OR2D.game.entities[from].resource.z, OR2D.game.entities[to].resource.z = OR2D.game.entities[to].resource.z, OR2D.game.entities[from].resource.z
86
+ sort_by_z
87
+ end
88
+
89
+ # Set the height of all layers in the Sprite.
90
+ # @param height [Integer] the height to set
91
+ def height=(height)
92
+ @layers.each_key do |id|
93
+ OR2D.game.entities[id].height = height + @layers[id][:offsets][3]
94
+ end
95
+ end
96
+
97
+ # Get the height of a specific layer.
98
+ # @param layer_idx [Integer] the index of the layer to get the height of
99
+ def get_layer_height(layer_idx = -1)
100
+ OR2D.game.entities[@layers.keys[layer_idx]].height
101
+ end
102
+
103
+ # Set the height of the Sprite or a specific layer with or without offsets.
104
+ # @param height [Integer] the height to set
105
+ # @param layer_id [String] the id of the layer to set the height of
106
+ # @param offsets [Boolean] whether or not to apply offsets to the height
107
+ def set_layer_height(layer_id, height, offsets: true)
108
+ OR2D.game.entities[layer_id].height = offsets ? height + @layers[layer_id][:offsets][3] : height
109
+ end
110
+
111
+ # Set the width of the Sprite.
112
+ # @param width [Integer] the width to set
113
+ def width=(width)
114
+ @layers.each_key do |id|
115
+ OR2D.game.entities[id].width = width + @layers[id][:offsets][2]
116
+ end
117
+ end
118
+
119
+ # Get the width of a specific layer.
120
+ # @param layer_idx [Integer] the index of the layer to get the width of
121
+ def get_layer_width(layer_idx = -1)
122
+ OR2D.game.entities[@layers.keys[layer_idx]].width
123
+ end
124
+
125
+ # Set the width of the Sprite or a specific layer with or without offsets.
126
+ # @param width [Integer] the width to set
127
+ # @param layer_id [String] the id of the layer to set the width of
128
+ # @param offsets [Boolean] whether or not to apply offsets to the width
129
+ def set_layer_width(layer_id, width, offsets: true)
130
+ OR2D.game.entities[layer_id].width = offsets ? width + @layers[layer_id][:offsets][2] : width
131
+ end
132
+
133
+ # Get the x-coordinate of the Sprite. This is determined by the last layer's x-coordinate.
134
+ # @return [Integer] the x-coordinate of the Sprite
135
+ def x
136
+ OR2D.game.entities[@layers.keys.last].x
137
+ end
138
+
139
+ # Set the x-coordinate of the Sprite with offsets.
140
+ # @param x_coordinate [Integer] the x-coordinate to set
141
+ def x=(x_coordinate)
142
+ @layers.each_key do |id|
143
+ OR2D.game.entities[id].x = x_coordinate + @layers[id][:offsets][0]
144
+ end
145
+ end
146
+
147
+ # Get the x-coordinate of a specific layer.
148
+ # @param layer_idx [Integer] the index of the layer to get the x-coordinate of
149
+ def get_layer_x(layer_idx = -1)
150
+ OR2D.game.entities[@layers.keys[layer_idx]].x
151
+ end
152
+
153
+ # Set the x-coordinate of a specific layer with or without offsets.
154
+ # @param x_coordinate [Integer] the x-coordinate to set
155
+ # @param layer_id [Integer] the layer to set the x-coordinate of
156
+ # @param offsets [Boolean] whether or not to apply offsets
157
+ def set_layer_x(layer_id, x_coordinate, offsets: true)
158
+ OR2D.game.entities[layer_id].x = offsets ? x_coordinate + @layers[layer_id][:offsets][0] : x_coordinate
159
+ end
160
+
161
+ # Get the y-coordinate of the Sprite. This is determined by the last layer's y-coordinate.
162
+ # @return [Integer] the y-coordinate of the Sprite
163
+ def y
164
+ OR2D.game.entities[@layers.keys.last].y
165
+ end
166
+
167
+ # Set the y-coordinate of the Sprite with offsets.
168
+ # @param y_coordinate [Integer] the y-coordinate to set
169
+ def y=(y_coordinate)
170
+ @layers.each_key do |id|
171
+ OR2D.game.entities[id].y = y_coordinate + @layers[id][:offsets][1]
172
+ end
173
+ end
174
+
175
+ # Get the y-coordinate of a specific layer.
176
+ # @param layer_idx [Integer] the index of the layer to get the y-coordinate of
177
+ def get_layer_y(layer_idx = -1)
178
+ OR2D.game.entities[@layers.keys[layer_idx]].y
179
+ end
180
+
181
+ # Set the y-coordinate of the Sprite or a specific layer with or without offsets.
182
+ # @param y_coordinate [Integer] the y-coordinate to set
183
+ # @param layer_id [String] the id of the layer to set the y-coordinate of
184
+ # @param offsets [Boolean] whether or not to apply offsets to the y-coordinate
185
+ def set_layer_y(layer_id, y_coordinate, offsets: true)
186
+ OR2D.game.entities[layer_id].y = offsets ? y_coordinate + @layers[layer_id][:offsets][1] : y_coordinate
187
+ end
188
+
189
+ # Plays all animations for layers that are visible.
190
+ # @param options [Hash] the options to play the animations with
191
+ # @note Animations should be passed using the following convention:
192
+ def play(options = {})
193
+ if options.key?(:layers)
194
+ options[:layers].each do |layer_id, options|
195
+ next unless @layers[layer_id][:show]
196
+ next unless OR2D.game.entities[layer_id].resource.respond_to?(:play)
197
+ next if options[:except].include?(layer_id)
198
+
199
+ OR2D.game.entities[layer_id].resource.play(animation: options[:animation],
200
+ loop: options[:loop],
201
+ flip: options[:flip],
202
+ &options[:done])
203
+
204
+ end
205
+ elsif options.key?(:layer)
206
+ return unless @layers[options[:layer]][:show]
207
+ return unless OR2D.game.entities[options[:layer]].resource.respond_to?(:play)
208
+
209
+ OR2D.game.entities[options[:layer]].resource.play(animation: options[:animation],
210
+ loop: options[:loop],
211
+ flip: options[:flip],
212
+ &options[:done])
213
+ else
214
+ @layers.each do |id, properties|
215
+ next unless properties[:show]
216
+ next unless OR2D.game.entities[id].resource.respond_to?(:play)
217
+ next if options[:except].include?(id)
218
+
219
+ OR2D.game.entities[id].resource.play(animation: options[:animation],
220
+ loop: options[:loop],
221
+ flip: options[:flip],
222
+ &options[:done])
223
+ end
224
+ end
225
+ end
226
+
227
+ # Sort the layers of the Sprite by their by z-coordinate.
228
+ def sort_by_z
229
+ @layers.keys
230
+ .sort_by! { |key| -OR2D.game.entities[key].resource.z }
231
+ .each { |k| @layers[k] = @layers.delete(k) }
232
+ end
233
+
234
+ private
235
+
236
+ def apply_all_offsets
237
+ @layers.each_key { |id| apply_offsets(id) }
238
+ end
239
+
240
+ def apply_offsets(layer_id)
241
+ OR2D.game.entities[layer_id].x += @layers[layer_id][:offsets][0]
242
+ OR2D.game.entities[layer_id].y += @layers[layer_id][:offsets][1]
243
+ end
244
+ end
245
+ end
@@ -0,0 +1,167 @@
1
+ module OR2D::Composites
2
+ # The Composite Text class is a composite entity that can be used to display multiple lines of text. It displays each line of text on a separate layer. It displays sentences character by character.
3
+ class Text < OR2D::Composite
4
+ include OR2D::Animations::CompositeAnimations
5
+
6
+ # Construct a new Composite Text object.
7
+ # @param options [Hash] the options to create the Composite Text object with
8
+ # @option options [Integer] :limit (24) the maximum number of characters that can be displayed on a single line
9
+ # @option options [Integer] :lines (0) the number of lines that can be displayed
10
+ # @option options [Integer] :update_interval (5) the number of frames between each update
11
+ def initialize(options = {})
12
+ super(options[:id] || "TextComposite_#{SecureRandom.uuid}")
13
+ @limit = options[:limit] || 24
14
+ @lines = 0
15
+ @update_interval = options[:update_interval] || 5
16
+ if options[:lines]
17
+ options[:lines].each do |line_opt|
18
+ add_line(line_opt)
19
+ end
20
+ elsif options[:line]
21
+ add_line(options[:line])
22
+ end
23
+ end
24
+
25
+ # Get the x coordinate of the text object.
26
+ # @param last [Boolean] whether to get the x coordinate of the last layer or the first layer
27
+ # @return [Integer] the x coordinate of the text object
28
+ def x(last: false)
29
+ OR2D.game.entities[last ? @layers.keys.last : @layers.keys.first].x
30
+ end
31
+
32
+ # Get the y coordinate of the text object.
33
+ # @param last [Boolean] whether to get the y coordinate of the last layer or the first layer
34
+ # @return [Integer] the y coordinate of the text object
35
+ def y(last: false)
36
+ OR2D.game.entities[last ? @layers.keys.last : @layers.keys.first].y
37
+ end
38
+
39
+ # Set the y coordinate of the text object.
40
+ # @param value [Integer] the y coordinate to set
41
+ def y=(value)
42
+ @layers.each_key do |key|
43
+ offset = if key == @layers.keys.first
44
+ 0
45
+ else
46
+ previous = @layers.keys[@layers.keys.index(key) - 1]
47
+ OR2D.game.entities[previous].y + (OR2D.game.entities[previous].resource.size / OR2D.scale)
48
+ end
49
+ OR2D.game.entities[key].y = value + offset
50
+ end
51
+ end
52
+
53
+ # Set the x coordinate of the text object.
54
+ # @param value [Integer] the x coordinate to set
55
+ def x=(value)
56
+ @layers.each_key do |key|
57
+ OR2D.game.entities[key].x = value
58
+ end
59
+ end
60
+
61
+ # Clear text for a specific layer or all layers
62
+ # @param layer_idx [Integer, Symbol] the index of the layer to clear or :all to clear all layers
63
+ def clear(layer_idx)
64
+ if layer_idx == :all
65
+ @layers.each do |id, properties|
66
+ properties[:buffer] = String.new
67
+ properties[:cursor] = 0
68
+ end
69
+ else
70
+ @layers[@layers.keys[layer_idx]][:buffer] = String.new
71
+ @layers[@layers.keys[layer_idx]][:cursor] = 0
72
+ end
73
+ end
74
+
75
+ # Add a new line to the text object. If there are no layers, the line will be added in place. If there are layers, the line will be added below the last layer.
76
+ # @param options [Hash] the options to create the layer with
77
+ def add_line(options = {})
78
+ @lines += 1
79
+ unless @layers.empty?
80
+ options.merge!(y: OR2D.game.entities[@layers.keys.last].y + (OR2D.game.entities[@layers.keys.last].resource.size + OR2D.scale))
81
+ end
82
+ add_layer(options)
83
+ end
84
+
85
+ # Set the text for a specific layer.
86
+ # @param text [String] the text to set
87
+ # @param layer_idx [Integer, Symbol] the index of the layer to set the text for
88
+ def set_text(text, layer_idx)
89
+ @layers[@layers.keys[layer_idx]][:buffer] = text.slice(0, @limit)
90
+ @layers[@layers.keys[layer_idx]][:cursor] = 0
91
+ end
92
+
93
+ # Append text to a specific layer.
94
+ # @param text [String] the text to append
95
+ # @param layer_idx [Integer, Symbol] the index of the layer to append the text to
96
+ def append_text(text, layer_idx)
97
+ return if @layers[@layers.keys[layer_idx]][:buffer].length >= @limit
98
+
99
+ @layers[@layers.keys[layer_idx]][:buffer] += text
100
+ @layers[@layers.keys[layer_idx]][:buffer] = @layers[@layers.keys[layer_idx]][:buffer].slice(0, @limit)
101
+ end
102
+
103
+ # Is the text object empty?
104
+ # @return [Boolean] whether the text object is empty
105
+ def empty?
106
+ @layers.empty?
107
+ end
108
+
109
+ # Update the text object. This works by updating the text for each layer one character at a time only on key frames determined by the update interval.
110
+ def update(force: false)
111
+ return unless force || OR2D.game.key_frame?(@update_interval)
112
+
113
+ @layers.each do |id, properties|
114
+ OR2D.game.entities[id].resource.text = properties[:buffer].slice(0, properties[:cursor])
115
+ properties[:cursor] += 1 if properties[:cursor] < properties[:buffer].length
116
+ end
117
+ end
118
+
119
+ # Show the text object. This works by showing each layer one at a time.
120
+ def show
121
+ @lines.times do |iteration|
122
+ if iteration == 1
123
+ OR2D.game.entities[@layers.keys[0]].show if @layers[@layers.keys[0]][:show]
124
+ elsif @layers[@layers.keys[iteration - 1]][:show]
125
+ OR2D.game.entities[@layers.keys[iteration - 1]].show
126
+ end
127
+ end
128
+ end
129
+
130
+ # Remove a layer from the text object. This works by removing the layer and adjusting the y coordinates of the remaining layers.
131
+ def remove_layer(id, adjust: true)
132
+ if adjust && @lines > 1
133
+ @lines.times do |index|
134
+ OR2D.game.entities[@layers.keys[index - 1]].y -= OR2D.game.entities[id].resource.size + OR2D.scale
135
+ end
136
+ end
137
+ @lines -= 1
138
+ super(id)
139
+ end
140
+
141
+ # Hide the text object. This works by hiding each layer one at a time.
142
+ def hide
143
+ @lines.times do |index|
144
+ OR2D.game.entities[@layers.keys[index]].hide
145
+ end
146
+ end
147
+
148
+ # Destroy the text object. This works by destroying each layer one at a time.
149
+ # @note This will also destroy the text object.
150
+ def destroy
151
+ @lines.times do |index|
152
+ OR2D.game.entities[@layers.keys[index]].destroy
153
+ end
154
+ super
155
+ end
156
+
157
+ private
158
+
159
+ def add_layer(options = {})
160
+ buffer = options[:text] || String.new
161
+ id = super(:text, options.merge(text: ''))
162
+ @layers[id][:buffer] = buffer
163
+ @layers[id][:cursor] = 0
164
+ show
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,199 @@
1
+ module OR2D
2
+ # The Console class is used to construct Console objects that allow execution of Ruby code at runtime.
3
+ class Console
4
+
5
+ # @!attribute [r] display
6
+ # @return [OR2D::Composites::Text] the display of the Console object
7
+ attr_reader :display
8
+
9
+ # @!attribute [r] boundary
10
+ # @return [Ruby2D::Rectangle] the boundary of the Console object
11
+ attr_reader :boundary
12
+
13
+ # Constructs a new Console object.
14
+ # @param options [Hash] the options to create the console with
15
+ def initialize(options = {})
16
+ @boundary = Ruby2D::Rectangle.new(x: 0, y: -(OR2D.game.window.get(:height) / 2), z: 0,
17
+ width: OR2D.game.window.get(:width),
18
+ height: (OR2D.game.window.get(:height) / 2),
19
+ color: 'green', opacity: 0.25)
20
+ OR2D.game.window.add(@boundary)
21
+ @properties = { input_size: (8 * OR2D.scale), output_size: (4 * OR2D.scale), max_length: options[:max_length] || 24 }
22
+ @properties[:max_lines] = (@boundary.height / (@properties[:output_size] * OR2D.scale)).to_i - @properties[:output_size]
23
+
24
+
25
+ @prompt = options[:prompt] || '>> '
26
+ @buffer = String.new
27
+ @display = OR2D::Composites::Text.new
28
+ @display.add_line(text: 'OR2D Console', color: 'yellow', size: @properties[:output_size],
29
+ x: @boundary.x + 16, y: @boundary.y + (16 * OR2D.scale), z: @boundary.z + 1)
30
+ @input = OR2D::Entity.new(:text, { text: @prompt, color: 'white',
31
+ x: @boundary.x + 16, y: (@boundary.y + @boundary.height) - (16 * OR2D.scale),
32
+ z: @boundary.z + 1, size: @properties[:input_size],
33
+ show: true })
34
+ @state = State.new(:RETRACTED, false, false)
35
+
36
+ setup_events
37
+ end
38
+
39
+ # Add a line of text to the console.
40
+ def add_line(options)
41
+ @display.add_line(options.merge(size: @properties[:output_size]))
42
+ end
43
+
44
+ # Remove the console text displays from the game instance window.
45
+ def remove
46
+ @input.destroy
47
+ @display.destroy
48
+ OR2D.game.window.remove(@boundary)
49
+ @descriptors.each_value { |descriptor| OR2D.game.window.off(descriptor) }
50
+ end
51
+
52
+ # Update the console.
53
+ def update
54
+ case @state.animation
55
+ when :RETRACTED
56
+ if @boundary.y >= -@boundary.height
57
+ @boundary.y -= 16
58
+ @input.y -= 16
59
+ @display.y -= 16 unless @display.empty?
60
+ else
61
+ @state.animation = :DRAWN
62
+ @state.drawn = false
63
+ end
64
+ when :PULL_DOWN
65
+ if @boundary.y <= -16 * OR2D.scale
66
+ @boundary.y += 16
67
+ @input.y += 16
68
+ @display.y += 16 unless @display.empty?
69
+ else
70
+ @state.animation = :DRAWN
71
+ @state.drawn = true
72
+ end
73
+ end
74
+
75
+ @display.update
76
+ @display.remove_layer(@display.layers.keys.first) if @display.layers.length > @properties[:max_lines]
77
+ @input.resource.text = @prompt + @buffer if @state.drawn
78
+ OR2D.game.window.add(@boundary)
79
+ end
80
+
81
+ # Retracts the console from view.
82
+ def retract
83
+ @state.animation = :RETRACTED
84
+ end
85
+
86
+ # Pulls the console into view.
87
+ def pull_down
88
+ @state.animation = :PULL_DOWN
89
+ end
90
+
91
+ private
92
+
93
+ # Contains the state of the console.
94
+ State = Struct.new(:animation, :drawn, :enabled) do
95
+
96
+ # Enables console input
97
+ def enable
98
+ self.enabled = true
99
+ end
100
+
101
+ # Disables console input
102
+ def disable
103
+ self.enabled = false
104
+ end
105
+
106
+ # Toggle console input
107
+ def toggle
108
+ self.enabled = !self.enabled
109
+ end
110
+ end
111
+
112
+ def setup_events
113
+ @descriptors = {}
114
+
115
+ @descriptors[:std_input] = OR2D.game.window.on(:key_up) do |event|
116
+ case event.key
117
+ when '`'
118
+ @state.toggle
119
+ @state.enabled ? pull_down : retract
120
+ end
121
+
122
+ if @state.drawn &&
123
+ ((!event.key.match?(/escape/) &&
124
+ !event.key.match?(/enter/) &&
125
+ !event.key.match?(/return/) &&
126
+ !event.key.match?(/backspace/) &&
127
+ !event.key.match?(/space/) &&
128
+ !event.key.match?(/shift/) &&
129
+ !event.key.match?(/control/) &&
130
+ !event.key.match?(/alt/) &&
131
+ !event.key.match?(/tab/) &&
132
+ !event.key.match?(/capslock/) &&
133
+ !event.key.match?(/pageup/) &&
134
+ !event.key.match?(/pagedown/) &&
135
+ !event.key.match?(/end/) &&
136
+ !event.key.match?(/home/) &&
137
+ !event.key.match?(/left/) &&
138
+ !event.key.match?(/up/) &&
139
+ !event.key.match?(/right/) &&
140
+ !event.key.match?(/down/) &&
141
+ !event.key.match?(/insert/) &&
142
+ !event.key.match?(/delete/) &&
143
+ !event.key.match?(/f1|f2|f3|f4|f5|f6|f7|f8|f9|f10/)) &&
144
+ event.key =~ /[a-zA-Z0-9]/ &&
145
+ (@properties[:max_length].zero? || @buffer.length < @properties[:max_length]))
146
+ @buffer.concat(OR2D.game.modifiers[:shift] ? event.key.capitalize : event.key)
147
+ end
148
+ end
149
+
150
+ @descriptors[:special_input] = OR2D.game.window.on(:key_up) do |event|
151
+ case event.key
152
+ when /enter|return/
153
+ begin
154
+ output = instance_eval(@buffer)
155
+ rescue StandardError => e
156
+ output = e.message
157
+ puts e.backtrace
158
+ end
159
+
160
+ @display.add_line(text: "#{@buffer} #=> #{output}",
161
+ size: @properties[:output_size],
162
+ color: 'white',
163
+ show: true)
164
+ @buffer.clear
165
+ when /backspace/ then @buffer.slice!(-1)
166
+ when /delete/ then @buffer.clear
167
+ when /space/ then @buffer << ' '
168
+ when /-|minus|hyphen/ then @buffer << (OR2D.game.modifiers[:shift] ? '_' : '-')
169
+ when '\\' then @buffer << (OR2D.game.modifiers[:shift] ? '|' : '\\')
170
+ when '.' then @buffer << (OR2D.game.modifiers[:shift] ? '>' : '.')
171
+ when ',' then @buffer << (OR2D.game.modifiers[:shift] ? '<' : ',')
172
+ when ';' then @buffer << (OR2D.game.modifiers[:shift] ? ':' : ';')
173
+ when '{' then @buffer << (OR2D.game.modifiers[:shift] ? '[' : '{')
174
+ when '}' then @buffer << (OR2D.game.modifiers[:shift] ? ']' : '}')
175
+ when '[' then @buffer << (OR2D.game.modifiers[:shift] ? '{' : '[')
176
+ when ']' then @buffer << (OR2D.game.modifiers[:shift] ? '}' : ']')
177
+ when /=|equals/ then @buffer << (OR2D.game.modifiers[:shift] ? '+' : '=')
178
+ when "'" then @buffer << (OR2D.game.modifiers[:shift] ? '"' : "'")
179
+ end
180
+ end
181
+
182
+ # Numbers
183
+ @descriptors[:numeric_input] = OR2D.game.window.on(:key_up) do |event|
184
+ case event.key
185
+ when '1' then @buffer << (OR2D.game.modifiers[:shift] ? '!' : '1')
186
+ when '2' then @buffer << (OR2D.game.modifiers[:shift] ? '@' : '2')
187
+ when '3' then @buffer << (OR2D.game.modifiers[:shift] ? '#' : '3')
188
+ when '4' then @buffer << (OR2D.game.modifiers[:shift] ? '$' : '4')
189
+ when '5' then @buffer << (OR2D.game.modifiers[:shift] ? '%' : '5')
190
+ when '6' then @buffer << (OR2D.game.modifiers[:shift] ? '^' : '6')
191
+ when '7' then @buffer << (OR2D.game.modifiers[:shift] ? '&' : '7')
192
+ when '8' then @buffer << (OR2D.game.modifiers[:shift] ? '*' : '8')
193
+ when '9' then @buffer << (OR2D.game.modifiers[:shift] ? '(' : '9')
194
+ when '0' then @buffer << (OR2D.game.modifiers[:shift] ? ')' : '0')
195
+ end
196
+ end
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,78 @@
1
+ module OR2D
2
+
3
+ # A Entity object represents a single entity in an OR2D instance. All entities have an ID, and a natural boundary
4
+ # that is provided by it's parent class (i.e. Ruby2D::Rectangle). It may also have a resource that can be rendered to
5
+ # the screen. It is recommended to use inheritance to create new entities.
6
+ class Entity < Ruby2D::Rectangle
7
+ include OR2D::Animations::EntityAnimations
8
+
9
+ # @!attribute [r] id
10
+ # @return [String] the entity's ID
11
+ attr_reader :id
12
+
13
+ # @!attribute [r] resource
14
+ # @return [Ruby2D::Image, Ruby2D::Sprite, Ruby2D::Text, Ruby2D::Triangle, Ruby2D::Quad, Ruby2D::Circle, Ruby2D::Square, Ruby2D::Line, Ruby2D::Rectangle] the entity's resource
15
+ attr_reader :resource
16
+
17
+ # Constructs a new Entity object.
18
+ # @param type [Symbol] the type of entity to create
19
+ # @param options [Hash] the options to create the entity with
20
+ def initialize(type, options = {})
21
+ super(x: options[:x] || 0,
22
+ y: options[:y] || 0,
23
+ width: options[:width].nil? ? 1 : options[:width] * OR2D.scale,
24
+ height: options[:height].nil? ? 1 : options[:height] * OR2D.scale,
25
+ opacity: options[:show_boundary] ? 0.55 : 0.0,
26
+ color: 'green')
27
+ @id = options[:id] || SecureRandom.uuid
28
+ @resource = options[:resource] || OR2D::Resource.create(type, options)
29
+ @width = @resource.width if @resource.respond_to?(:width)
30
+ @height = @resource.height if @resource.respond_to?(:height)
31
+ show if options[:show]
32
+ ensure
33
+ OR2D.game.add_entity(self)
34
+ end
35
+
36
+ # Set the Entity x coordinate.
37
+ # @param x_coordinate [Integer] the x coordinate of the Entity on the screen
38
+ def x=(x_coordinate)
39
+ super(x_coordinate)
40
+ @resource.x = x_coordinate if @resource.respond_to?(:x=)
41
+ end
42
+
43
+ # Set the Entity y coordinate.
44
+ # @param y_coordinate [Integer] the y coordinate of the Entity on the screen
45
+ def y=(y_coordinate)
46
+ super(y_coordinate)
47
+ @resource.y = y_coordinate if @resource.respond_to?(:y=)
48
+ end
49
+
50
+ # Show the entity's boundary.
51
+ def toggle_boundary
52
+ @color.opacity = if @color.opacity <= 0.0
53
+ 0.35
54
+ else
55
+ 0.0
56
+ end
57
+ end
58
+
59
+ # Show the entity on the game instance window.
60
+ def show
61
+ OR2D.game.window.add(self)
62
+ OR2D.game.window.add(@resource) if @resource
63
+ end
64
+
65
+ # Hide the entity from the game instance window.
66
+ def hide
67
+ OR2D.game.window.remove(self)
68
+ OR2D.game.window.remove(@resource) if @resource
69
+ end
70
+
71
+ # Remove the entity from the game instance window, and from the game instance's entity list.
72
+ def destroy
73
+ OR2D.game.window.remove(self)
74
+ OR2D.game.window.remove(@resource) if @resource
75
+ OR2D.game.remove_entity(@id)
76
+ end
77
+ end
78
+ end