graphics 1.0.0b5 → 1.0.0b6
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/History.rdoc +38 -0
- data/Manifest.txt +5 -0
- data/Rakefile +2 -0
- data/examples/boid.rb +14 -15
- data/examples/bounce.rb +9 -11
- data/examples/canvas.rb +3 -1
- data/examples/collision.rb +10 -8
- data/examples/demo.rb +12 -12
- data/examples/fluid2.rb +13 -8
- data/examples/gol2.rb +0 -2
- data/examples/math.rb +3 -1
- data/examples/pi_polygon.rb +145 -0
- data/examples/radar.rb +3 -1
- data/examples/rainbow_fluid.rb +243 -0
- data/examples/tank.rb +19 -17
- data/examples/tank2.rb +25 -21
- data/examples/targeting.rb +3 -1
- data/examples/vants.rb +5 -21
- data/examples/walker.rb +15 -12
- data/examples/walker2.rb +28 -26
- data/examples/zombies.rb +0 -2
- data/ext/sdl/sdl.c +10 -3
- data/ext/sdl/sge/sge_primitives.cpp +11 -0
- data/ext/sdl/sge/sge_primitives.h +3 -0
- data/lib/graphics.rb +2 -1
- data/lib/graphics/body.rb +10 -25
- data/lib/graphics/decorators.rb +21 -0
- data/lib/graphics/rainbows.rb +128 -0
- data/lib/graphics/simulation.rb +139 -15
- data/test/test_graphics.rb +45 -9
- data/test/test_rainbows.rb +95 -0
- metadata +20 -28
- metadata.gz.sig +0 -0
data/examples/walker.rb
CHANGED
@@ -37,15 +37,6 @@ class Person < Graphics::Body
|
|
37
37
|
self.m += D_M unless m >= M_M
|
38
38
|
end
|
39
39
|
|
40
|
-
def draw
|
41
|
-
trail.draw
|
42
|
-
|
43
|
-
w.angle x, y, ga, 60, :red
|
44
|
-
|
45
|
-
# the blit looks HORRIBLE when rotated... dunno why
|
46
|
-
w.blit w.body_img, x, y
|
47
|
-
end
|
48
|
-
|
49
40
|
def turn_towards_goal
|
50
41
|
turn a.relative_angle(ga, D_A)
|
51
42
|
end
|
@@ -66,6 +57,17 @@ class Person < Graphics::Body
|
|
66
57
|
self.a = (a + 180).degrees
|
67
58
|
change_goal
|
68
59
|
end
|
60
|
+
|
61
|
+
class View
|
62
|
+
def self.draw w, b
|
63
|
+
b.trail.draw
|
64
|
+
|
65
|
+
w.angle b.x, b.y, b.ga, 60, :red
|
66
|
+
|
67
|
+
# the blit looks HORRIBLE when rotated... dunno why
|
68
|
+
w.blit w.body_img, b.x, b.y
|
69
|
+
end
|
70
|
+
end
|
69
71
|
end
|
70
72
|
|
71
73
|
class WalkerSimulation < Graphics::Simulation
|
@@ -75,6 +77,7 @@ class WalkerSimulation < Graphics::Simulation
|
|
75
77
|
super 850, 850, 16, "Walker"
|
76
78
|
|
77
79
|
self.ps = populate Person
|
80
|
+
register_bodies ps
|
78
81
|
|
79
82
|
self.body_img = sprite 20, 20 do
|
80
83
|
circle 10, 10, 5, :white, :filled
|
@@ -84,14 +87,14 @@ class WalkerSimulation < Graphics::Simulation
|
|
84
87
|
end
|
85
88
|
|
86
89
|
def update n
|
87
|
-
|
90
|
+
super
|
91
|
+
|
88
92
|
detect_collisions(ps).each(&:collide)
|
89
93
|
end
|
90
94
|
|
91
95
|
def draw n
|
92
|
-
|
96
|
+
super
|
93
97
|
|
94
|
-
ps.each(&:draw)
|
95
98
|
fps n
|
96
99
|
end
|
97
100
|
|
data/examples/walker2.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
#!/usr/local/bin/ruby -w
|
2
2
|
|
3
|
-
# srand 42
|
4
|
-
|
5
3
|
require "graphics"
|
6
4
|
require "graphics/trail"
|
7
5
|
|
@@ -90,26 +88,6 @@ class Person < Graphics::Body
|
|
90
88
|
self.m += D_M unless m >= max
|
91
89
|
end
|
92
90
|
|
93
|
-
def draw
|
94
|
-
if debug? and attack? then
|
95
|
-
w.angle x, y, a-75, VISIBILITY, :yellow
|
96
|
-
w.angle x, y, a-25, VISIBILITY, :yellow
|
97
|
-
w.angle x, y, a+25, VISIBILITY, :yellow
|
98
|
-
w.angle x, y, a+75, VISIBILITY, :yellow
|
99
|
-
nearby.each do |o|
|
100
|
-
w.line x, y, o.x, o.y, :yellow
|
101
|
-
end
|
102
|
-
# sleep 0.25 unless nearby.empty?
|
103
|
-
end
|
104
|
-
|
105
|
-
w.angle x, y, a, 20, :green
|
106
|
-
w.angle x, y, ga, 10, :red
|
107
|
-
|
108
|
-
# the blit looks HORRIBLE when rotated... dunno why
|
109
|
-
w.blit w.body_img, x, y
|
110
|
-
w.circle x, y, 5, :red, :filled if attack?
|
111
|
-
end
|
112
|
-
|
113
91
|
def turn_towards_goal
|
114
92
|
turn a.relative_angle(ga, D_A)
|
115
93
|
end
|
@@ -133,6 +111,30 @@ class Person < Graphics::Body
|
|
133
111
|
self.a = (a + 180).degrees
|
134
112
|
change_goal
|
135
113
|
end
|
114
|
+
|
115
|
+
class View
|
116
|
+
def self.draw w, b
|
117
|
+
x, y, a, ga = b.x, b.y, b.a, b.ga
|
118
|
+
|
119
|
+
if b.debug? and b.attack? then
|
120
|
+
w.angle x, y, a-75, VISIBILITY, :yellow
|
121
|
+
w.angle x, y, a-25, VISIBILITY, :yellow
|
122
|
+
w.angle x, y, a+25, VISIBILITY, :yellow
|
123
|
+
w.angle x, y, a+75, VISIBILITY, :yellow
|
124
|
+
b.nearby.each do |o|
|
125
|
+
w.line x, y, o.x, o.y, :yellow
|
126
|
+
end
|
127
|
+
# sleep 0.25 unless nearby.empty?
|
128
|
+
end
|
129
|
+
|
130
|
+
w.angle x, y, a, 20, :green
|
131
|
+
w.angle x, y, ga, 10, :red
|
132
|
+
|
133
|
+
# the blit looks HORRIBLE when rotated... dunno why
|
134
|
+
w.blit w.body_img, x, y
|
135
|
+
w.circle x, y, 5, :red, :filled if b.attack?
|
136
|
+
end
|
137
|
+
end
|
136
138
|
end
|
137
139
|
|
138
140
|
class WalkerSimulation < Graphics::Simulation
|
@@ -142,6 +144,7 @@ class WalkerSimulation < Graphics::Simulation
|
|
142
144
|
super 850, 850, 16, "Walker"
|
143
145
|
|
144
146
|
self.ps = populate Person, 2
|
147
|
+
register_bodies ps
|
145
148
|
|
146
149
|
# 5.times do |n|
|
147
150
|
# ps[n].attack = true
|
@@ -168,7 +171,8 @@ class WalkerSimulation < Graphics::Simulation
|
|
168
171
|
end
|
169
172
|
|
170
173
|
def update n
|
171
|
-
|
174
|
+
super
|
175
|
+
|
172
176
|
detect_collisions(ps).each do |a, b|
|
173
177
|
a.collide b
|
174
178
|
end
|
@@ -177,9 +181,7 @@ class WalkerSimulation < Graphics::Simulation
|
|
177
181
|
end
|
178
182
|
|
179
183
|
def draw n
|
180
|
-
|
181
|
-
|
182
|
-
ps.each(&:draw)
|
184
|
+
super
|
183
185
|
|
184
186
|
debug "#{ps.size}"
|
185
187
|
fps n
|
data/examples/zombies.rb
CHANGED
data/ext/sdl/sdl.c
CHANGED
@@ -727,6 +727,12 @@ static VALUE Surface_transform(VALUE self, VALUE bgcolor, VALUE angle,
|
|
727
727
|
return TypedData_Wrap_Struct(cSurface, &_Surface_type, result);
|
728
728
|
}
|
729
729
|
|
730
|
+
static VALUE Surface_save(VALUE self, VALUE path) {
|
731
|
+
DEFINE_SELF(Surface, surface, self);
|
732
|
+
|
733
|
+
return INT2NUM(SDL_SaveBMP(surface, RSTRING_PTR(path)));
|
734
|
+
}
|
735
|
+
|
730
736
|
//// SDL::TTFFont methods:
|
731
737
|
|
732
738
|
static void _TTFFont_free(void* font) {
|
@@ -909,9 +915,10 @@ void Init_sdl() {
|
|
909
915
|
rb_define_method(cSurface, "w", Surface_w, 0);
|
910
916
|
rb_define_method(cSurface, "[]", Surface_index, 2);
|
911
917
|
rb_define_method(cSurface, "[]=", Surface_index_equals, 3);
|
912
|
-
rb_define_method(cSurface, "transform",
|
913
|
-
rb_define_method(cSurface, "
|
914
|
-
rb_define_method(cSurface, "
|
918
|
+
rb_define_method(cSurface, "transform", Surface_transform, 5);
|
919
|
+
rb_define_method(cSurface, "save", Surface_save, 1);
|
920
|
+
rb_define_method(cSurface, "flags", Surface_flags, 0);
|
921
|
+
rb_define_method(cSurface, "set_alpha", Surface_set_alpha, 2);
|
915
922
|
|
916
923
|
//// SDL::TTFFont methods:
|
917
924
|
|
@@ -2514,3 +2514,14 @@ void sge_AABezier(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16
|
|
2514
2514
|
sge_AABezierAlpha(surface,x1,y1,x2,y2,x3,y3,x4,y4,level, SDL_MapRGB(surface->format,R,G,B),255);
|
2515
2515
|
}
|
2516
2516
|
|
2517
|
+
//==================================================================================
|
2518
|
+
// Added by zenspider:
|
2519
|
+
//==================================================================================
|
2520
|
+
|
2521
|
+
void sge_FastFilledRect(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color) {
|
2522
|
+
for (Sint16 y = y1; y <= y2; y++) {
|
2523
|
+
_HLine(Surface, x1, x2, y, color);
|
2524
|
+
}
|
2525
|
+
|
2526
|
+
sge_UpdateRect(Surface, x1, y1, x2, y2);
|
2527
|
+
}
|
@@ -105,6 +105,9 @@ DECLSPEC void sge_Bezier(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2,
|
|
105
105
|
DECLSPEC void sge_BezierAlpha(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,Sint16 x3, Sint16 y3, Sint16 x4, Sint16 y4, int level, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha);
|
106
106
|
DECLSPEC void sge_AABezier(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,Sint16 x3, Sint16 y3, Sint16 x4, Sint16 y4, int level, Uint8 R, Uint8 G, Uint8 B);
|
107
107
|
DECLSPEC void sge_AABezierAlpha(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,Sint16 x3, Sint16 y3, Sint16 x4, Sint16 y4, int level, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha);
|
108
|
+
|
109
|
+
// Added by zenspider
|
110
|
+
DECLSPEC void sge_FastFilledRect(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color);
|
108
111
|
#endif /* sge_C_ONLY */
|
109
112
|
|
110
113
|
|
data/lib/graphics.rb
CHANGED
data/lib/graphics/body.rb
CHANGED
@@ -177,18 +177,18 @@ class Graphics::Body
|
|
177
177
|
max_h, max_w = w.h, w.w
|
178
178
|
|
179
179
|
if x < 0 then
|
180
|
-
self.x =
|
180
|
+
self.x = x.abs
|
181
181
|
return :west
|
182
182
|
elsif x > max_w then
|
183
|
-
self.x = max_w
|
183
|
+
self.x = 2 * max_w - x
|
184
184
|
return :east
|
185
185
|
end
|
186
186
|
|
187
187
|
if y < 0 then
|
188
|
-
self.y =
|
188
|
+
self.y = y.abs
|
189
189
|
return :south
|
190
190
|
elsif y > max_h then
|
191
|
-
self.y = max_h
|
191
|
+
self.y = 2 * max_h - y
|
192
192
|
return :north
|
193
193
|
end
|
194
194
|
|
@@ -223,28 +223,13 @@ class Graphics::Body
|
|
223
223
|
|
224
224
|
##
|
225
225
|
# Like clip, keep the body in bounds of the window, but set the
|
226
|
-
# angle to the angle of reflection. Also slows momentum by
|
226
|
+
# angle to the angle of reflection. Also slows momentum by +friction+%.
|
227
227
|
|
228
|
-
def bounce
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
if x < 0 then
|
234
|
-
self.x, normal = 0, 0
|
235
|
-
elsif x > max_w then
|
236
|
-
self.x, normal = max_w, 180
|
237
|
-
end
|
238
|
-
|
239
|
-
if y < 0 then
|
240
|
-
self.y, normal = 0, 90
|
241
|
-
elsif y > max_h then
|
242
|
-
self.y, normal = max_h, 270
|
243
|
-
end
|
244
|
-
|
245
|
-
if normal then
|
246
|
-
self.a = (2 * normal - 180 - a).degrees
|
247
|
-
self.m *= 0.8
|
228
|
+
def bounce friction = 0.2
|
229
|
+
if wall = clip then
|
230
|
+
self.a = (2 * NORMAL[wall] - 180 - a).degrees
|
231
|
+
self.m *= (1.0 - friction) if friction and friction > 0
|
232
|
+
true
|
248
233
|
end
|
249
234
|
end
|
250
235
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ShowFPS
|
2
|
+
def draw n
|
3
|
+
super
|
4
|
+
fps n
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
module DrawGrid
|
9
|
+
def pre_draw n
|
10
|
+
super
|
11
|
+
|
12
|
+
(0...w).step(self.class::GRID_WIDTH).each do |x|
|
13
|
+
hline x, :gray
|
14
|
+
vline x, :gray
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module WhiteBackground
|
20
|
+
CLEAR_COLOR = :white
|
21
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
class Graphics::Rainbow
|
2
|
+
attr_reader :cache
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@cache = self.cache_colors
|
6
|
+
end
|
7
|
+
|
8
|
+
def clamp d, min, max
|
9
|
+
[[min, d].max, max].min
|
10
|
+
end
|
11
|
+
|
12
|
+
##
|
13
|
+
# Takes a value and a range,
|
14
|
+
# and scales that range to 0-360
|
15
|
+
def scale d, min, max
|
16
|
+
range = max - min
|
17
|
+
if range != 0
|
18
|
+
scaled = (d.to_f / range) * 360
|
19
|
+
return clamp(scaled, 0, 360).round
|
20
|
+
else
|
21
|
+
0
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def cache_colors
|
26
|
+
# Saves all the colors to a hash
|
27
|
+
cache = {}
|
28
|
+
(0..360).each do |degree|
|
29
|
+
cache[degree] = _color degree
|
30
|
+
end
|
31
|
+
cache
|
32
|
+
end
|
33
|
+
|
34
|
+
def color d, min=0, max=360
|
35
|
+
scaled = scale d, min, max
|
36
|
+
@cache[scaled]
|
37
|
+
end
|
38
|
+
|
39
|
+
def _color degree
|
40
|
+
raise "Subclass responsibility"
|
41
|
+
end
|
42
|
+
private :_color
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Black to white gradient
|
47
|
+
#
|
48
|
+
class Graphics::Greyscale < Graphics::Rainbow
|
49
|
+
def initialize
|
50
|
+
super
|
51
|
+
end
|
52
|
+
|
53
|
+
def _color degree
|
54
|
+
brightness_unit = degree/360.0
|
55
|
+
brightness = (brightness_unit*255.0).floor # Scale back to RGB
|
56
|
+
|
57
|
+
[brightness, brightness, brightness]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# The full RGB spectrum
|
63
|
+
#
|
64
|
+
class Graphics::Hue < Graphics::Rainbow
|
65
|
+
|
66
|
+
def initialize
|
67
|
+
super
|
68
|
+
end
|
69
|
+
|
70
|
+
def _color degree
|
71
|
+
main_color = 1 * 255 # Let chroma (saturation * brightness) always == 1
|
72
|
+
second_strongest_color = ((1 - (degree/60.0 % 2 - 1).abs) * 255).floor
|
73
|
+
|
74
|
+
case degree
|
75
|
+
when 0..60
|
76
|
+
[main_color, second_strongest_color, 0]
|
77
|
+
when 61..120
|
78
|
+
[second_strongest_color, main_color, 0]
|
79
|
+
when 121..180
|
80
|
+
[0, main_color, second_strongest_color]
|
81
|
+
when 181..240
|
82
|
+
[0, second_strongest_color, main_color]
|
83
|
+
when 241..300
|
84
|
+
[second_strongest_color, 0, main_color]
|
85
|
+
when 301..360
|
86
|
+
[main_color, 0, second_strongest_color]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
##
|
93
|
+
# Spectrum with linearly increasing brightness
|
94
|
+
#
|
95
|
+
class Graphics::Cubehelix < Graphics::Rainbow
|
96
|
+
|
97
|
+
def initialize
|
98
|
+
super
|
99
|
+
end
|
100
|
+
|
101
|
+
def _color degree
|
102
|
+
d = degree/360.0
|
103
|
+
start = 0.5 # Starting position in color space - 0=blue, 1=red, 2=green
|
104
|
+
rotations = -1.5 # How many rotations through the rainbow?
|
105
|
+
saturation = 1.2
|
106
|
+
gamma = 1.0
|
107
|
+
fract = d**gamma # Position on the spectrum
|
108
|
+
|
109
|
+
# Amplitude of the helix
|
110
|
+
amp = saturation * fract * (1 - fract) / 2.0
|
111
|
+
angle = 2*Math::PI*(start/3.0 + 1.0 + rotations*fract)
|
112
|
+
# From the CubeHelix Equations
|
113
|
+
r = fract + amp * (-0.14861 * Math.cos(angle) + 1.78277 * Math.sin(angle))
|
114
|
+
g = fract + amp * (-0.29227 * Math.cos(angle) - 0.90649 * Math.sin(angle))
|
115
|
+
b = fract + amp * (1.97294 * Math.cos(angle))
|
116
|
+
|
117
|
+
[(r * 255).round, (g * 255).round, (b * 255).round]
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
class Graphics::Simulation
|
122
|
+
def initialize_rainbow rainbow, name
|
123
|
+
rainbow.cache.each do |degree, color|
|
124
|
+
color_name = "#{name}_#{degree}".to_sym
|
125
|
+
self.register_color(color_name, *color, 255)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/lib/graphics/simulation.rb
CHANGED
@@ -5,10 +5,12 @@ require "sdl/sdl"
|
|
5
5
|
module SDL; end # :nodoc: -- stupid rdoc :(
|
6
6
|
|
7
7
|
##
|
8
|
-
#
|
9
|
-
# convenience methods to make life easier.
|
8
|
+
# An abstract simulation. See Graphics::Simulation and Graphics::Drawing.
|
10
9
|
|
11
|
-
class Graphics::
|
10
|
+
class Graphics::AbstractSimulation
|
11
|
+
|
12
|
+
# The default color to clear the screen.
|
13
|
+
CLEAR_COLOR = :black
|
12
14
|
|
13
15
|
# degrees to radians
|
14
16
|
D2R = Math::PI / 180.0
|
@@ -19,6 +21,9 @@ class Graphics::Simulation
|
|
19
21
|
# Call +log+ every N ticks, if +log+ is defined.
|
20
22
|
LOG_INTERVAL = 60
|
21
23
|
|
24
|
+
# Collection of collections of Bodies to auto-update and draw.
|
25
|
+
attr_accessor :_bodies
|
26
|
+
|
22
27
|
# The window the simulation is drawing in.
|
23
28
|
attr_accessor :screen
|
24
29
|
|
@@ -49,6 +54,9 @@ class Graphics::Simulation
|
|
49
54
|
# Procs registered to handle keydown events.
|
50
55
|
attr_accessor :keydown_handler
|
51
56
|
|
57
|
+
# Is the application done?
|
58
|
+
attr_accessor :done
|
59
|
+
|
52
60
|
##
|
53
61
|
# Create a new simulation of a certain width and height. Optionally,
|
54
62
|
# you can set the bits per pixel (0 for current screen settings),
|
@@ -61,11 +69,13 @@ class Graphics::Simulation
|
|
61
69
|
|
62
70
|
full = full ? SDL::FULLSCREEN : 0
|
63
71
|
|
72
|
+
self._bodies = []
|
73
|
+
|
64
74
|
self.font = find_font("Menlo", 32)
|
65
75
|
|
66
76
|
SDL::WM.set_caption name, name
|
67
77
|
|
68
|
-
self.screen = SDL::Screen.open w, h, bpp,
|
78
|
+
self.screen = SDL::Screen.open w, h, bpp, self.class::SCREEN_FLAGS|full
|
69
79
|
self.w, self.h = screen.w, screen.h
|
70
80
|
|
71
81
|
self.color = {}
|
@@ -85,8 +95,8 @@ class Graphics::Simulation
|
|
85
95
|
# Register default key events. Handles ESC & Q (quit) and P (pause).
|
86
96
|
|
87
97
|
def initialize_keys
|
88
|
-
add_keydown_handler("\e") {
|
89
|
-
add_keydown_handler("q") {
|
98
|
+
add_keydown_handler("\e") { self.done = true }
|
99
|
+
add_keydown_handler("q") { self.done = true }
|
90
100
|
add_keydown_handler("p") { self.paused = !paused }
|
91
101
|
add_keydown_handler("/") { self.iter_per_tick += 1 }
|
92
102
|
add_keydown_handler("-") { self.iter_per_tick -= 1; self.iter_per_tick = 1 if iter_per_tick < 1 }
|
@@ -95,10 +105,12 @@ class Graphics::Simulation
|
|
95
105
|
def initialize_colors # :nodoc:
|
96
106
|
register_color :black, 0, 0, 0
|
97
107
|
register_color :white, 255, 255, 255
|
108
|
+
register_color :gray, 127, 127, 127
|
98
109
|
register_color :red, 255, 0, 0
|
99
110
|
register_color :green, 0, 255, 0
|
100
111
|
register_color :blue, 0, 0, 255
|
101
|
-
register_color :
|
112
|
+
register_color :cyan, 0, 255, 255
|
113
|
+
register_color :magenta, 255, 0, 255
|
102
114
|
register_color :yellow, 255, 255, 0
|
103
115
|
register_color :alpha, 0, 0, 0, 0
|
104
116
|
|
@@ -108,6 +120,20 @@ class Graphics::Simulation
|
|
108
120
|
register_color(("red%02d" % n).to_sym, m, 0, 0)
|
109
121
|
register_color(("green%02d" % n).to_sym, 0, m, 0)
|
110
122
|
register_color(("blue%02d" % n).to_sym, 0, 0, m)
|
123
|
+
register_color(("cyan%02d" % n).to_sym, 0, m, m)
|
124
|
+
register_color(("magenta%02d" % n).to_sym, m, 0, m)
|
125
|
+
register_color(("yellow%02d" % n).to_sym, m, m, 0)
|
126
|
+
end
|
127
|
+
|
128
|
+
(0...256).each do |n|
|
129
|
+
m = (256 * n / 255.0).to_i
|
130
|
+
register_color(("gray%03d" % n).to_sym, m, m, m)
|
131
|
+
register_color(("red%03d" % n).to_sym, m, 0, 0)
|
132
|
+
register_color(("green%03d" % n).to_sym, 0, m, 0)
|
133
|
+
register_color(("blue%03d" % n).to_sym, 0, 0, m)
|
134
|
+
register_color(("cyan%03d" % n).to_sym, 0, m, m)
|
135
|
+
register_color(("magenta%03d" % n).to_sym, m, 0, m)
|
136
|
+
register_color(("yellow%03d" % n).to_sym, m, m, 0)
|
111
137
|
end
|
112
138
|
end
|
113
139
|
|
@@ -127,6 +153,22 @@ class Graphics::Simulation
|
|
127
153
|
SDL::TTF.open(font, size)
|
128
154
|
end
|
129
155
|
|
156
|
+
##
|
157
|
+
# Register a collection of bodies to be auto-updated and drawn.
|
158
|
+
|
159
|
+
def register_bodies ary
|
160
|
+
_bodies << ary
|
161
|
+
ary
|
162
|
+
end
|
163
|
+
|
164
|
+
##
|
165
|
+
# Register a single Body to be auto-updated and drawn.
|
166
|
+
|
167
|
+
def register_body obj
|
168
|
+
_bodies << [obj]
|
169
|
+
obj
|
170
|
+
end
|
171
|
+
|
130
172
|
##
|
131
173
|
# Name a color w/ rgba values.
|
132
174
|
|
@@ -203,6 +245,7 @@ class Graphics::Simulation
|
|
203
245
|
self.start_time = Time.now
|
204
246
|
n = 0
|
205
247
|
event = nil
|
248
|
+
self.done = false
|
206
249
|
|
207
250
|
logger = respond_to? :log
|
208
251
|
log_interval = self.class::LOG_INTERVAL
|
@@ -217,6 +260,8 @@ class Graphics::Simulation
|
|
217
260
|
draw_and_flip n
|
218
261
|
|
219
262
|
log if logger and n % log_interval == 0
|
263
|
+
|
264
|
+
break if done
|
220
265
|
end
|
221
266
|
end
|
222
267
|
|
@@ -226,25 +271,54 @@ class Graphics::Simulation
|
|
226
271
|
end
|
227
272
|
|
228
273
|
##
|
229
|
-
# Draw the scene
|
230
|
-
#
|
274
|
+
# Draw the scene by clearing the window and drawing all registered
|
275
|
+
# bodies. You are free to completely override this or call super and
|
276
|
+
# add any extras at the end.
|
231
277
|
|
232
278
|
def draw n
|
233
|
-
|
279
|
+
pre_draw n
|
280
|
+
post_draw n
|
281
|
+
end
|
282
|
+
|
283
|
+
def pre_draw n
|
284
|
+
clear
|
285
|
+
end
|
286
|
+
|
287
|
+
def post_draw n
|
288
|
+
_bodies.each do |ary|
|
289
|
+
draw_collection ary
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
##
|
294
|
+
# Draw a homogeneous collection of bodies. This assumes that the MVC
|
295
|
+
# pattern described on this class is being used.
|
296
|
+
|
297
|
+
def draw_collection ary
|
298
|
+
return if ary.empty?
|
299
|
+
|
300
|
+
cls = ary.first.class.const_get :View
|
301
|
+
|
302
|
+
ary.each do |obj|
|
303
|
+
cls.draw self, obj
|
304
|
+
end
|
234
305
|
end
|
235
306
|
|
236
307
|
##
|
237
|
-
# Update the simulation
|
238
|
-
#
|
308
|
+
# Update the simulation by telling all registered bodies to update.
|
309
|
+
# You are free to completely override this or call super and add any
|
310
|
+
# extras at the end.
|
239
311
|
|
240
312
|
def update n
|
241
|
-
|
313
|
+
_bodies.each do |ary|
|
314
|
+
ary.each(&:update)
|
315
|
+
end
|
242
316
|
end
|
243
317
|
|
244
318
|
##
|
245
|
-
# Clear the whole screen
|
319
|
+
# Clear the whole screen. Defaults to CLEAR_COLOR.
|
246
320
|
|
247
|
-
def clear c =
|
321
|
+
def clear c = self.class::CLEAR_COLOR
|
248
322
|
fast_rect 0, 0, w, h, c
|
249
323
|
end
|
250
324
|
|
@@ -454,6 +528,13 @@ class Graphics::Simulation
|
|
454
528
|
SDL::Surface.blit img, 0, 0, 0, 0, screen, x-1, h-y-img.h
|
455
529
|
end
|
456
530
|
|
531
|
+
##
|
532
|
+
# Save the current screen to a bmp
|
533
|
+
|
534
|
+
def save path
|
535
|
+
screen.save path
|
536
|
+
end
|
537
|
+
|
457
538
|
##
|
458
539
|
# Create a new sprite with a given width and height and yield to a
|
459
540
|
# block with the new sprite as the current screen. All drawing
|
@@ -477,6 +558,49 @@ class Graphics::Simulation
|
|
477
558
|
end
|
478
559
|
end
|
479
560
|
|
561
|
+
##
|
562
|
+
# A simulation. This ties everything together and provides a bunch of
|
563
|
+
# convenience methods to make life easier.
|
564
|
+
#
|
565
|
+
# In the Model View Controller (MVC) pattern, the simulation is the
|
566
|
+
# Controller and controls both the window and all bodies involved in
|
567
|
+
# the simulation. The bodies are the Model and each body class is
|
568
|
+
# expected to have an inner View class w/ a #draw class method for the
|
569
|
+
# View.
|
570
|
+
#
|
571
|
+
# For example, in examples/bounce.rb:
|
572
|
+
#
|
573
|
+
# + BounceSimulation subclasses Graphics::Simulation
|
574
|
+
# + BounceSimulation has many Balls
|
575
|
+
# + Ball#update maintains all ball movement.
|
576
|
+
# + BounceSimulation#draw automatically calls Ball::View.draw on all balls.
|
577
|
+
# + Ball::View.draw takes a window and a ball and draws it.
|
578
|
+
|
579
|
+
class Graphics::Simulation < Graphics::AbstractSimulation
|
580
|
+
SCREEN_FLAGS = SDL::HWSURFACE|SDL::DOUBLEBUF
|
581
|
+
end
|
582
|
+
|
583
|
+
##
|
584
|
+
# A drawing. Like a Simulation, but on a canvas that doesn't have
|
585
|
+
# double buffering or clearing on each tick.
|
586
|
+
#
|
587
|
+
# See AbstractSimulation for most methods.
|
588
|
+
|
589
|
+
class Graphics::Drawing < Graphics::AbstractSimulation
|
590
|
+
SCREEN_FLAGS = SDL::HWSURFACE
|
591
|
+
|
592
|
+
def initialize(*a)
|
593
|
+
super
|
594
|
+
|
595
|
+
clear
|
596
|
+
end
|
597
|
+
|
598
|
+
def draw_and_flip n
|
599
|
+
screen.update 0, 0, 0, 0
|
600
|
+
# no flip
|
601
|
+
end
|
602
|
+
end
|
603
|
+
|
480
604
|
if $0 == __FILE__ then
|
481
605
|
SDL.init SDL::INIT_EVERYTHING
|
482
606
|
SDL.set_video_mode(640, 480, 16, SDL::SWSURFACE)
|