rubydraw 0.1.9 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -1,24 +1,13 @@
1
- Rubydraw is a high level game/graphics library, like Gosu or Rubygame, and is written in Ruby.
2
- Its only dependency is ruby-sdl-ffi, which it uses to access SDL functions. Also, thanks,
3
- Rubygame, for documenting your code (which, completely by coninsidence, also uses ruby-sdl-ffi),
4
- otherwise I wouldn't have the slightest idea on how to use the base library's undocumented code!
5
- You have been very helpful. :)
1
+ Rubydraw is a high level game/graphics library, like Gosu or Rubygame, and is written in Ruby. Its only dependency is ruby-sdl-ffi, which it uses to access SDL functions. Also, thanks, Rubygame, for documenting your code (which apparently also uses ruby-sdl-ffi), otherwise I wouldn't have the slightest idea on how to use the base library's undocumented code! You have been very helpful. :)
6
2
  –––––
7
- NOTE: I can't get +ruby-sdl-ffi+ (the library Rubydraw uses to access SDL) to work with +Ruby
8
- 1.9.2+, so I don't know if it even does. If it does work, and/or you know how to make it work,
9
- I would appreciate it if you notify me. So basically, I can't test anything with +1.9.2+. Sorry
10
- for the inconvenience!
3
+ NOTE: I can't get +ruby-sdl-ffi+ (the library Rubydraw uses to access SDL) to work with +Ruby 1.9.2+, so I don't know if it even does. If it does work, and/or you know how to make it work, I would appreciate it if you notify me. So basically, I can't test anything with +1.9.2+. Sorry for the inconvenience!
11
4
 
12
5
  HOW TO INSTALL
13
- To install this library without RubyGems, navigate to this directory in the command
14
- line tool and give "rubydraw/build_and_install" permissions to run. Then simply run it. Hooray, it
15
- should be working now! Test it in irb with "require 'rubydraw'".
6
+ First of all, Rubydraw of course requires you to install SDL. This is mostly a breeze, and a good guide for all platforms can be found here: https://github.com/rubygame/rubygame/wiki/Install (but you don't need to install Rubygame). Then, to install this library without using RubyGems, navigate to this directory in the command line tool and give "rubydraw/build_and_install" permissions to run. Then simply run it. Hooray, it should be working now! Test it by requiring 'rubydraw' in the irb.
16
7
 
17
8
  HOW TO USE
18
- There isn't a proper guide yet, so just read the comments in the other files. Or you can fire up the
19
- gem server and read the RDoc.
9
+ There isn't a proper guide yet, so just read the comments in the other files. Or you can fire up the gem server and read the RDoc.
20
10
 
21
- Thanks for checking this little project. I hope it doesn't give you headaches.
22
- Have fun!
11
+ Thanks for checking this little project. I hope it doesn't give you headaches. Have fun!
23
12
 
24
13
  NEW: Now you can install it from the RubyGems website! Hooray! :D
data/examples/image_ex.rb CHANGED
@@ -12,6 +12,12 @@ class MyWindow < Rubydraw::Window
12
12
  whenever Rubydraw::Events::MouseMove do |event|
13
13
  @mouse_position = event.position
14
14
  end
15
+ whenever Rubydraw::Events::FocusGain do
16
+ @focused = true
17
+ end
18
+ whenever Rubydraw::Events::FocusLoss do
19
+ @focused = false
20
+ end
15
21
  end
16
22
 
17
23
  def mouse_moved(event)
@@ -20,7 +26,7 @@ class MyWindow < Rubydraw::Window
20
26
  end
21
27
 
22
28
  def tick
23
- @image.draw(self, @mouse_position) #if @focused
29
+ @image.draw(self, @mouse_position) if @focused
24
30
  end
25
31
  end
26
32
 
@@ -5,10 +5,7 @@ class MyWindow < Rubydraw::Window
5
5
  def initialize(width, height)
6
6
  super(width, height)
7
7
  puts "New window created with width: #{@width} and height #{@height}"
8
- end
9
- def handle_event(event)
10
- case event
11
- when Rubydraw::Event::Quit
8
+ whenever Rubydraw::Events::QuitRequest do
12
9
  close
13
10
  end
14
11
  end
@@ -19,7 +16,4 @@ w = gets.to_i
19
16
  print "Window width: "
20
17
  h = gets.to_i
21
18
 
22
- window = MyWindow.new(w, h).show
23
-
24
- # Wait for a while to let the user enjoy the window
25
- sleep 10
19
+ window = MyWindow.new(w, h).show
@@ -0,0 +1,4 @@
1
+ # Everything in this file defines constants that "point" to some Rubydraw class.
2
+ # This is why you can write "Point[x, y]" instead of "Rubydraw::Point[x, y]"
3
+ Point = Rubydraw::Point
4
+ Rectangle = Rubydraw::Rectangle
data/lib/ext/object.rb ADDED
@@ -0,0 +1,34 @@
1
+ class Object
2
+ # Execute the given block on the appearance of an instance of +event+ and pass that
3
+ # instance to the block.
4
+ #
5
+ # Example:
6
+ # class MyWindow < Rubydraw::Window
7
+ # def initialize
8
+ # super(300, 300)
9
+ # whenever(Rubydraw::Events::QuitRequest) do
10
+ # puts "Goodbye!"
11
+ # close
12
+ # end
13
+ # whenever(Rubydraw::Events::MouseMove) do |event|
14
+ # new_pos = event.position
15
+ # puts "Mouse moved to #{new_pos.x}, #{new_pos.y}.}"
16
+ # end
17
+ # end
18
+ # end
19
+ def whenever(event, window=self, &block)
20
+ # A very simple rule: +window+ must be a window. Therefore, since +window+ is self
21
+ # by default, instances of Rubydraw::Window calling this method don't have to set
22
+ # that parameter.
23
+ unless window.is_a?(Rubydraw::Window)
24
+ raise ArgumentError, "window must be a Rubydraw::Window"
25
+ end
26
+ event_block = window.registered_actions[event]
27
+ # If nobody has registered a block for this event, prepare the way.
28
+ if event_block.nil?
29
+ window.registered_actions[event] = []
30
+ end
31
+ # Now add the block.
32
+ window.registered_actions[event] << block
33
+ end
34
+ end
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -4,12 +4,47 @@ module Rubydraw
4
4
  # when a Rubydraw::Window is initialized. Every tick, the window asks its
5
5
  # event queue (created in Rubydraw::Window#initialize) for the new events
6
6
  class EventQueue
7
+ def initialize
8
+ @keys_being_repeated = []
9
+ end
10
+ def key_repeat
11
+ Rubydraw.key_repeat
12
+ end
7
13
  # Get all the new events
8
14
  def get_events
15
+ events = []
16
+ until ((event = SDL.PollEvent) == nil)
17
+ new_event = Events.match(event)
18
+ if new_event.is_a?(Events::KeyReleased)
19
+ @keys_being_repeated.delete(new_event.key)
20
+ end
21
+ if new_event.is_a?(Events::KeyPressed) and not @keys_being_repeated.include?(new_event.key)
22
+ @keys_being_repeated << new_event.key
23
+ end
24
+ events << new_event
25
+ end
26
+ @keys_being_repeated.each {|num| events << Events::KeyPressed.new(num)}
27
+ events
28
+ end
29
+
30
+ def exp_get_events
9
31
  events = []
10
32
  until((event = SDL::PollEvent()).nil?)
11
- events << Events.match(event)
33
+ new_event = Events.match(event)
34
+ events << new_event
35
+ key = new_event.key if new_event.is_a?(Events::KeyboardEvent)
36
+ if new_event.is_a?(Events::KeyReleased) and @keys_being_repeated.include?(key)
37
+ @keys_being_repeated.delete(key)
38
+ end
39
+ # Synthesize each key that is being held.
40
+ @keys_being_repeated.each {|num| events << Events::KeyPressed.new(num)}
41
+ # Start adding keys that are held, and remove keys that are no longer
42
+ # being held (whenever a Events::KeyReleased is created).
43
+ if new_event.is_a?(Events::KeyPressed)
44
+ @keys_being_repeated << key
45
+ end
12
46
  end
47
+ puts @keys_being_repeated.size
13
48
  events
14
49
  end
15
50
  end
@@ -19,16 +19,17 @@ module Rubydraw
19
19
  end
20
20
  end
21
21
 
22
- # Blit (copy) into the window at +position+ (see point.rb).
22
+ # Blit (copy) into the window at +position+ (see Rubydraw::Point).
23
23
  # No graphical effects are applied.
24
24
  #
25
25
  # Notice that you don't blit surfaces to other surfaces when using
26
26
  # Rubygame, but instead you draw things.
27
27
  def draw(window, position)
28
- #source_rect = Rectangle[Point[0, 0], width, height]
29
- #blit_rect = Rectangle[position, window.width, window.height]
30
- source_rect = Rectangle[width, height, Point[0, 0]]
31
- blit_rect = Rectangle[window.width, window.height, position]
28
+ unless position.respond_to?(:x) and position.respond_to?(:y)
29
+ raise ArgumentError, "Expected a Point, got #{position}"
30
+ end
31
+ source_rect = Rectangle[Point[0, 0], Point[width, height]]
32
+ blit_rect = Rectangle[position, Point[window.width, window.height]]
32
33
  SDL::BlitSurface(@sdl_image, source_rect.to_sdl, window.sdl_surface, blit_rect.to_sdl)
33
34
  self
34
35
  end
data/lib/rubydraw/keys.rb CHANGED
@@ -17,7 +17,7 @@ module Rubydraw
17
17
  # @x -= 1
18
18
  # end
19
19
  # end
20
- module Keys
20
+ module Key
21
21
  UpArrow = SDL::K_UP
22
22
  DownArrow = SDL::K_DOWN
23
23
  RightArrow = SDL::K_RIGHT
@@ -13,24 +13,48 @@ module Rubydraw
13
13
 
14
14
  # Create a new point with the given +x+ and +y+ positions.
15
15
  def initialize(x, y)
16
- unless x.is_a?(Numeric) and y.is_a?(Numeric)
17
- raise RuntimeError "New Point x and y must be a number."
16
+ unless x.respond_to?(:+)
17
+ "Expected an integer for x, got #{x}"
18
+ end
19
+ unless y.respond_to?(:+)
20
+ "Expected an integer for y, got #{y}"
18
21
  end
19
22
  @x, @y = x, y
20
23
  end
21
24
 
22
25
  # Returns if this self falls within the given rectangle.
23
- def inside?(min, max)
26
+ def inside?(rect)
27
+ min = rect.top_left
28
+ max = rect.bottom_right
24
29
  (x.between?(min.x, max.x)) and (y.between?(min.y, max.y))
25
30
  end
26
31
 
27
- # Add this point's x and y positions to other's x and y positions.
32
+ # Add this point's x and y positions to +other+'s x and y positions.
28
33
  #
29
34
  # Example:
30
- # # This produces #<Rubydraw::Point:0x1010f1958 @y=10, @x=60>
31
- # Rubydraw::Point[10, 20] + Rubydraw::Point[50, -10]
35
+ # Point[10, 20] + Point[50, -10]
36
+ # => #<Rubydraw::Point:0x1010f1958 @y=10, @x=60>
32
37
  def +(other)
33
38
  Point[self.x + other.x, self.y + other.y]
34
39
  end
40
+
41
+ # Subtract +other+'s x and y positions from this point's x and y.
42
+ def -(other)
43
+ Point[self.x - other.x, self.y - other.y]
44
+ end
45
+
46
+ # Two points are equal if both their x and y positions are the same.
47
+ def ==(other)
48
+ result = if other.is_a?(Point)
49
+ @x == other.x and @y == other.y
50
+ else
51
+ false
52
+ end
53
+ end
54
+
55
+ # Returns a human readable string containing info about this point.
56
+ def to_s
57
+ "#{@x}, #{y}"
58
+ end
35
59
  end
36
60
  end
@@ -3,16 +3,24 @@ module Rubydraw
3
3
  # falls inside it. One good use for this class would be a button (will be implemented
4
4
  # in a future version, probably soon)
5
5
  class Rectangle
6
- attr_reader(:position, :width, :height)
6
+ attr_reader(:dimensions, :position)
7
7
 
8
8
  # Shorthand new method
9
- def self.[](width, height, position)
10
- self.new(width, height, position)
9
+ def self.[](position, dimensions)
10
+ self.new(position, dimensions)
11
11
  end
12
12
 
13
13
  # Create a new rectangle with the given dimensions and position.
14
- def initialize(width, height, position)
15
- @width, @height, @position = width, height, position
14
+ def initialize(position, dimensions)
15
+ #raise ArgumentError, "Rectangle dimensions must be a Point" unless dimensions.is_a?(Rubydraw::Point)
16
+ #raise ArgumentError, "Rectangle position must be a Point" unless position.is_a?(Rubydraw::Point)
17
+ unless position.respond_to?(:x) and position.respond_to?(:y)
18
+ raise ArgumentError, "Expected a Point, got #{position}"
19
+ end
20
+ unless dimensions.respond_to?(:x) and dimensions.respond_to?(:y)
21
+ raise ArgumentError, "Expected a Point, got #{position}"
22
+ end
23
+ @position, @dimensions = position, dimensions
16
24
  end
17
25
 
18
26
  # Returns the x position for the rectangle
@@ -28,19 +36,50 @@ module Rubydraw
28
36
  # Returns the positon of the top left corner
29
37
  alias top_left position
30
38
 
39
+ # Returns a point at the bottom left corner
40
+ def bottom_left
41
+ Point[x, y + height]
42
+ end
43
+
44
+ # Returns the point at the top right corner
45
+ def top_right
46
+ Point[x + width, y]
47
+ end
48
+
31
49
  # Returns the position at the bottom right
32
50
  def bottom_right
33
- Point[x + @width, y + @height]
51
+ @position + @dimensions
34
52
  end
35
53
 
36
54
  # Returns if the given point is inside this rectangle. See Rubydraw::Point#inside?
37
55
  def contains?(point)
38
- point.inside?(top_left, bottom_right)
56
+ point.inside?(self)
39
57
  end
40
58
 
41
59
  # Returns an SDL::Rectangle equal to this one.
42
60
  def to_sdl
43
61
  SDL::Rect.new([x, y, width, height])
44
62
  end
63
+
64
+ # Returns this rectangle's width.
65
+ def width
66
+ @dimensions.x
67
+ end
68
+
69
+ # Returns this rectangle's height.
70
+ def height
71
+ @dimensions.y
72
+ end
73
+
74
+ # Returns all four corners in this Rectangle.
75
+ def points
76
+ [top_left, top_right, bottom_left, bottom_right]
77
+ end
78
+
79
+ # Returns a human-readable string, specifying this rectangle.
80
+ def to_s
81
+ d = @dimensions
82
+ ":Rectangle: (position: #{@position.to_s}) (dimensions: #{d.x}x#{d.y}):"
83
+ end
45
84
  end
46
85
  end
data/lib/rubydraw/text.rb CHANGED
@@ -3,11 +3,21 @@ module Rubydraw
3
3
  # with the text to display. They can be drawn at a position on the
4
4
  # screen.
5
5
  class Text
6
- attr_accessor(:font, :contents, :size, :color)
6
+ attr_accessor(:contents, :font, :color, :size)
7
7
  # Create a new drawable Text object with the given font and contents.
8
- def initialize(font, contents, color = Rubydraw::Color::White, size = 25)
9
- @font, @contents, @size, @color = font, contents, size, color
10
- @drawable = SDL::TTF.OpenFont(font, size)
8
+ def initialize(contents, color, font_name="Times New Roman", size = 25)
9
+ @font, @contents, @size, @color = font_name, contents, size, color
10
+ if File.exist?(font_name)
11
+ font_path = font_name
12
+ else
13
+ # The font doesn't exist in the program's directory.
14
+ # Check in Rubydraw's font directory (rubydraw-x.x.x/lib/rubydraw/fonts)
15
+ font_path = "#{File.dirname(__FILE__)}/../fonts/#{font_name}.ttf"
16
+ end
17
+ unless File.exists?(font_path)
18
+ raise "Font file '#{font_name}' does not exist; attemped to load from '#{font_path}'"
19
+ end
20
+ @drawable = SDL::TTF.OpenFont(font_path, size)
11
21
  raise(SDLError, "Failed to initialize font: #{SDL.GetError}") if @drawable.pointer.null?
12
22
  end
13
23
 
@@ -15,8 +25,8 @@ module Rubydraw
15
25
  def draw(window, position)
16
26
  sdl_color = @color.to_sdl
17
27
  sdl_surface = SDL::TTF.RenderText_Blended(@drawable, @contents, sdl_color)
18
- source_rect = Rectangle[sdl_surface.w, sdl_surface.h, Point[0, 0]]
19
- blit_rect = Rectangle[window.width, window.height, position]
28
+ source_rect = Rectangle[Point[0, 0], Point[sdl_surface.w, sdl_surface.h]]
29
+ blit_rect = Rectangle[position, Point[window.width, window.height]]
20
30
  SDL::BlitSurface(sdl_surface, source_rect.to_sdl, window.sdl_surface, blit_rect.to_sdl)
21
31
  end
22
32
  end
@@ -72,9 +72,14 @@ module Rubydraw
72
72
  def handle_events
73
73
  events = @event_queue.get_events
74
74
 
75
+ #events.each {|event|
76
+ # block = @registered_actions[event.class]
77
+ # block.call(event) unless block.nil?}
75
78
  events.each {|event|
76
- block = @registered_actions[event.class]
77
- block.call(event) unless block.nil?}
79
+ blocks = @registered_actions[event.class]
80
+ unless blocks.nil?
81
+ blocks.each {|b| b.call(event) unless b.nil?}
82
+ end}
78
83
  end
79
84
 
80
85
  # This causes the main loop to exit. Use Rubydraw::Window#close to close the
@@ -102,25 +107,8 @@ module Rubydraw
102
107
  def tick
103
108
  end
104
109
 
105
- # Execute the given block on the appearance of an instance of +event+ and pass that
106
- # instance to the block.
107
- #
108
- # Example:
109
- # class MyWindow < Rubydraw::Window
110
- # def initialize
111
- # super(300, 300)
112
- # whenever(Rubydraw::Events::QuitRequest) do
113
- # puts "Goodbye!"
114
- # close
115
- # end
116
- # whenever(Rubydraw::Events::MouseMove) do |event|
117
- # new_pos = event.position
118
- # puts "Mouse moved to #{new_pos.x}, #{new_pos.y}.}"
119
- # end
120
- # end
121
- # end
122
- def whenever(event, &block)
123
- @registered_actions[event] = block
110
+ def registered_actions
111
+ @registered_actions
124
112
  end
125
113
  end
126
114
  end
data/lib/rubydraw.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  # The only dependency
2
2
  require 'ruby-sdl-ffi'
3
3
 
4
- # The extention must be loaded first.
4
+ # The extentions must be loaded first, except for +aliases.rb+
5
5
  require 'ext/string'
6
+ require 'ext/object'
6
7
 
7
8
  # Require all the rubydraw files
8
9
  files = %w[
@@ -17,7 +18,11 @@ files = %w[
17
18
  color
18
19
  sdl_error
19
20
  rectangle]
20
- files.each {|f| require("rubydraw/" + f)}
21
+ files.each { |f| require("rubydraw/" + f) }
22
+
23
+ # This must be loaded last, because it sets up constants that "point" to Rubydraw classes, hence
24
+ # the name "aliases".
25
+ require 'ext/aliases'
21
26
 
22
27
  # Rubydraw is a high level game/graphics library, like Gosu or Rubygame, and is written completely
23
28
  # in Ruby. Its only dependency is ruby-sdl-ffi, which it uses to access SDL functions. Also, thanks,
@@ -30,6 +35,9 @@ files.each {|f| require("rubydraw/" + f)}
30
35
  # I would appreciate it if you notify me. So basically, I can't test anything with +1.9.2+. Sorry
31
36
  # for the inconvenience!
32
37
  module Rubydraw
38
+ # Basically just an alias to Rubydraw::Rectangle.
39
+ Rect = Rectangle
40
+
33
41
  # Initialize SDL.
34
42
  def self.initialize_sdl
35
43
  if SDL::Init(SDL::INIT_EVERYTHING) != 0
@@ -40,6 +48,38 @@ module Rubydraw
40
48
  raise SDLError "Failed to initialize SDL TTF: #{SDL.GetError}"
41
49
  end
42
50
  end
51
+
52
+ # Enable/disable key repeating. After this method is called, instances of Rubydraw::Events::KeyPressed
53
+ # wil be continually created, until the key is released.
54
+ #
55
+ # Couldn't get SDL.EnableKeyRepeat to work, so I implemented my own for the time being. This _should_
56
+ # be temporary, but no guarentees...
57
+ def self.set_key_repeat(new)
58
+ unless new.is_a?(TrueClass) or new.is_a?(FalseClass)
59
+ raise ArgumentError, "'new' must be boolean"
60
+ end
61
+ @@key_repeat = new
62
+ end
63
+
64
+ # See Rubydraw.set_key_repeat.
65
+ def self.enable_key_repeat
66
+ set_key_repeat(true)
67
+ end
68
+
69
+ # See Rubydraw.set_key_repeat.
70
+ def self.disable_key_repeat
71
+ set_key_repeat(false)
72
+ end
73
+
74
+ # Return if +key_repeat+ is enabled or not.
75
+ def self.key_repeat
76
+ @@key_repeat
77
+ end
43
78
  end
44
79
 
45
- Rubydraw::initialize_sdl
80
+ Rubydraw.enable_key_repeat
81
+
82
+ Rubydraw.initialize_sdl
83
+
84
+ # Make sure to quit SDL systems when the program terminates.
85
+ at_exit {SDL.Quit}
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubydraw
3
3
  version: !ruby/object:Gem::Version
4
- hash: 9
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 1
9
- - 9
10
- version: 0.1.9
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - J. Wostenberg
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-11-19 00:00:00 -07:00
18
+ date: 2011-11-22 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -36,9 +36,10 @@ dependencies:
36
36
  description: |-
37
37
 
38
38
  Rubydraw is a high level drawing/game library,
39
- like Gosu or Rubygame. Its only dependency is
40
- ruby-sdl-ffi, which it uses to access SDL
41
- functions.
39
+ like Gosu or Rubygame. Its only dependencies are
40
+ ruby-sdl-ffi--which it uses to access SDL
41
+ functions--and SDL itself (See README on how to
42
+ install the latter).
42
43
  email:
43
44
  executables: []
44
45
 
@@ -49,7 +50,6 @@ extra_rdoc_files: []
49
50
  files:
50
51
  - README
51
52
  - lib/rubydraw.rb
52
- - lib/ext/string.rb
53
53
  - lib/rubydraw/window.rb
54
54
  - lib/rubydraw/image.rb
55
55
  - lib/rubydraw/sound.rb
@@ -67,6 +67,18 @@ files:
67
67
  - examples/media/bug.png
68
68
  - examples/media/hooray.ogg
69
69
  - examples/media/noise.ogg
70
+ - lib/ext/string.rb
71
+ - lib/ext/object.rb
72
+ - lib/ext/aliases.rb
73
+ - lib/fonts/Georgia.ttf
74
+ - lib/fonts/Georgia Bold.ttf
75
+ - lib/fonts/Georgia Italic.ttf
76
+ - lib/fonts/Georgia Bold Italic.ttf
77
+ - lib/fonts/Sans Serif.ttf
78
+ - lib/fonts/Times New Roman.ttf
79
+ - lib/fonts/Times New Roman Bold.ttf
80
+ - lib/fonts/Times New Roman Italic.ttf
81
+ - lib/fonts/Times New Roman Bold Italic.ttf
70
82
  has_rdoc: true
71
83
  homepage: https://github.com/awostenberg/rubydraw
72
84
  licenses: []
@@ -101,6 +113,6 @@ rubyforge_project:
101
113
  rubygems_version: 1.5.2
102
114
  signing_key:
103
115
  specification_version: 3
104
- summary: Rubydraw is a high level drawing/graphics library, like Gosu or Rubygame
116
+ summary: Rubydraw is a high level drawing/graphics library, like Gosu or Rubygame.
105
117
  test_files: []
106
118