graphics 1.0.0b1 → 1.0.0b4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/History.rdoc +30 -0
  5. data/Manifest.txt +39 -7
  6. data/README.rdoc +48 -4
  7. data/Rakefile +8 -2
  8. data/examples/boid.rb +9 -18
  9. data/examples/bounce.rb +15 -23
  10. data/examples/canvas.rb +75 -0
  11. data/examples/collision.rb +6 -6
  12. data/examples/demo.rb +5 -7
  13. data/examples/editor.rb +12 -9
  14. data/examples/fluid.rb +2 -3
  15. data/examples/fluid2.rb +1 -1
  16. data/examples/{lito2.rb → gol.rb} +0 -0
  17. data/examples/{zenspider4.rb → gol2.rb} +0 -0
  18. data/examples/logo.rb +4 -7
  19. data/examples/maze.rb +136 -0
  20. data/examples/tank.rb +10 -11
  21. data/examples/tank2.rb +12 -17
  22. data/examples/targeting.rb +1 -1
  23. data/examples/vants.rb +1 -1
  24. data/examples/walker.rb +3 -12
  25. data/examples/walker2.rb +197 -0
  26. data/examples/zombies.rb +31 -35
  27. data/ext/sdl/extconf.rb +31 -0
  28. data/ext/sdl/sdl.c +1067 -0
  29. data/ext/sdl/sge/INSTALL +72 -0
  30. data/ext/sdl/sge/LICENSE +504 -0
  31. data/ext/sdl/sge/Makefile +83 -0
  32. data/ext/sdl/sge/Makefile.conf +63 -0
  33. data/ext/sdl/sge/README +219 -0
  34. data/ext/sdl/sge/Todo +7 -0
  35. data/ext/sdl/sge/WhatsNew +224 -0
  36. data/ext/sdl/sge/sge.h +31 -0
  37. data/ext/sdl/sge/sge_blib.cpp +1939 -0
  38. data/ext/sdl/sge/sge_blib.h +68 -0
  39. data/ext/sdl/sge/sge_bm_text.cpp +451 -0
  40. data/ext/sdl/sge/sge_bm_text.h +71 -0
  41. data/ext/sdl/sge/sge_collision.cpp +388 -0
  42. data/ext/sdl/sge/sge_collision.h +54 -0
  43. data/ext/sdl/sge/sge_config.h +6 -0
  44. data/ext/sdl/sge/sge_internal.h +152 -0
  45. data/ext/sdl/sge/sge_misc.cpp +92 -0
  46. data/ext/sdl/sge/sge_misc.h +37 -0
  47. data/ext/sdl/sge/sge_primitives.cpp +2516 -0
  48. data/ext/sdl/sge/sge_primitives.h +111 -0
  49. data/ext/sdl/sge/sge_rotation.cpp +683 -0
  50. data/ext/sdl/sge/sge_rotation.h +46 -0
  51. data/ext/sdl/sge/sge_shape.cpp +762 -0
  52. data/ext/sdl/sge/sge_shape.h +365 -0
  53. data/ext/sdl/sge/sge_surface.cpp +1090 -0
  54. data/ext/sdl/sge/sge_surface.h +100 -0
  55. data/ext/sdl/sge/sge_textpp.cpp +785 -0
  56. data/ext/sdl/sge/sge_textpp.h +270 -0
  57. data/ext/sdl/sge/sge_tt_text.cpp +1456 -0
  58. data/ext/sdl/sge/sge_tt_text.h +114 -0
  59. data/graphics_setup.sh +26 -0
  60. data/lib/graphics.rb +1 -1
  61. data/lib/graphics/body.rb +50 -3
  62. data/lib/graphics/extensions.rb +13 -7
  63. data/lib/graphics/simulation.rb +126 -46
  64. data/test/test_graphics.rb +52 -12
  65. data/test/test_sdl.rb +1 -0
  66. metadata +54 -23
  67. metadata.gz.sig +0 -0
  68. data/.gemtest +0 -0
  69. data/examples/lito.rb +0 -108
  70. data/examples/zenspider1.rb +0 -93
  71. data/examples/zenspider2.rb +0 -123
  72. data/examples/zenspider3.rb +0 -104
  73. data/rubysdl_setup.sh +0 -34
@@ -34,8 +34,6 @@ class Demo < Graphics::Simulation
34
34
  super 800, 800, 16, "Boid"
35
35
  self.ball = Ball.new self
36
36
 
37
- r = color[:red]
38
-
39
37
  self.img = sprite 10, 10 do
40
38
  circle 5, 5, 5, :white, :filled
41
39
  end
@@ -64,12 +62,14 @@ class Demo < Graphics::Simulation
64
62
 
65
63
  circle 225, 50, 10, :white
66
64
 
67
- ellipse 250, 50, 10, 10, :white
65
+ ellipse 250, 50, 10, 20, :white
68
66
 
69
67
  bezier 275, 50, 275, 100, 285, 0, 300, 50, :white
70
68
 
71
69
  rect 300, 25, 50, 50, :white
72
- blit img, 325, 50, 0
70
+
71
+ blit img, 325, 50 # centered
72
+ put img, 335, 50 # cornered
73
73
 
74
74
  text "blah", 350, 50, :white
75
75
 
@@ -85,6 +85,4 @@ class Demo < Graphics::Simulation
85
85
  end
86
86
  end
87
87
 
88
- if $0 == __FILE__
89
- Demo.new.run
90
- end
88
+ Demo.new.run if $0 == __FILE__
@@ -16,9 +16,14 @@ class Editor < Graphics::Simulation
16
16
  self.lines = []
17
17
  end
18
18
 
19
+ def initialize_keys
20
+ # no super
21
+ add_key_handler(:ESCAPE) { exit }
22
+ end
23
+
19
24
  def handle_event e, n
20
25
  case e
21
- when SDL::Event::KeyDown then
26
+ when SDL::Event::Keydown then
22
27
  if e.mod & (SDL::Key::MOD_LCTRL | SDL::Key::MOD_RCTRL) != 0 then
23
28
  case e.sym.chr
24
29
  when "t" then
@@ -55,16 +60,14 @@ class Editor < Graphics::Simulation
55
60
  end
56
61
 
57
62
  def draw_overlay
58
- if overlay? then
59
- lines.each_with_index do |l, i|
60
- text l, 10, ((lines.size-i)*font.height), :gray
61
- end
63
+ return unless overlay?
62
64
 
63
- text "> #{s}_", 10, 0, :white
65
+ lines.each_with_index do |l, i|
66
+ text l, 10, ((lines.size-i)*font.height), :gray
64
67
  end
68
+
69
+ text "> #{s}_", 10, 0, :white
65
70
  end
66
71
  end
67
72
 
68
- if $0 == __FILE__
69
- Editor.new.run
70
- end
73
+ Editor.new.run if $0 == __FILE__
@@ -111,15 +111,14 @@ class SPH
111
111
  # Calculate fluid density around each particle
112
112
  particles.each do |particle|
113
113
  particles.each do |neighbor|
114
-
115
114
  # If particles are close together, density increases
116
115
  distance = particle.position - neighbor.position
117
116
 
118
- if distance.magnitude < H # Particles are close enough to matter
117
+ if distance.magnitude < H then
118
+ # Particles are close enough to matter
119
119
  particle.density += MASS * weight(distance, H)
120
120
  end
121
121
  end
122
- # p particle.density if particle.density > 2*H
123
122
  end
124
123
  end
125
124
 
@@ -52,7 +52,7 @@ class Particle < Graphics::Body
52
52
  nearby.each do |neighbor|
53
53
  distance = (position - neighbor.position)
54
54
 
55
- self.density += MASS * weight(distance, H) # if distance.magnitude < H
55
+ self.density += MASS * weight(distance, H)
56
56
  end
57
57
  end
58
58
 
File without changes
File without changes
@@ -34,9 +34,8 @@ class Turtle < Graphics::Body
34
34
  self.a += $1.to_i
35
35
  when /f (\d+)/ then
36
36
  dist = $1.to_i
37
- if pen then
38
- w.angle x, y, a, dist, :white
39
- end
37
+
38
+ w.angle x, y, a, dist, :white if pen
40
39
  move_by a, dist
41
40
  else
42
41
  src.delete line
@@ -51,7 +50,7 @@ class Turtle < Graphics::Body
51
50
  p2 = w.project(x, y, a+90, 5)
52
51
  p3 = w.project(x, y, a-90, 5)
53
52
 
54
- polygon p1, p2, p3, :green
53
+ w.polygon p1, p2, p3, :green
55
54
  end
56
55
  end
57
56
 
@@ -68,6 +67,4 @@ class Logo < Editor
68
67
  end
69
68
  end
70
69
 
71
- if $0 == __FILE__
72
- Logo.new.run
73
- end
70
+ Logo.new.run if $0 == __FILE__
@@ -0,0 +1,136 @@
1
+ #!/usr/local/bin/ruby -w
2
+ # -*- coding: utf-8 -*-
3
+
4
+ require "graphics"
5
+
6
+ ##
7
+ # All code here is adapted from Jamis Buck's Mazes for Programmers.
8
+ # Used with Permission.
9
+
10
+ class Cell
11
+ attr_reader :row, :column
12
+ attr_accessor :north, :south, :east, :west
13
+
14
+ def initialize(row, column)
15
+ @row, @column = row, column
16
+ @links = {}
17
+ end
18
+
19
+ def link(cell, bidi=true)
20
+ @links[cell] = true
21
+ cell.link(self, false) if bidi
22
+ self
23
+ end
24
+
25
+ def linked?(cell)
26
+ @links.key?(cell)
27
+ end
28
+ end
29
+
30
+ class Grid
31
+ attr_reader :rows, :columns, :w
32
+
33
+ def initialize(rows, columns, w)
34
+ @rows = rows
35
+ @columns = columns
36
+ @w = w
37
+
38
+ @grid = prepare_grid
39
+ configure_cells
40
+ end
41
+
42
+ def prepare_grid
43
+ Array.new(rows) do |row|
44
+ Array.new(columns) do |column|
45
+ Cell.new(row, column)
46
+ end
47
+ end
48
+ end
49
+
50
+ def configure_cells
51
+ each_cell do |cell|
52
+ row, col = cell.row, cell.column
53
+
54
+ cell.north = self[row - 1, col]
55
+ cell.south = self[row + 1, col]
56
+ cell.west = self[row, col - 1]
57
+ cell.east = self[row, col + 1]
58
+ end
59
+ end
60
+
61
+ def [](row, column)
62
+ return nil unless row.between?(0, @rows - 1)
63
+ return nil unless column.between?(0, @grid[row].count - 1)
64
+ @grid[row][column]
65
+ end
66
+
67
+ def each_row
68
+ @grid.each do |row|
69
+ yield row
70
+ end
71
+ end
72
+
73
+ def each_cell
74
+ each_row do |row|
75
+ row.each do |cell|
76
+ yield cell if cell
77
+ end
78
+ end
79
+ end
80
+
81
+ def draw n
82
+ cell_size = w.w / columns
83
+
84
+ each_cell do |cell|
85
+ x1 = cell_size * cell.column
86
+ y1 = cell_size * cell.row
87
+ x2 = cell_size * (cell.column + 1)
88
+ y2 = cell_size * (cell.row + 1)
89
+
90
+ w.line x1, y1, x2, y1, :white unless cell.north
91
+ w.line x1, y1, x1, y2, :white unless cell.west
92
+ w.line x2, y1, x2, y2, :white unless cell.linked? cell.east
93
+ w.line x1, y2, x2, y2, :white unless cell.linked? cell.south
94
+ end
95
+ end
96
+ end
97
+
98
+ class BinaryTree
99
+ def self.on(grid)
100
+ grid.each_cell do |cell|
101
+ neighbors = []
102
+ neighbors << cell.north if cell.north
103
+ neighbors << cell.east if cell.east
104
+
105
+ index = rand(neighbors.length)
106
+ neighbor = neighbors[index]
107
+
108
+ cell.link(neighbor) if neighbor
109
+ end
110
+
111
+ grid
112
+ end
113
+ end
114
+
115
+ class Maze < Graphics::Simulation
116
+ attr_accessor :grid
117
+
118
+ def initialize
119
+ super 800, 800
120
+
121
+ self.grid = Grid.new 50, 50, self
122
+ BinaryTree.on grid
123
+ end
124
+
125
+ def update n
126
+ # do nothing
127
+ end
128
+
129
+ def draw n
130
+ clear
131
+
132
+ grid.draw n
133
+ end
134
+ end
135
+
136
+ Maze.new.run if $0 == __FILE__
@@ -123,8 +123,6 @@ class TargetSimulation < Graphics::Simulation
123
123
  def initialize
124
124
  super 640, 640, 16, "Target Practice"
125
125
 
126
- SDL::Key.enable_key_repeat 50, 10
127
-
128
126
  self.tank = Tank.new self
129
127
  self.bullets = []
130
128
 
@@ -132,15 +130,16 @@ class TargetSimulation < Graphics::Simulation
132
130
  self.turret_img = image "resources/images/turret.png"
133
131
  end
134
132
 
135
- def handle_keys
136
- exit if SDL::Key.press? SDL::Key::ESCAPE
137
- tank.turn_right if SDL::Key.press? SDL::Key::RIGHT
138
- tank.turn_left if SDL::Key.press? SDL::Key::LEFT
139
- tank.accelerate if SDL::Key.press? SDL::Key::UP
140
- tank.decelerate if SDL::Key.press? SDL::Key::DOWN
141
- tank.aim_left if SDL::Key.press? SDL::Key::SEMICOLON
142
- tank.aim_right if SDL::Key.press? SDL::Key::Q
143
- tank.fire if SDL::Key.press? SDL::Key::SPACE
133
+ def initialize_keys
134
+ super
135
+
136
+ add_key_handler(:RIGHT) { tank.turn_right }
137
+ add_key_handler(:LEFT) { tank.turn_left }
138
+ add_key_handler(:UP) { tank.accelerate }
139
+ add_key_handler(:DOWN) { tank.decelerate }
140
+ add_key_handler(:SEMICOLON) { tank.aim_left }
141
+ add_key_handler(:Q, :remove){ tank.aim_right }
142
+ add_key_handler(:SPACE) { tank.fire }
144
143
  end
145
144
 
146
145
  def update n
@@ -97,13 +97,9 @@ class TargetSimulation < Graphics::Simulation
97
97
  def initialize
98
98
  super 640, 640, 16, "Target Practice"
99
99
 
100
- SDL::Key.enable_key_repeat 50, 10
101
-
102
100
  self.tank = Tank.new w/2, h/2
103
101
  self.bullets = []
104
102
 
105
- screen.set_alpha SDL::SRCALPHA, 128
106
-
107
103
  self.body_img = sprite 40, 30 do
108
104
  rect 0, 0, 39, 29, :white
109
105
  rect 0, 4, 39, 21, :white
@@ -120,15 +116,16 @@ class TargetSimulation < Graphics::Simulation
120
116
  end
121
117
  end
122
118
 
123
- def handle_keys
124
- exit if SDL::Key.press? SDL::Key::ESCAPE
125
- tank.turn_right if SDL::Key.press? SDL::Key::RIGHT
126
- tank.turn_left if SDL::Key.press? SDL::Key::LEFT
127
- tank.accelerate if SDL::Key.press? SDL::Key::UP
128
- tank.decelerate if SDL::Key.press? SDL::Key::DOWN
129
- tank.aim_left if SDL::Key.press? SDL::Key::SEMICOLON
130
- tank.aim_right if SDL::Key.press? SDL::Key::Q
131
- fire if SDL::Key.press? SDL::Key::SPACE
119
+ def initialize_keys
120
+ super
121
+
122
+ add_key_handler(:RIGHT) { tank.turn_right }
123
+ add_key_handler(:LEFT) { tank.turn_left }
124
+ add_key_handler(:UP) { tank.accelerate }
125
+ add_key_handler(:DOWN) { tank.decelerate }
126
+ add_key_handler(:SEMICOLON) { tank.aim_left }
127
+ add_key_handler(:Q, :remove){ tank.aim_right }
128
+ add_key_handler(:SPACE) { fire }
132
129
  end
133
130
 
134
131
  def fire
@@ -152,13 +149,11 @@ class TargetSimulation < Graphics::Simulation
152
149
  fps n
153
150
  end
154
151
 
155
- AA = SDL::Surface::TRANSFORM_AA
156
-
157
152
  def draw_tank
158
153
  x, y, a, t = tank.x, tank.y, tank.angle, tank.turret
159
154
 
160
- blit body_img, x, y, a, AA
161
- blit turret_img, x, y, t, AA
155
+ blit body_img, x, y, a
156
+ blit turret_img, x, y, t
162
157
 
163
158
  debug "%3d @ %.2f @ %d", tank.angle, tank.speed, tank.energy
164
159
  end
@@ -15,7 +15,7 @@ class TargetSimulation < Graphics::Simulation
15
15
  end
16
16
 
17
17
  def handle_event event, n
18
- bombs << [n, event.x, h-event.y] if SDL::Event::MouseButtonDown === event
18
+ bombs << [n, event.x, h-event.y] if SDL::Event::Mousedown === event
19
19
  super
20
20
  end
21
21
 
@@ -62,7 +62,7 @@ class Vants < Graphics::Simulation
62
62
  end
63
63
 
64
64
  def draw n
65
- screen.update_rect 0, 0, 0, 0
65
+ screen.update 0, 0, 0, 0
66
66
  end
67
67
  end
68
68
 
@@ -10,9 +10,7 @@ class Person < Graphics::Body
10
10
  D_M = 0.25
11
11
  M_M = 5.0
12
12
 
13
- AA = SDL::Surface::TRANSFORM_AA
14
-
15
- attr_accessor :trail, :attack
13
+ attr_accessor :trail
16
14
 
17
15
  def initialize w
18
16
  super
@@ -21,7 +19,6 @@ class Person < Graphics::Body
21
19
 
22
20
  self.a = random_angle
23
21
  self.ga = random_angle
24
- self.attack = false
25
22
  end
26
23
 
27
24
  def update
@@ -43,16 +40,10 @@ class Person < Graphics::Body
43
40
  def draw
44
41
  trail.draw
45
42
 
46
- if attack then
47
- w.angle x, y, a-45, 50, :yellow
48
- w.angle x, y, a, 60, :red
49
- w.angle x, y, a+45, 50, :yellow
50
- end
51
-
52
43
  w.angle x, y, ga, 60, :red
53
44
 
54
45
  # the blit looks HORRIBLE when rotated... dunno why
55
- w.blit w.body_img, x, y, 0, AA
46
+ w.blit w.body_img, x, y
56
47
  end
57
48
 
58
49
  def turn_towards_goal
@@ -68,7 +59,7 @@ class Person < Graphics::Body
68
59
  end
69
60
 
70
61
  def collide_with? other
71
- w.cmap.collision_check(x, y, w.cmap, other.x, other.y) != nil
62
+ w.cmap.check(x, y, w.cmap, other.x, other.y) != nil
72
63
  end
73
64
 
74
65
  def collide
@@ -0,0 +1,197 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ # srand 42
4
+
5
+ require "graphics"
6
+ require "graphics/trail"
7
+
8
+ class Person < Graphics::Body
9
+ COUNT = 40
10
+
11
+ D_A = 5.0
12
+ D_M = 0.25
13
+ M_M = 5.0
14
+
15
+ VISIBILITY = 100
16
+ ATTACK_DISTANCE = 6 * 2
17
+ VISIBILITY_SQ = VISIBILITY**2
18
+ ATTACK_DISTANCE_SQ = ATTACK_DISTANCE**2
19
+
20
+ attr_accessor :attack, :debug
21
+ alias attack? attack
22
+ alias debug? debug
23
+
24
+ def initialize w
25
+ super
26
+
27
+ self.a = random_angle
28
+ self.ga = random_angle
29
+ self.attack = false
30
+ self.debug = false
31
+ end
32
+
33
+ def update
34
+ return update_attack if attack?
35
+
36
+ normal_update
37
+ end
38
+
39
+ def normal_update
40
+ turn_towards_goal
41
+ possibly_change_goal
42
+
43
+ # accelerate
44
+ # move
45
+
46
+ wrap
47
+ end
48
+
49
+ def near? p
50
+ distance_to_squared(p) < VISIBILITY_SQ
51
+ end
52
+
53
+ def visible? o
54
+ pa = self.angle_to o
55
+ da = (pa - self.a + 90).degrees
56
+ da.between?(75, 150)
57
+ end
58
+
59
+ def nearby
60
+ @nearby ||= begin
61
+ all_but_me = w.ps.reject(&:attack?)
62
+ nearby = all_but_me.find_all { |p| self.near? p }
63
+ visible = nearby.select { |p| self.visible? p }
64
+ visible.sort_by { |p| self.distance_to_squared(p) }
65
+ end
66
+ end
67
+
68
+ def update_attack
69
+ @nearby = nil
70
+
71
+ nearby.each do |p|
72
+ dist = self.distance_to_squared(p)
73
+
74
+ if dist <= ATTACK_DISTANCE_SQ then
75
+ p.kill
76
+ else
77
+ self.ga = self.angle_to(nearby.first)
78
+ end
79
+ end
80
+
81
+ normal_update
82
+ end
83
+
84
+ def kill
85
+ w.ps.delete self unless attack?
86
+ end
87
+
88
+ def accelerate
89
+ max = attack ? 1.1 * M_M : M_M
90
+ self.m += D_M unless m >= max
91
+ end
92
+
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
+ def turn_towards_goal
114
+ turn a.relative_angle(ga, D_A)
115
+ end
116
+
117
+ def change_goal
118
+ self.ga = (a + random_turn(180)).degrees
119
+ end
120
+
121
+ def possibly_change_goal
122
+ close = ga.close_to?(a)
123
+ change = close && 1 =~ 25
124
+ change_goal if change
125
+ end
126
+
127
+ def collide_with? other
128
+ w.cmap.check(x, y, w.cmap, other.x, other.y) != nil
129
+ end
130
+
131
+ def collide b
132
+ return b.kill if self.attack?
133
+ self.a = (a + 180).degrees
134
+ change_goal
135
+ end
136
+ end
137
+
138
+ class WalkerSimulation < Graphics::Simulation
139
+ attr_accessor :ps, :body_img, :cmap
140
+
141
+ def initialize
142
+ super 850, 850, 16, "Walker"
143
+
144
+ self.ps = populate Person, 2
145
+
146
+ # 5.times do |n|
147
+ # ps[n].attack = true
148
+ # end
149
+
150
+ ps[0].debug = true
151
+ ps[0].attack = true
152
+
153
+ ps.first.x = w/2
154
+ ps.first.y = h/2
155
+ ps.first.a = 90
156
+ ps.first.ga = 90
157
+
158
+ ps.last.x = w/2 + 50
159
+ ps.last.y = h/2 + 50
160
+ ps.last.a = 0
161
+ ps.last.ga = 0
162
+
163
+ self.body_img = sprite 20, 20 do
164
+ circle 10, 10, 5, :white, :filled
165
+ end
166
+
167
+ self.cmap = body_img.make_collision_map
168
+ end
169
+
170
+ def update n
171
+ ps.each(&:update)
172
+ detect_collisions(ps).each do |a, b|
173
+ a.collide b
174
+ end
175
+
176
+ exit if ps.all?(&:attack?)
177
+ end
178
+
179
+ def draw n
180
+ clear
181
+
182
+ ps.each(&:draw)
183
+
184
+ debug "#{ps.size}"
185
+ fps n
186
+ end
187
+
188
+ def detect_collisions sprites
189
+ collisions = []
190
+ sprites.combination(2).each do |a, b|
191
+ collisions << [a, b] if a.collide_with? b
192
+ end
193
+ collisions
194
+ end
195
+ end
196
+
197
+ WalkerSimulation.new.run