graphics 1.0.0b6 → 1.0.0
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.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/History.rdoc +88 -0
- data/Manifest.txt +2 -0
- data/Rakefile +7 -8
- data/examples/boid.rb +44 -63
- data/examples/bounce.rb +4 -4
- data/examples/canvas.rb +17 -16
- data/examples/collision.rb +1 -1
- data/examples/demo.rb +1 -1
- data/examples/editor.rb +1 -1
- data/examples/fluid.rb +6 -6
- data/examples/fluid2.rb +22 -9
- data/examples/gol.rb +1 -1
- data/examples/gol2.rb +14 -22
- data/examples/math.rb +1 -1
- data/examples/pi_polygon.rb +8 -3
- data/examples/radar.rb +3 -3
- data/examples/rainbow_fluid.rb +4 -3
- data/examples/tank.rb +7 -3
- data/examples/tank2.rb +3 -3
- data/examples/targeting.rb +3 -3
- data/examples/vants.rb +13 -4
- data/examples/walker.rb +1 -1
- data/examples/walker2.rb +1 -1
- data/examples/zombies.rb +13 -7
- data/ext/sdl/extconf.rb +12 -20
- data/ext/sdl/sdl.c +619 -360
- data/ext/sdl/sge/Makefile +36 -11
- data/ext/sdl/sge/Makefile.conf +15 -9
- data/ext/sdl/sge/sge_bm_text.cpp +7 -6
- data/ext/sdl/sge/sge_collision.cpp +3 -1
- data/ext/sdl/sge/sge_config.h +0 -2
- data/ext/sdl/sge/sge_internal.h +0 -8
- data/ext/sdl/sge/sge_primitives.cpp +0 -11
- data/ext/sdl/sge/sge_primitives.h +0 -3
- data/ext/sdl/sge/sge_rotation.cpp +1 -1
- data/ext/sdl/sge/sge_shape.cpp +18 -9
- data/ext/sdl/sge/sge_surface.cpp +10 -4
- data/ext/sdl/sge/sge_textpp.cpp +17 -13
- data/graphics_setup.sh +43 -13
- data/lib/graphics.rb +1 -1
- data/lib/graphics/body.rb +8 -0
- data/lib/graphics/decorators.rb +15 -3
- data/lib/graphics/extensions.rb +1 -1
- data/lib/graphics/rainbows.rb +17 -25
- data/lib/graphics/simulation.rb +265 -106
- data/lib/graphics/v.rb +8 -1
- data/resources/sounds/attribution.txt +2 -0
- data/resources/sounds/bullet.wav +0 -0
- data/test/test_graphics.rb +232 -107
- metadata +37 -43
- metadata.gz.sig +1 -2
data/graphics_setup.sh
CHANGED
@@ -1,26 +1,56 @@
|
|
1
1
|
#!/bin/sh
|
2
2
|
set -e
|
3
|
+
set -v
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
# if [ $(id -u) != 0 ]; then
|
6
|
+
# echo "Please run this as root or with sudo"
|
7
|
+
# exit 1
|
8
|
+
# fi
|
7
9
|
|
8
|
-
for gem in graphics
|
9
|
-
|
10
|
+
for gem in graphics rsdl; do
|
11
|
+
gem uninstall -ax $gem || true
|
10
12
|
done
|
11
13
|
|
12
|
-
|
14
|
+
case `uname` in
|
15
|
+
Darwin)
|
16
|
+
echo "I'm on OSX. Not using sudo"
|
17
|
+
SUDO=
|
18
|
+
|
19
|
+
brew unlink sdl
|
20
|
+
brew unlink sdl_mixer
|
21
|
+
brew unlink sdl_ttf
|
22
|
+
brew unlink sdl_image
|
23
|
+
|
24
|
+
brew install sdl2
|
25
|
+
brew install sdl2_mixer
|
26
|
+
brew install sdl2_ttf
|
27
|
+
brew install sdl2_image --without-webp
|
28
|
+
brew install sdl2_gfx
|
29
|
+
;;
|
30
|
+
Linux)
|
31
|
+
echo "I'm on linux, using sudo where needed"
|
32
|
+
SUDO=sudo
|
33
|
+
|
34
|
+
$SUDO apt-get install --no-install-recommends --no-install-suggests libsdl1.2-dev libsdl-image1.2-dev libsdl-mixer1.2-dev libsdl-ttf2.0-dev
|
35
|
+
$SUDO apt-get install --no-install-recommends --no-install-suggests gcc g++
|
36
|
+
;;
|
37
|
+
*)
|
38
|
+
echo "Unknown OS $OSTYPE, aborting"
|
39
|
+
exit 1
|
40
|
+
;;
|
41
|
+
esac
|
42
|
+
|
43
|
+
$SUDO gem update --system -N -V
|
13
44
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
brew install sdl_image --universal --without-webp
|
45
|
+
gem install hoe --conservative
|
46
|
+
$SUDO rake newb
|
47
|
+
rake test
|
18
48
|
|
19
49
|
if [ -f $0 ]; then
|
20
50
|
rake clean package
|
21
|
-
gem install pkg/graphics*.gem
|
51
|
+
$SUDO gem install pkg/graphics*.gem
|
22
52
|
else
|
23
|
-
gem install graphics --pre
|
53
|
+
$SUDO gem install graphics --pre
|
24
54
|
fi
|
25
55
|
|
26
|
-
rsdl -rgraphics -e 'Class.new(Graphics::Simulation) { def draw n; clear :white; text "hit escape to quit", 100, 100, :black; end; }.new(500, 250, 0, "Working!").run'
|
56
|
+
rsdl -Ilib -rgraphics -e 'Class.new(Graphics::Simulation) { def draw n; clear :white; text "hit escape to quit", 100, 100, :black; end; }.new(500, 250, 0, "Working!").run'
|
data/lib/graphics.rb
CHANGED
data/lib/graphics/body.rb
CHANGED
@@ -70,6 +70,14 @@ class Graphics::Body
|
|
70
70
|
self.m = 0.0
|
71
71
|
end
|
72
72
|
|
73
|
+
##
|
74
|
+
# Update the body. Does nothing by default. Override this method to
|
75
|
+
# add behavior to the body.
|
76
|
+
|
77
|
+
def update
|
78
|
+
# do nothing
|
79
|
+
end
|
80
|
+
|
73
81
|
def inspect # :nodoc:
|
74
82
|
"%s(%.2fx%.2f @ %.2f°x%.2f == %p @ %p)" %
|
75
83
|
[self.class, x, y, a, m, position, velocity]
|
data/lib/graphics/decorators.rb
CHANGED
@@ -1,12 +1,20 @@
|
|
1
|
+
##
|
2
|
+
# Include this in your simulation to automatically include an FPS
|
3
|
+
# meter.
|
4
|
+
|
1
5
|
module ShowFPS
|
2
|
-
def draw n
|
6
|
+
def draw n # :nodoc:
|
3
7
|
super
|
4
8
|
fps n
|
5
9
|
end
|
6
10
|
end
|
7
11
|
|
12
|
+
##
|
13
|
+
# Include this in your simulation and define +GRID_WIDTH+ to draw a
|
14
|
+
# grid in the window.
|
15
|
+
|
8
16
|
module DrawGrid
|
9
|
-
def pre_draw n
|
17
|
+
def pre_draw n # :nodoc:
|
10
18
|
super
|
11
19
|
|
12
20
|
(0...w).step(self.class::GRID_WIDTH).each do |x|
|
@@ -16,6 +24,10 @@ module DrawGrid
|
|
16
24
|
end
|
17
25
|
end
|
18
26
|
|
27
|
+
##
|
28
|
+
# Include this in your simulation to make the background white.
|
29
|
+
|
19
30
|
module WhiteBackground
|
20
|
-
CLEAR_COLOR = :white
|
31
|
+
CLEAR_COLOR = :white # :nodoc:
|
32
|
+
DEBUG_COLOR = :black # :nodoc:
|
21
33
|
end
|
data/lib/graphics/extensions.rb
CHANGED
data/lib/graphics/rainbows.rb
CHANGED
@@ -1,17 +1,20 @@
|
|
1
|
+
##
|
2
|
+
# Creates a range of colors all at once. See #initialize_rainbow.
|
3
|
+
|
1
4
|
class Graphics::Rainbow
|
2
|
-
attr_reader :cache
|
5
|
+
attr_reader :cache # :nodoc:
|
3
6
|
|
4
|
-
def initialize
|
7
|
+
def initialize # :nodoc:
|
5
8
|
@cache = self.cache_colors
|
6
9
|
end
|
7
10
|
|
8
|
-
def clamp d, min, max
|
11
|
+
def clamp d, min, max # :nodoc:
|
9
12
|
[[min, d].max, max].min
|
10
13
|
end
|
11
14
|
|
12
15
|
##
|
13
|
-
# Takes a value and a range,
|
14
|
-
|
16
|
+
# Takes a value and a range, and scales that range to 0-360
|
17
|
+
|
15
18
|
def scale d, min, max
|
16
19
|
range = max - min
|
17
20
|
if range != 0
|
@@ -22,7 +25,7 @@ class Graphics::Rainbow
|
|
22
25
|
end
|
23
26
|
end
|
24
27
|
|
25
|
-
def cache_colors
|
28
|
+
def cache_colors # :nodoc:
|
26
29
|
# Saves all the colors to a hash
|
27
30
|
cache = {}
|
28
31
|
(0..360).each do |degree|
|
@@ -31,12 +34,12 @@ class Graphics::Rainbow
|
|
31
34
|
cache
|
32
35
|
end
|
33
36
|
|
34
|
-
def color d, min=0, max=360
|
37
|
+
def color d, min=0, max=360 # :nodoc:
|
35
38
|
scaled = scale d, min, max
|
36
39
|
@cache[scaled]
|
37
40
|
end
|
38
41
|
|
39
|
-
def _color degree
|
42
|
+
def _color degree # :nodoc:
|
40
43
|
raise "Subclass responsibility"
|
41
44
|
end
|
42
45
|
private :_color
|
@@ -46,11 +49,7 @@ end
|
|
46
49
|
# Black to white gradient
|
47
50
|
#
|
48
51
|
class Graphics::Greyscale < Graphics::Rainbow
|
49
|
-
def
|
50
|
-
super
|
51
|
-
end
|
52
|
-
|
53
|
-
def _color degree
|
52
|
+
def _color degree # :nodoc:
|
54
53
|
brightness_unit = degree/360.0
|
55
54
|
brightness = (brightness_unit*255.0).floor # Scale back to RGB
|
56
55
|
|
@@ -62,12 +61,7 @@ end
|
|
62
61
|
# The full RGB spectrum
|
63
62
|
#
|
64
63
|
class Graphics::Hue < Graphics::Rainbow
|
65
|
-
|
66
|
-
def initialize
|
67
|
-
super
|
68
|
-
end
|
69
|
-
|
70
|
-
def _color degree
|
64
|
+
def _color degree # :nodoc:
|
71
65
|
main_color = 1 * 255 # Let chroma (saturation * brightness) always == 1
|
72
66
|
second_strongest_color = ((1 - (degree/60.0 % 2 - 1).abs) * 255).floor
|
73
67
|
|
@@ -93,12 +87,7 @@ end
|
|
93
87
|
# Spectrum with linearly increasing brightness
|
94
88
|
#
|
95
89
|
class Graphics::Cubehelix < Graphics::Rainbow
|
96
|
-
|
97
|
-
def initialize
|
98
|
-
super
|
99
|
-
end
|
100
|
-
|
101
|
-
def _color degree
|
90
|
+
def _color degree # :nodoc:
|
102
91
|
d = degree/360.0
|
103
92
|
start = 0.5 # Starting position in color space - 0=blue, 1=red, 2=green
|
104
93
|
rotations = -1.5 # How many rotations through the rainbow?
|
@@ -119,6 +108,9 @@ class Graphics::Cubehelix < Graphics::Rainbow
|
|
119
108
|
end
|
120
109
|
|
121
110
|
class Graphics::Simulation
|
111
|
+
##
|
112
|
+
# Generate colors using a rainbow and a prefix name.
|
113
|
+
|
122
114
|
def initialize_rainbow rainbow, name
|
123
115
|
rainbow.cache.each do |degree, color|
|
124
116
|
color_name = "#{name}_#{degree}".to_sym
|
data/lib/graphics/simulation.rb
CHANGED
@@ -2,16 +2,64 @@
|
|
2
2
|
|
3
3
|
require "sdl/sdl"
|
4
4
|
|
5
|
-
module SDL
|
5
|
+
module SDL # :nodoc:
|
6
|
+
init INIT_EVERYTHING
|
7
|
+
end
|
8
|
+
|
9
|
+
module SDL
|
10
|
+
##
|
11
|
+
# Renderer is the workhorse of the graphics gem. Everything
|
12
|
+
# graphical gets done through the renderer.
|
13
|
+
|
14
|
+
class Renderer
|
15
|
+
##
|
16
|
+
# The PixelFormat for the current renderer.
|
17
|
+
|
18
|
+
attr_reader :format
|
19
|
+
|
20
|
+
##
|
21
|
+
# The surface used by this renderer.
|
22
|
+
|
23
|
+
attr_reader :surface
|
24
|
+
|
25
|
+
##
|
26
|
+
# The window for this renderer
|
27
|
+
|
28
|
+
attr_reader :window
|
29
|
+
|
30
|
+
##
|
31
|
+
# The title of the window.
|
32
|
+
|
33
|
+
def title
|
34
|
+
@window.title
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# Sets the title of the window.
|
39
|
+
|
40
|
+
def title= s
|
41
|
+
@window.title = s
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
6
45
|
|
7
46
|
##
|
8
47
|
# An abstract simulation. See Graphics::Simulation and Graphics::Drawing.
|
9
48
|
|
10
49
|
class Graphics::AbstractSimulation
|
11
50
|
|
12
|
-
|
51
|
+
##
|
52
|
+
# Flags to be used when initializing a window. Defaults to 0. See
|
53
|
+
# SDL doco for more.
|
54
|
+
|
55
|
+
SCREEN_FLAGS = 0
|
56
|
+
|
57
|
+
# The default color to clear the window.
|
13
58
|
CLEAR_COLOR = :black
|
14
59
|
|
60
|
+
# The default font color for `debug` calls.
|
61
|
+
DEBUG_COLOR = :white
|
62
|
+
|
15
63
|
# degrees to radians
|
16
64
|
D2R = Math::PI / 180.0
|
17
65
|
|
@@ -21,11 +69,19 @@ class Graphics::AbstractSimulation
|
|
21
69
|
# Call +log+ every N ticks, if +log+ is defined.
|
22
70
|
LOG_INTERVAL = 60
|
23
71
|
|
72
|
+
# The default font. Menlo on OS X, Deja Vu Sans Mono on linux.
|
73
|
+
DEFAULT_FONT = case RUBY_PLATFORM
|
74
|
+
when /darwin/ then "Menlo"
|
75
|
+
when /linux/ then "DejaVuSansMono"
|
76
|
+
else
|
77
|
+
raise "Unsupported platform #{RUBY_PLATFORM}. Please fix."
|
78
|
+
end
|
79
|
+
|
24
80
|
# Collection of collections of Bodies to auto-update and draw.
|
25
81
|
attr_accessor :_bodies
|
26
82
|
|
27
|
-
# The
|
28
|
-
attr_accessor :
|
83
|
+
# The renderer (software or hardware backed) the simulation is drawing in.
|
84
|
+
attr_accessor :renderer
|
29
85
|
|
30
86
|
# The window width.
|
31
87
|
attr_accessor :w
|
@@ -42,9 +98,6 @@ class Graphics::AbstractSimulation
|
|
42
98
|
# A hash of color names to their values.
|
43
99
|
attr_accessor :color
|
44
100
|
|
45
|
-
# A hash of color values to their rgb values. For text, apparently. *shrug*
|
46
|
-
attr_accessor :rgb
|
47
|
-
|
48
101
|
# Number of update iterations per drawing tick.
|
49
102
|
attr_accessor :iter_per_tick
|
50
103
|
|
@@ -64,22 +117,28 @@ class Graphics::AbstractSimulation
|
|
64
117
|
#
|
65
118
|
# This also names a bunch colors and hues for convenience.
|
66
119
|
|
67
|
-
def initialize w, h
|
68
|
-
|
120
|
+
def initialize w=nil, h=nil, name=self.class.name, full=false
|
121
|
+
w ||= SDL::Screen::W/2
|
122
|
+
h ||= SDL::Screen::H/2
|
123
|
+
|
124
|
+
# TODO: remove for 1.0.0 final
|
125
|
+
raise "Do NOT pass bpp to Simulation anymore" if !name || Integer === name
|
69
126
|
|
70
127
|
full = full ? SDL::FULLSCREEN : 0
|
71
128
|
|
72
129
|
self._bodies = []
|
73
130
|
|
74
|
-
self.font = find_font(
|
131
|
+
self.font = find_font(DEFAULT_FONT, 32)
|
75
132
|
|
76
|
-
|
133
|
+
name ||= "Unknown"
|
134
|
+
name = name.gsub(/[A-Z]/, ' \0').strip
|
77
135
|
|
78
|
-
self.
|
79
|
-
self.w, self.h =
|
136
|
+
self.renderer = SDL::Screen.open w, h, 32, self.class::SCREEN_FLAGS|full
|
137
|
+
self.w, self.h = w, h
|
138
|
+
|
139
|
+
renderer.title = name
|
80
140
|
|
81
141
|
self.color = {}
|
82
|
-
self.rgb = Hash.new { |hash, k| hash[k] = screen.format.get_rgb(color[k]) }
|
83
142
|
self.paused = false
|
84
143
|
|
85
144
|
self.iter_per_tick = 1
|
@@ -89,6 +148,9 @@ class Graphics::AbstractSimulation
|
|
89
148
|
|
90
149
|
initialize_keys
|
91
150
|
initialize_colors
|
151
|
+
|
152
|
+
clear # so you start with the right color blank window on frame 0
|
153
|
+
renderer.present
|
92
154
|
end
|
93
155
|
|
94
156
|
##
|
@@ -109,17 +171,17 @@ class Graphics::AbstractSimulation
|
|
109
171
|
register_color :red, 255, 0, 0
|
110
172
|
register_color :green, 0, 255, 0
|
111
173
|
register_color :blue, 0, 0, 255
|
112
|
-
register_color :cyan, 0,
|
113
|
-
register_color :magenta, 255, 0,
|
174
|
+
register_color :cyan, 0, 255, 255
|
175
|
+
register_color :magenta, 255, 0, 255
|
114
176
|
register_color :yellow, 255, 255, 0
|
115
|
-
register_color :alpha, 0,
|
177
|
+
register_color :alpha, 0, 0, 0, 0
|
116
178
|
|
117
179
|
(0..99).each do |n|
|
118
180
|
m = (255 * (n / 100.0)).to_i
|
119
|
-
register_color(("gray%02d"
|
120
|
-
register_color(("red%02d"
|
121
|
-
register_color(("green%02d"
|
122
|
-
register_color(("blue%02d"
|
181
|
+
register_color(("gray%02d" % n).to_sym, m, m, m)
|
182
|
+
register_color(("red%02d" % n).to_sym, m, 0, 0)
|
183
|
+
register_color(("green%02d" % n).to_sym, 0, m, 0)
|
184
|
+
register_color(("blue%02d" % n).to_sym, 0, 0, m)
|
123
185
|
register_color(("cyan%02d" % n).to_sym, 0, m, m)
|
124
186
|
register_color(("magenta%02d" % n).to_sym, m, 0, m)
|
125
187
|
register_color(("yellow%02d" % n).to_sym, m, m, 0)
|
@@ -137,10 +199,16 @@ class Graphics::AbstractSimulation
|
|
137
199
|
end
|
138
200
|
end
|
139
201
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
202
|
+
font_dirs = [
|
203
|
+
# OS X
|
204
|
+
"/System/Library/Fonts",
|
205
|
+
"/Library/Fonts",
|
206
|
+
File.expand_path("~/Library/Fonts/"),
|
207
|
+
|
208
|
+
# Ubuntu
|
209
|
+
"/usr/share/fonts/truetype/**/",
|
210
|
+
]
|
211
|
+
FONT_GLOB = "{#{font_dirs.join(",")}}" # :nodoc:
|
144
212
|
|
145
213
|
##
|
146
214
|
# Find and open a (TTF) font. Should be as system agnostic as possible.
|
@@ -165,7 +233,7 @@ class Graphics::AbstractSimulation
|
|
165
233
|
# Register a single Body to be auto-updated and drawn.
|
166
234
|
|
167
235
|
def register_body obj
|
168
|
-
|
236
|
+
register_bodies Array(obj)
|
169
237
|
obj
|
170
238
|
end
|
171
239
|
|
@@ -173,7 +241,77 @@ class Graphics::AbstractSimulation
|
|
173
241
|
# Name a color w/ rgba values.
|
174
242
|
|
175
243
|
def register_color name, r, g, b, a = 255
|
176
|
-
color[name] =
|
244
|
+
color[name] = renderer.format.map_rgba r, g, b, a
|
245
|
+
end
|
246
|
+
|
247
|
+
##
|
248
|
+
# Name a color w/ HSL values.
|
249
|
+
|
250
|
+
def register_hsla n, h, s, l, a = 1.0
|
251
|
+
register_color n, *from_hsl(h, s, l), (a*255).round
|
252
|
+
end
|
253
|
+
|
254
|
+
##
|
255
|
+
# Name a color w/ HSV values.
|
256
|
+
|
257
|
+
def register_hsva n, h, s, v, a = 1.0
|
258
|
+
register_color n, *from_hsv(h, s, v), (a*255).round
|
259
|
+
end
|
260
|
+
|
261
|
+
##
|
262
|
+
# Convert HSL to RGB.
|
263
|
+
#
|
264
|
+
# https://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV
|
265
|
+
|
266
|
+
def from_hsl h, s, l # 0..360, 0..1, 0..1
|
267
|
+
raise ArgumentError, "%f, %f, %f out of range" % [h, s, v] unless
|
268
|
+
h.between?(0, 360) && s.between?(0, 1) && l.between?(0, 1)
|
269
|
+
|
270
|
+
c = (1 - (2*l - 1).abs) * s
|
271
|
+
h2 = h / 60.0
|
272
|
+
x = c * (1 - (h2 % 2 - 1).abs)
|
273
|
+
m = l - c/2
|
274
|
+
|
275
|
+
r, g, b = case
|
276
|
+
when 0 <= h2 && h2 < 1 then [c+m, x+m, 0+m]
|
277
|
+
when 1 <= h2 && h2 < 2 then [x+m, c+m, 0+m]
|
278
|
+
when 2 <= h2 && h2 < 3 then [0+m, c+m, x+m]
|
279
|
+
when 3 <= h2 && h2 < 4 then [0+m, x+m, c+m]
|
280
|
+
when 4 <= h2 && h2 < 5 then [x+m, 0+m, c+m]
|
281
|
+
when 5 <= h2 && h2 < 6 then [c+m, 0+m, x+m]
|
282
|
+
else
|
283
|
+
raise [h, s, v, h2, x, m].inspect
|
284
|
+
end
|
285
|
+
|
286
|
+
[(r*255).round, (g*255).round, (b*255).round]
|
287
|
+
end
|
288
|
+
|
289
|
+
##
|
290
|
+
# Convert HSV to RGB.
|
291
|
+
#
|
292
|
+
# https://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV
|
293
|
+
|
294
|
+
def from_hsv h, s, v # 0..360, 0..1, 0..1
|
295
|
+
raise ArgumentError, "%f, %f, %f out of range" % [h, s, v] unless
|
296
|
+
h.between?(0, 360) && s.between?(0, 1) && v.between?(0, 1)
|
297
|
+
|
298
|
+
c = v * s
|
299
|
+
h2 = h / 60.0
|
300
|
+
x = c * (1 - (h2 % 2 - 1).abs)
|
301
|
+
m = v - c
|
302
|
+
|
303
|
+
r, g, b = case
|
304
|
+
when 0 <= h2 && h2 < 1 then [c+m, x+m, 0+m]
|
305
|
+
when 1 <= h2 && h2 < 2 then [x+m, c+m, 0+m]
|
306
|
+
when 2 <= h2 && h2 < 3 then [0+m, c+m, x+m]
|
307
|
+
when 3 <= h2 && h2 < 4 then [0+m, x+m, c+m]
|
308
|
+
when 4 <= h2 && h2 < 5 then [x+m, 0+m, c+m]
|
309
|
+
when 5 <= h2 && h2 < 6 then [c+m, 0+m, x+m]
|
310
|
+
else
|
311
|
+
raise [h, s, v, h2, x, m].inspect
|
312
|
+
end
|
313
|
+
|
314
|
+
[(r*255).round, (g*255).round, (b*255).round]
|
177
315
|
end
|
178
316
|
|
179
317
|
##
|
@@ -254,20 +392,19 @@ class Graphics::AbstractSimulation
|
|
254
392
|
handle_event event, n while event = SDL::Event.poll
|
255
393
|
handle_keys
|
256
394
|
|
257
|
-
|
395
|
+
break if done
|
396
|
+
next if paused
|
258
397
|
|
259
398
|
iter_per_tick.times { update n; n += 1 }
|
260
399
|
draw_and_flip n
|
261
400
|
|
262
401
|
log if logger and n % log_interval == 0
|
263
|
-
|
264
|
-
break if done
|
265
402
|
end
|
266
403
|
end
|
267
404
|
|
268
405
|
def draw_and_flip n # :nodoc:
|
269
406
|
self.draw n
|
270
|
-
|
407
|
+
renderer.present
|
271
408
|
end
|
272
409
|
|
273
410
|
##
|
@@ -280,10 +417,17 @@ class Graphics::AbstractSimulation
|
|
280
417
|
post_draw n
|
281
418
|
end
|
282
419
|
|
420
|
+
##
|
421
|
+
# The pre-draw phase. Defaults to clearing.
|
422
|
+
|
283
423
|
def pre_draw n
|
284
424
|
clear
|
285
425
|
end
|
286
426
|
|
427
|
+
##
|
428
|
+
# The post-draw phase. Defaults to having all bodies draw
|
429
|
+
# themselves.
|
430
|
+
|
287
431
|
def post_draw n
|
288
432
|
_bodies.each do |ary|
|
289
433
|
draw_collection ary
|
@@ -316,31 +460,36 @@ class Graphics::AbstractSimulation
|
|
316
460
|
end
|
317
461
|
|
318
462
|
##
|
319
|
-
# Clear the whole
|
463
|
+
# Clear the whole window. Defaults to CLEAR_COLOR.
|
320
464
|
|
321
465
|
def clear c = self.class::CLEAR_COLOR
|
322
|
-
|
466
|
+
cc = color[c]
|
467
|
+
if cc then
|
468
|
+
renderer.clear cc
|
469
|
+
else
|
470
|
+
warn "Color #{c} doesn't appear to be registered. Skipping clear."
|
471
|
+
end
|
323
472
|
end
|
324
473
|
|
325
474
|
##
|
326
475
|
# Draw an antialiased line from x1/y1 to x2/y2 in color c.
|
327
476
|
|
328
|
-
def line x1, y1, x2, y2, c
|
477
|
+
def line x1, y1, x2, y2, c, aa = true
|
329
478
|
h = self.h
|
330
|
-
|
479
|
+
renderer.draw_line x1, h-y1-1, x2, h-y2-1, color[c], aa
|
331
480
|
end
|
332
481
|
|
333
482
|
##
|
334
483
|
# Draw a horizontal line from x1 to x2 at y in color c.
|
335
484
|
|
336
|
-
def hline y, c, x1 = 0, x2 =
|
485
|
+
def hline y, c, x1 = 0, x2 = w
|
337
486
|
line x1, y, x2, y, c
|
338
487
|
end
|
339
488
|
|
340
489
|
##
|
341
490
|
# Draw a vertical line from y1 to y2 at y in color c.
|
342
491
|
|
343
|
-
def vline x, c, y1 =
|
492
|
+
def vline x, c, y1 = h-1, y2 = 0
|
344
493
|
line x, y1, x, y2, c
|
345
494
|
end
|
346
495
|
|
@@ -367,14 +516,21 @@ class Graphics::AbstractSimulation
|
|
367
516
|
# Draw a rect at x/y with w by h dimensions in color c. Ignores blending.
|
368
517
|
|
369
518
|
def fast_rect x, y, w, h, c
|
370
|
-
|
519
|
+
y = self.h-y-h # TODO: -1???
|
520
|
+
renderer.fast_rect x, y, w, h, color[c]
|
371
521
|
end
|
372
522
|
|
373
523
|
##
|
374
|
-
#
|
524
|
+
# Read or write a color to x/y. If c is given, write, otherwise read.
|
525
|
+
#
|
526
|
+
# Reading is pretty slow. Try to avoid.
|
375
527
|
|
376
|
-
def point x, y, c
|
377
|
-
|
528
|
+
def point x, y, c = nil
|
529
|
+
if c then
|
530
|
+
renderer[x, h-y-1] = color[c]
|
531
|
+
else
|
532
|
+
renderer[x, h-y-1]
|
533
|
+
end
|
378
534
|
end
|
379
535
|
|
380
536
|
##
|
@@ -390,45 +546,38 @@ class Graphics::AbstractSimulation
|
|
390
546
|
# Draw a rect at x/y with w by h dimensions in color c.
|
391
547
|
|
392
548
|
def rect x, y, w, h, c, fill = false
|
393
|
-
y = self.h-y-h-1
|
394
|
-
|
395
|
-
screen.fill_rect x, y, w, h, color[c]
|
396
|
-
else
|
397
|
-
screen.draw_rect x, y, w, h, color[c]
|
398
|
-
end
|
549
|
+
y = self.h-y-h # TODO: -1???
|
550
|
+
renderer.draw_rect x, y, w, h, color[c], fill
|
399
551
|
end
|
400
552
|
|
401
553
|
##
|
402
554
|
# Draw a circle at x/y with radius r in color c.
|
403
555
|
|
404
|
-
def circle x, y, r, c, fill = false
|
556
|
+
def circle x, y, r, c, fill = false, aa = true
|
405
557
|
y = h-y-1
|
406
|
-
|
407
|
-
screen.fill_circle x, y, r, color[c]
|
408
|
-
else
|
409
|
-
screen.draw_circle x, y, r, color[c]
|
410
|
-
end
|
558
|
+
renderer.draw_circle x, y, r, color[c], aa, fill
|
411
559
|
end
|
412
560
|
|
413
561
|
##
|
414
562
|
# Draw a circle at x/y with radiuses w/h in color c.
|
415
563
|
|
416
|
-
def ellipse x, y, w, h, c, fill = false
|
564
|
+
def ellipse x, y, w, h, c, fill = false, aa = true
|
417
565
|
y = self.h-y-1
|
418
|
-
|
419
|
-
screen.fill_ellipse x, y, w, h, color[c]
|
420
|
-
else
|
421
|
-
screen.draw_ellipse x, y, w, h, color[c]
|
422
|
-
end
|
566
|
+
renderer.draw_ellipse x, y, w, h, color[c], aa, fill
|
423
567
|
end
|
424
568
|
|
425
569
|
##
|
426
570
|
# Draw an antialiased curve from x1/y1 to x2/y2 via control points
|
427
571
|
# cx1/cy1 & cx2/cy2 in color c.
|
428
572
|
|
429
|
-
def bezier
|
430
|
-
h = self.h
|
431
|
-
|
573
|
+
def bezier *points, c
|
574
|
+
h = self.h-1
|
575
|
+
|
576
|
+
# TODO: there is probably a cleaner way... or move entirely into C
|
577
|
+
xs, ys = points.each_slice(2).to_a.transpose
|
578
|
+
ys.map! { |y| h-y }
|
579
|
+
|
580
|
+
renderer.draw_bezier xs, ys, 5, color[c]
|
432
581
|
end
|
433
582
|
|
434
583
|
## Text
|
@@ -437,14 +586,14 @@ class Graphics::AbstractSimulation
|
|
437
586
|
# Return the w/h of the text s in font f.
|
438
587
|
|
439
588
|
def text_size s, f = font
|
440
|
-
f.text_size s
|
589
|
+
f.text_size s.to_s
|
441
590
|
end
|
442
591
|
|
443
592
|
##
|
444
593
|
# Return the rendered text s in color c in font f.
|
445
594
|
|
446
595
|
def render_text s, c, f = font
|
447
|
-
f.render
|
596
|
+
f.render renderer, s, color[c]
|
448
597
|
end
|
449
598
|
|
450
599
|
##
|
@@ -452,7 +601,7 @@ class Graphics::AbstractSimulation
|
|
452
601
|
|
453
602
|
def text s, x, y, c, f = font
|
454
603
|
y = self.h-y-f.height-1
|
455
|
-
f.draw
|
604
|
+
f.draw renderer, s, x, y, color[c]
|
456
605
|
end
|
457
606
|
|
458
607
|
##
|
@@ -461,24 +610,22 @@ class Graphics::AbstractSimulation
|
|
461
610
|
|
462
611
|
def debug fmt, *args
|
463
612
|
s = fmt % args
|
464
|
-
text s, 10, h-40-font.height,
|
613
|
+
text s, 10, h-40-font.height, self.class::DEBUG_COLOR
|
465
614
|
end
|
466
615
|
|
467
616
|
attr_accessor :start_time # :nodoc:
|
468
617
|
|
469
618
|
##
|
470
|
-
# Draw the current frames-per-second in the top left corner
|
619
|
+
# Draw the current frames-per-second in the top left corner. Defaults to green.
|
471
620
|
|
472
|
-
def fps n
|
621
|
+
def fps n, color = :green
|
473
622
|
secs = Time.now - start_time
|
474
623
|
fps = "%5.1f fps" % [n / secs]
|
475
|
-
text fps, 10, h-font.height,
|
624
|
+
text fps, 10, h-font.height, color
|
476
625
|
end
|
477
626
|
|
478
627
|
### Blitting Methods:
|
479
628
|
|
480
|
-
# TODO: copy_rect(x,y,w,h)
|
481
|
-
|
482
629
|
##
|
483
630
|
# Load an image at path into a new surface.
|
484
631
|
|
@@ -512,48 +659,40 @@ class Graphics::AbstractSimulation
|
|
512
659
|
##
|
513
660
|
# Draw a bitmap centered at x/y with optional angle, x/y scale, and flags.
|
514
661
|
|
515
|
-
def blit src, x, y, a° =
|
516
|
-
|
517
|
-
|
518
|
-
SDL::Surface.blit img, 0, 0, 0, 0, screen, x-img.w/2, h-y-img.h/2
|
662
|
+
def blit src, x, y, a° = nil, xscale = nil, yscale = nil, flags = nil
|
663
|
+
renderer.blit src, x-src.w/2, h-y-src.h/2, a°, xscale, yscale, :center
|
519
664
|
end
|
520
665
|
|
521
666
|
##
|
522
667
|
# Draw a bitmap at x/y with optional angle, x/y scale, and flags.
|
523
668
|
|
524
|
-
def put src, x, y, a° =
|
525
|
-
|
526
|
-
|
527
|
-
# why x-1? because transform adds a pixel to all sides even if a°==0
|
528
|
-
SDL::Surface.blit img, 0, 0, 0, 0, screen, x-1, h-y-img.h
|
669
|
+
def put src, x, y, a° = nil, xscale = nil, yscale = nil, flags = nil
|
670
|
+
renderer.blit src, x, h-y-src.h, a°, xscale, yscale, false
|
529
671
|
end
|
530
672
|
|
531
673
|
##
|
532
|
-
# Save the current
|
674
|
+
# Save the current window to a png.
|
533
675
|
|
534
676
|
def save path
|
535
|
-
|
677
|
+
renderer.save path
|
536
678
|
end
|
537
679
|
|
538
680
|
##
|
539
|
-
# Create a new
|
540
|
-
# block
|
541
|
-
# primitives will work and the resulting surface is returned.
|
681
|
+
# Create a new renderer with a given width and height and yield to a
|
682
|
+
# block for drawing. The resulting surface is returned.
|
542
683
|
|
543
684
|
def sprite w, h
|
544
|
-
|
545
|
-
|
546
|
-
old_w, old_h
|
685
|
+
old_renderer = renderer
|
686
|
+
new_renderer = renderer.sprite w, h
|
687
|
+
old_w, old_h = renderer.w, renderer.h
|
547
688
|
self.w, self.h = w, h
|
689
|
+
self.renderer = new_renderer
|
548
690
|
|
549
|
-
self.screen = new_screen
|
550
691
|
yield if block_given?
|
551
692
|
|
552
|
-
|
553
|
-
|
554
|
-
new_screen
|
693
|
+
new_renderer.surface
|
555
694
|
ensure
|
556
|
-
self.
|
695
|
+
self.renderer = old_renderer
|
557
696
|
self.w, self.h = old_w, old_h
|
558
697
|
end
|
559
698
|
end
|
@@ -577,7 +716,7 @@ end
|
|
577
716
|
# + Ball::View.draw takes a window and a ball and draws it.
|
578
717
|
|
579
718
|
class Graphics::Simulation < Graphics::AbstractSimulation
|
580
|
-
|
719
|
+
|
581
720
|
end
|
582
721
|
|
583
722
|
##
|
@@ -587,23 +726,43 @@ end
|
|
587
726
|
# See AbstractSimulation for most methods.
|
588
727
|
|
589
728
|
class Graphics::Drawing < Graphics::AbstractSimulation
|
590
|
-
|
729
|
+
##
|
730
|
+
# The canvas used for all drawing.
|
731
|
+
|
732
|
+
attr_accessor :texture
|
591
733
|
|
592
|
-
def initialize(*a)
|
734
|
+
def initialize(*a) # :nodoc:
|
593
735
|
super
|
594
736
|
|
595
|
-
|
737
|
+
self.texture = renderer.new_texture
|
738
|
+
|
739
|
+
draw_on texture do
|
740
|
+
clear
|
741
|
+
yield if block_given?
|
742
|
+
end
|
596
743
|
end
|
597
744
|
|
598
|
-
|
599
|
-
|
600
|
-
|
745
|
+
##
|
746
|
+
# Temporarily render to a texture instead of the renderer's window,
|
747
|
+
# then copy that texture to the renderer and present it.
|
748
|
+
|
749
|
+
def draw_on texture
|
750
|
+
renderer.target = texture
|
751
|
+
|
752
|
+
yield if block_given?
|
753
|
+
ensure
|
754
|
+
renderer.target = nil
|
755
|
+
renderer.copy_texture texture
|
756
|
+
renderer.present
|
601
757
|
end
|
602
|
-
end
|
603
758
|
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
759
|
+
def pre_draw n # :nodoc:
|
760
|
+
# no clear
|
761
|
+
end
|
762
|
+
|
763
|
+
def draw_and_flip n # :nodoc:
|
764
|
+
draw_on texture do
|
765
|
+
self.draw n
|
766
|
+
end
|
767
|
+
end
|
609
768
|
end
|