adventure_rl 0.0.1.pre.ld42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +12 -0
  5. data/Gemfile.lock +47 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +31 -0
  8. data/Rakefile +11 -0
  9. data/adventure_rl.gemspec +48 -0
  10. data/bin/console +7 -0
  11. data/bin/mkaudio +196 -0
  12. data/bin/mkclip +223 -0
  13. data/bin/rdoc +9 -0
  14. data/bin/setup +8 -0
  15. data/bin/vimall +5 -0
  16. data/doc/Mask.md +183 -0
  17. data/doc/Point.md +95 -0
  18. data/doc/Window.md +139 -0
  19. data/lib/AdventureRL/Animation.rb +63 -0
  20. data/lib/AdventureRL/Audio.rb +75 -0
  21. data/lib/AdventureRL/AudioPlayer.rb +65 -0
  22. data/lib/AdventureRL/Button.rb +51 -0
  23. data/lib/AdventureRL/Clip.rb +91 -0
  24. data/lib/AdventureRL/ClipPlayer.rb +187 -0
  25. data/lib/AdventureRL/Deltatime.rb +51 -0
  26. data/lib/AdventureRL/EventHandlers/Buttons.rb +225 -0
  27. data/lib/AdventureRL/EventHandlers/EventHandler.rb +62 -0
  28. data/lib/AdventureRL/EventHandlers/MouseButtons.rb +142 -0
  29. data/lib/AdventureRL/Events/Event.rb +69 -0
  30. data/lib/AdventureRL/Events/Mouse.rb +60 -0
  31. data/lib/AdventureRL/FileGroup.rb +100 -0
  32. data/lib/AdventureRL/FileGroupPlayer.rb +226 -0
  33. data/lib/AdventureRL/Helpers/Error.rb +68 -0
  34. data/lib/AdventureRL/Helpers/MethodHelper.rb +20 -0
  35. data/lib/AdventureRL/Helpers/PipeMethods.rb +26 -0
  36. data/lib/AdventureRL/Image.rb +77 -0
  37. data/lib/AdventureRL/Layer.rb +273 -0
  38. data/lib/AdventureRL/Mask.rb +462 -0
  39. data/lib/AdventureRL/Menu.rb +92 -0
  40. data/lib/AdventureRL/Modifiers/Gravity.rb +60 -0
  41. data/lib/AdventureRL/Modifiers/Inventory.rb +104 -0
  42. data/lib/AdventureRL/Modifiers/Pusher.rb +61 -0
  43. data/lib/AdventureRL/Modifiers/Solid.rb +302 -0
  44. data/lib/AdventureRL/Modifiers/Velocity.rb +163 -0
  45. data/lib/AdventureRL/Point.rb +188 -0
  46. data/lib/AdventureRL/Quadtree.rb +237 -0
  47. data/lib/AdventureRL/Rectangle.rb +62 -0
  48. data/lib/AdventureRL/Settings.rb +80 -0
  49. data/lib/AdventureRL/SolidsManager.rb +170 -0
  50. data/lib/AdventureRL/Textbox.rb +195 -0
  51. data/lib/AdventureRL/TimingHandler.rb +225 -0
  52. data/lib/AdventureRL/Window.rb +152 -0
  53. data/lib/AdventureRL/misc/extensions.rb +80 -0
  54. data/lib/AdventureRL/misc/require_files.rb +45 -0
  55. data/lib/AdventureRL/version.rb +3 -0
  56. data/lib/adventure_rl.rb +22 -0
  57. data/lib/default_settings.yml +20 -0
  58. data/vimrc +4 -0
  59. metadata +237 -0
@@ -0,0 +1,142 @@
1
+ module AdventureRL
2
+ module EventHandlers
3
+ class MouseButtons < Buttons
4
+ # This constant contains the IDs of all mouse buttons.
5
+ MOUSE_BUTTON_IDS = [
6
+ Gosu::MS_LEFT,
7
+ Gosu::MS_MIDDLE,
8
+ Gosu::MS_RIGHT,
9
+ Gosu::MS_WHEEL_DOWN,
10
+ Gosu::MS_WHEEL_UP
11
+ ] .concat((0 .. 7).map do |n|
12
+ next Gosu.const_get "MS_OTHER_#{n.to_s}"
13
+ end)
14
+
15
+ DEFAULT_SETTINGS = Settings.new(
16
+ only_mouse_buttons: true
17
+ )
18
+
19
+ def initialize settings = {}
20
+ @settings = DEFAULT_SETTINGS.merge settings
21
+ @only_mouse_buttons = @settings.get :only_mouse_buttons
22
+ super @settings
23
+ end
24
+
25
+ def button_down btnid
26
+ super unless (@only_mouse_buttons)
27
+ trigger(
28
+ :mouse_down,
29
+ get_semantic_button_name(btnid),
30
+ shift: shift_button_pressed?,
31
+ control: control_button_pressed?,
32
+ alt: alt_button_pressed?
33
+ ) if (MOUSE_BUTTON_IDS.include?(btnid))
34
+ end
35
+
36
+ def button_up btnid
37
+ return unless (MOUSE_BUTTON_IDS.include? btnid)
38
+ trigger(
39
+ :mouse_up,
40
+ get_semantic_button_name(btnid),
41
+ shift: shift_button_pressed?,
42
+ control: control_button_pressed?,
43
+ alt: alt_button_pressed?
44
+ )
45
+ end
46
+
47
+ def update
48
+ pressed_btnids = MOUSE_BUTTON_IDS.select do |btnid|
49
+ next Gosu.button_down?(btnid)
50
+ end
51
+ return unless (pressed_btnids.any?)
52
+ pressed_btnids.each do |btnid|
53
+ trigger(
54
+ :mouse_press,
55
+ get_semantic_button_name(btnid),
56
+ shift: shift_button_pressed?,
57
+ control: control_button_pressed?,
58
+ alt: alt_button_pressed?
59
+ )
60
+ end
61
+ end
62
+
63
+ def add_pressable_button *args
64
+ Helpers::Error.error(
65
+ "Cannot add pressable button(s) to #{self.class.name}."
66
+ )
67
+ end
68
+
69
+ private
70
+
71
+ def get_events
72
+ return super.concat([
73
+ get_event_mouse_down,
74
+ get_event_mouse_up,
75
+ get_event_mouse_press
76
+ ])
77
+ end
78
+
79
+ def get_event_mouse_down
80
+ event = Events::Mouse.new(:mouse_down)
81
+ event.on_trigger do |object, btn_name, mod_keys|
82
+ next unless (object.methods.include?(:on_mouse_down) && object.collides_with?(get_mouse_point))
83
+ case object.method(:on_mouse_down).arity.abs
84
+ when 0
85
+ object.on_mouse_down
86
+ when 1
87
+ object.on_mouse_down btn_name
88
+ when 2
89
+ object.on_mouse_down btn_name, mod_keys
90
+ end
91
+ end
92
+ return event
93
+ end
94
+
95
+ def get_event_mouse_up
96
+ event = Events::Mouse.new(:mouse_up)
97
+ event.on_trigger do |object, btn_name, mod_keys|
98
+ next unless (object.methods.include?(:on_mouse_up) && object.collides_with?(get_mouse_point))
99
+ case object.method(:on_mouse_up).arity.abs
100
+ when 0
101
+ object.on_mouse_up
102
+ when 1
103
+ object.on_mouse_up btn_name
104
+ when 2
105
+ object.on_mouse_up btn_name, mod_keys
106
+ end
107
+ end
108
+ return event
109
+ end
110
+
111
+ def get_event_mouse_press
112
+ event = Events::Mouse.new(:mouse_press)
113
+ event.on_trigger do |object, btn_name, mod_keys|
114
+ next unless (object.methods.include?(:on_mouse_press) && object.collides_with?(get_mouse_point))
115
+ case object.method(:on_mouse_press).arity.abs
116
+ when 0
117
+ object.on_mouse_press
118
+ when 1
119
+ object.on_mouse_press btn_name
120
+ when 2
121
+ object.on_mouse_press btn_name, mod_keys
122
+ end
123
+ end
124
+ return event
125
+ end
126
+
127
+ def get_mouse_point
128
+ window = Window.get_window
129
+ return nil unless (window)
130
+ return Point.new(window.mouse_x, window.mouse_y)
131
+ end
132
+
133
+ def get_semantic_button_name btnid
134
+ return Gosu.constants.map do |constant_name|
135
+ constant = Gosu.const_get constant_name
136
+ next constant_name.to_s.sub(/^MS_/,'').downcase.to_sym if (constant == btnid && constant_name.match?(/_/))
137
+ next nil
138
+ end .compact.first
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,69 @@
1
+ module AdventureRL
2
+ module Events
3
+ class Event
4
+ def initialize name
5
+ @name = name
6
+ @objects = []
7
+ @trigger_method = nil
8
+ end
9
+
10
+ # Returns the <tt>name</tt> of the Event.
11
+ def get_name
12
+ return @name
13
+ end
14
+
15
+ # Returns the objects that subscribed to this Event. (see #add_object)
16
+ def get_objects
17
+ return @objects
18
+ end
19
+
20
+ # Add one or multiple <tt>object</tt>(s) to this Event.
21
+ def add_object object
22
+ [object].flatten.each do |obj|
23
+ Helpers::Error.error(
24
+ "Object `#{obj.inspect}:#{obj.class.name}' cannot be given",
25
+ "to this Event `#{self.inspect}:#{self.class.name}'."
26
+ ) unless (valid_object? obj)
27
+ @objects << obj unless (@objects.include? obj)
28
+ end
29
+ end
30
+ alias_method :add, :add_object
31
+ alias_method :<<, :add_object
32
+
33
+ # Remove one or multiple <tt>object</tt>(s) from this Event.
34
+ def remove_object object
35
+ [object].flatten.each do |obj|
36
+ @objects.delete obj
37
+ end
38
+ end
39
+
40
+ # Pass a block, which will be called when this Event is triggered (see #trigger).
41
+ # The passed block takes an argument, which is a subscribed object.
42
+ def on_trigger &block
43
+ Helpers::Error.error(
44
+ "Method #on_trigger needs a block to be passed."
45
+ ) unless (block_given?)
46
+ @trigger_method = block
47
+ end
48
+
49
+ # The block defined with #on_trigger will be called
50
+ # for every subscribed object.
51
+ # Optionally, additional <tt>args</tt> arguments can be passed,
52
+ # which will be passed to the trigger method.
53
+ def trigger *args
54
+ get_objects.each do |object|
55
+ @trigger_method.call object, *args
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ # Returns <tt>true</tt> if the passed <tt>object</tt> can be given to this Event,
62
+ # and <tt>false</tt> if not.
63
+ # This method should be overwritten to fit specific requirements.
64
+ def valid_object? object
65
+ return !!object
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,60 @@
1
+ module AdventureRL
2
+ module Events
3
+ class Mouse < Event
4
+ def initialize *args
5
+ super
6
+ @quadtree = Quadtree.new
7
+ end
8
+
9
+ # Overwrite the #add_object method, so we can
10
+ # reset the object in the Quadtree if necessary,
11
+ # via the object's #move_by method.
12
+ def add_object object
13
+ super
14
+ [object].flatten.each do |obj|
15
+ get_quadtree.add_object obj
16
+ mouse_event = self
17
+ obj.define_singleton_method :move_by do |*args|
18
+ previous_position = get_position.dup
19
+ super(*args)
20
+ mouse_event.get_quadtree.reset_object self if (get_position != previous_position)
21
+ end
22
+ end
23
+ end
24
+
25
+ # Overwrite the #remove_object method, so we can
26
+ # also remove the object(s) from the Quadtree.
27
+ def remove_object object
28
+ super
29
+ [object].flatten.each do |obj|
30
+ get_quadtree.remove_object obj
31
+ end
32
+ end
33
+
34
+ # Overwrite the #trigger method, to perform a
35
+ # Quadtree query for objects colliding with the mouse pointer.
36
+ # For improved performance.
37
+ def trigger *args
38
+ get_colliding_objects.each do |object|
39
+ @trigger_method.call object, *args
40
+ end
41
+ end
42
+
43
+ def get_quadtree
44
+ return @quadtree
45
+ end
46
+
47
+ private
48
+
49
+ def get_colliding_objects
50
+ return get_quadtree.get_colliding_objects_for get_mouse_point
51
+ end
52
+
53
+ def get_mouse_point
54
+ window = Window.get_window
55
+ return nil unless (window)
56
+ return Point.new(window.mouse_x, window.mouse_y)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,100 @@
1
+ module AdventureRL
2
+ # This is an abstract class, which is inherited by
3
+ # - Clip
4
+ # - Audio
5
+ class FileGroup
6
+ include Helpers::Error
7
+
8
+ # Initialize with either a path to a YAML settings file as a String,
9
+ # or a Hash containing your settings.
10
+ def initialize settings_arg
11
+ settings = Settings.new settings_arg
12
+ @settings = get_settings_with settings
13
+ @name = @settings.get :name
14
+ @directory = get_directory_from_settings @settings
15
+ validate_directory @directory
16
+ @files = get_file_paths
17
+ end
18
+
19
+ # Returns the settings as <tt>AdventureRL::Settings</tt>,
20
+ # unless <tt>*keys</tt> are given, then it returns the value of
21
+ # <tt>@settings.get(*keys)</tt>.
22
+ def get_settings *keys
23
+ return @settings if (keys.empty?)
24
+ return @settings.get(*keys)
25
+ end
26
+
27
+ # Returns the Clip's name.
28
+ def get_name
29
+ return @name
30
+ end
31
+
32
+ # Returns an Array of the filepaths.
33
+ def get_files
34
+ return @files
35
+ end
36
+
37
+ # Returns the filepath at index <tt>index</tt>.
38
+ def get_file index
39
+ return @files[index]
40
+ end
41
+
42
+ # Returns the set directory of files.
43
+ def get_file_directory
44
+ return @directory
45
+ end
46
+ alias_method :get_directory, :get_file_directory
47
+
48
+ # Returns true if <tt>index</tt> file exists.
49
+ def has_file_index? index
50
+ return index < @files.size && index >= 0
51
+ end
52
+ alias_method :has_index?, :has_file_index?
53
+
54
+ private
55
+
56
+ def get_settings_with custom_settings
57
+ return get_default_settings.merge custom_settings
58
+ end
59
+
60
+ # This method should be overwritten by the child class,
61
+ # and return their specific <tt>INTERNAL_DEFAULT_SETTINGS</tt>.
62
+ def get_default_settings
63
+ return {}
64
+ end
65
+
66
+ def get_directory_from_settings settings = @settings
67
+ directory = settings.get(:directory)
68
+ directory = directory.to_path if (directory.is_a? Pathname)
69
+ error(
70
+ "`:directory' key must be given in settings hash to #new."
71
+ ) unless (directory)
72
+ return Pathname.new File.join(self.class.get_root_directory, directory)
73
+ end
74
+
75
+ def validate_directory directory = get_directory
76
+ error_no_directory directory unless (directory_exists? directory)
77
+ end
78
+
79
+ def get_file_paths
80
+ return sort_files(get_directory.each_child.select do |file|
81
+ next false unless (file.file?)
82
+ next file.basename.to_path.match? get_filename_regex
83
+ end)
84
+ end
85
+
86
+ def sort_files files
87
+ return files.sort do |file_one, file_two|
88
+ number_one = file_one.basename.to_path.match(/\A(\d+)\..+\z/)[1].to_i
89
+ number_two = file_two.basename.to_path.match(/\A(\d+)\..+\z/)[1].to_i
90
+ next number_one <=> number_two
91
+ end
92
+ end
93
+
94
+ # This method should be overwritten by the child class.
95
+ # It should return the regex which must match the filenames.
96
+ def get_filename_regex
97
+ return /\A.+\..+\z/
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,226 @@
1
+ module AdventureRL
2
+ # This is an abstract class, which is inherited by
3
+ # - ClipPlayer
4
+ # - AudioPlayer
5
+ # At its core, it takes a FileGroup in its #play method,
6
+ # and <em>"plays"</em> it.
7
+ class FileGroupPlayer
8
+ include Helpers::Error
9
+
10
+ # Pass settings Hash or Settings as argument.
11
+ # Supersedes the child class' <tt>DEFAULT_SETTINGS</tt>.
12
+ def initialize settings = {}
13
+ @settings = get_default_settings.merge settings
14
+ @playing = false
15
+ @speed = @settings.get(:speed)
16
+ @filegroup_index = 0
17
+ @filegroup = nil
18
+ @current_file = nil
19
+ @current_time = 0.0
20
+ @last_current_time = 0.0
21
+ @target_frame_delay = 1.0 / 24.0 # Default, will be overwritten in #play
22
+ @deltatime = Deltatime.new
23
+ end
24
+
25
+ # Returns the settings as <tt>AdventureRL::Settings</tt>,
26
+ # unless <tt>*keys</tt> are given, then it returns the value of
27
+ # <tt>@settings.get(*keys)</tt>.
28
+ def get_settings *keys
29
+ return @settings if (keys.empty?)
30
+ return @settings.get(*keys)
31
+ end
32
+
33
+ # Returns the currently set FileGroup.
34
+ def get_filegroup
35
+ return @filegroup
36
+ end
37
+
38
+ # Returns the current playback time in seconds.
39
+ def get_current_time
40
+ return @current_time
41
+ end
42
+ alias_method :get_time, :get_current_time
43
+
44
+ # Set a new current playback time in seconds.
45
+ def set_current_time seconds
46
+ error(
47
+ "Passed seconds must be an Integer or Float,",
48
+ "but got #{seconds.inspect}:#{seconds.class.name}"
49
+ ) unless ([Integer, Float].include? seconds.class)
50
+ @current_time = seconds
51
+ end
52
+ alias_method :set_time, :set_current_time
53
+
54
+ # Increase (or decrease) current_time.
55
+ def increase_current_time seconds
56
+ error(
57
+ "Passed seconds must be an Integer or Float,",
58
+ "but got #{seconds.inspect}:#{seconds.class.name}"
59
+ ) unless ([Integer, Float].include? seconds.class)
60
+ @current_time += seconds
61
+ end
62
+ alias_method :increase_time, :increase_current_time
63
+ alias_method :seek, :increase_current_time
64
+
65
+ # Returns the current playback speed multiplier.
66
+ def get_speed
67
+ return @speed
68
+ end
69
+
70
+ # Set playback speed multiplier.
71
+ def set_speed speed
72
+ error(
73
+ "Argument passed to #set_speed must be a Float or Integer, but got",
74
+ "#{speed.inspect}:#{speed.class.name}"
75
+ ) unless ([Float, Integer].include? speed.class)
76
+ @speed = speed
77
+ end
78
+
79
+ # Increment (or decrement) the speed value by <tt>amount</tt>.
80
+ def increase_speed amount
81
+ error(
82
+ "Argument passed to #increment_speed must be a Float or Integer, but got",
83
+ "#{seconds.inspect}:#{amount.class.name}"
84
+ ) unless ([Float, Integer].include? amount.class)
85
+ @speed += amount
86
+ end
87
+
88
+ # Start playing FileGroup <tt>filegroup</tt>.
89
+ def play filegroup
90
+ load_filegroup filegroup
91
+ @playing = true
92
+ reset
93
+ end
94
+
95
+ # Load a FileGroup as active FileGroup.
96
+ def load_filegroup filegroup
97
+ error(
98
+ "Passed argument must be an instance of FileGroup, but got",
99
+ "#{filegroup.inspect}:#{filegroup.class.name}."
100
+ ) unless (filegroup.is_a? FileGroup)
101
+ set_filegroup filegroup
102
+ @target_frame_delay = 1.0 / get_filegroup.get_settings(:fps).to_f
103
+ end
104
+
105
+ # Pause the currently playing FileGroup.
106
+ def pause
107
+ @playing = false
108
+ end
109
+
110
+ # Resumes playing paused FileGroup.
111
+ def resume
112
+ return unless (has_filegroup?)
113
+ @playing = true
114
+ @deltatime.reset
115
+ end
116
+
117
+ # Returns true if there is a currently active FileGroup.
118
+ def has_filegroup?
119
+ return !!get_filegroup
120
+ end
121
+
122
+ # Stop playing and clear active FileGroup.
123
+ # Cannot call #resume after this,
124
+ # before calling #play again.
125
+ def stop
126
+ @filegroup = nil
127
+ @playing = false
128
+ end
129
+
130
+ # Calls #resume if is paused,
131
+ # or calls #pause if is playing.
132
+ def toggle
133
+ if (is_playing?)
134
+ pause
135
+ elsif (has_filegroup?)
136
+ resume
137
+ end
138
+ end
139
+
140
+ # Reset the current playback.
141
+ # Start playing from the start again.
142
+ def reset
143
+ @deltatime.reset
144
+ @current_time = 0.0
145
+ @filegroup_index = 0
146
+ set_file
147
+ end
148
+
149
+ # Returns <tt>true</tt> if is currently _playing_,
150
+ # and <tt>false</tt> if is _paused_ or _stopped_.
151
+ def is_playing?
152
+ return @playing
153
+ end
154
+
155
+ # Check which file from FileGroup is supposed to be played.
156
+ # This should be called every frame.
157
+ def update
158
+ return unless (is_playing?)
159
+ set_filegroup_index
160
+ update_timing
161
+ end
162
+
163
+ private
164
+
165
+ # This method should be overwritten by the child class,
166
+ # and return their specific <tt>DEFAULT_SETTINGS</tt>.
167
+ def get_default_settings
168
+ return {}
169
+ end
170
+
171
+ def set_filegroup filegroup
172
+ @filegroup_index = 0
173
+ @filegroup = filegroup
174
+ set_file
175
+ end
176
+
177
+ def set_file
178
+ filegroup = get_filegroup
179
+ return if (
180
+ !filegroup ||
181
+ !filegroup.has_index?(get_filegroup_index)
182
+ )
183
+ load_file filegroup.get_file(get_filegroup_index).to_s
184
+ end
185
+
186
+ # This method should be overwritten by the child class.
187
+ # It is passed the filepath <tt>file</tt>.
188
+ def load_file file
189
+ end
190
+
191
+ def get_filegroup_index
192
+ return @filegroup_index
193
+ end
194
+ alias_method :get_index, :get_filegroup_index
195
+
196
+ def set_filegroup_index
197
+ previous_index = get_filegroup_index
198
+ index = (get_current_time / @target_frame_delay).floor
199
+ return if (previous_index == index)
200
+ @filegroup_index = index
201
+ filegroup = get_filegroup
202
+ unless (filegroup.has_index? get_filegroup_index)
203
+ if (get_settings(:loop))
204
+ reset
205
+ else
206
+ stop
207
+ end
208
+ return
209
+ end
210
+ set_file
211
+ end
212
+
213
+ def update_timing
214
+ @current_time += @deltatime.dt * @speed
215
+ @deltatime.update
216
+ end
217
+
218
+ def get_current_file
219
+ return @current_file
220
+ end
221
+
222
+ def set_current_file new_file
223
+ @current_file = new_file
224
+ end
225
+ end
226
+ end
@@ -0,0 +1,68 @@
1
+ module AdventureRL
2
+ module Helpers
3
+ module Error
4
+ PADDING = ' '
5
+ STACK_TRACE_SIZE = 20
6
+ STACK_TRACE_PADDING = 1
7
+
8
+ def self.error *messages
9
+ message = messages.join ?\n
10
+ message.gsub! /^/, PADDING
11
+ stack_trace_lines = caller[STACK_TRACE_PADDING ... (STACK_TRACE_SIZE + STACK_TRACE_PADDING)].map do |line|
12
+ next "#{PADDING}#{line}"
13
+ end .reverse
14
+ abort([
15
+ "#{DIR[:entry].to_s} Error:",
16
+ message,
17
+ "#{PADDING}Exiting.",
18
+ "Stack traceback (most recent call last):",
19
+ stack_trace_lines
20
+ ].flatten.join(?\n))
21
+ end
22
+
23
+ def self.error_no_file file
24
+ filepath = file
25
+ filepath = file.to_path if (file.is_a? Pathname)
26
+ error "File does not exist, or is a directory:", " '#{filepath}'"
27
+ end
28
+
29
+ def self.error_no_directory directory
30
+ dirpath = directory
31
+ dirpath = directory.to_path if (directory.is_a? Pathname)
32
+ error "Directory does not exist, or is a file:", " '#{dirpath}'"
33
+ end
34
+
35
+ def self.file_exists? file
36
+ return false unless (file)
37
+ return File.file? file
38
+ end
39
+
40
+ def self.directory_exists? directory
41
+ return false unless (directory)
42
+ return File.directory? directory
43
+ end
44
+
45
+ private
46
+
47
+ def error *messages
48
+ AdventureRL::Helpers::Error.error *messages
49
+ end
50
+
51
+ def error_no_file file
52
+ AdventureRL::Helpers::Error.error_no_file file
53
+ end
54
+
55
+ def error_no_directory directory
56
+ AdventureRL::Helpers::Error.error_no_directory directory
57
+ end
58
+
59
+ def file_exists? file
60
+ return AdventureRL::Helpers::Error.file_exists? file
61
+ end
62
+
63
+ def directory_exists? directory
64
+ return AdventureRL::Helpers::Error.directory_exists? directory
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,20 @@
1
+ module AdventureRL
2
+ module Helpers
3
+ module MethodHelper
4
+ private
5
+
6
+ def method_exists? method_name
7
+ return (
8
+ methods.include?(method_name) ||
9
+ private_methods.include?(method_name)
10
+ )
11
+ end
12
+
13
+ def method_takes_arguments? method_name
14
+ return nil unless (method_exists?(method_name))
15
+ meth = method method_name
16
+ return meth.arity.abs > 0
17
+ end
18
+ end
19
+ end
20
+ end