gosu-examples 1.0.3

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 (55) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/README.md +14 -0
  4. data/bin/gosu-examples +97 -0
  5. data/examples/chipmunk_and_rmagick.rb +152 -0
  6. data/examples/chipmunk_integration.rb +278 -0
  7. data/examples/cptn_ruby.rb +229 -0
  8. data/examples/media/BrokenPNG.png +0 -0
  9. data/examples/media/Cursor.png +0 -0
  10. data/examples/media/JingleBells.mp3 +0 -0
  11. data/examples/media/JingleBells.ogg +0 -0
  12. data/examples/media/Loop.wav +0 -0
  13. data/examples/media/Sample.wav +0 -0
  14. data/examples/media/SquareTexture.png +0 -0
  15. data/examples/media/Wallpaper.png +0 -0
  16. data/examples/media/WallpaperXXL.png +0 -0
  17. data/examples/media/WhiteAlpha.png +0 -0
  18. data/examples/media/audio_formats/aiff_32bit_float.aiff +0 -0
  19. data/examples/media/audio_formats/au_16bit_pcm.au +0 -0
  20. data/examples/media/audio_formats/caf_be_16bit_44khz.caf +0 -0
  21. data/examples/media/audio_formats/caf_le_16bit_44khz.caf +0 -0
  22. data/examples/media/audio_formats/caf_le_8bit_44khz.caf +0 -0
  23. data/examples/media/audio_formats/general_midi.mid +0 -0
  24. data/examples/media/audio_formats/impulse_tracker.it +0 -0
  25. data/examples/media/audio_formats/mp3_128k_stereo.mp3 +0 -0
  26. data/examples/media/audio_formats/mp3_avg_96kbit_jointstereo.mp3 +0 -0
  27. data/examples/media/audio_formats/ogg_vorbis.ogg +0 -0
  28. data/examples/media/audio_formats/wav_16bit_pcm.wav +0 -0
  29. data/examples/media/audio_formats/wav_32bit_pcm.wav +0 -0
  30. data/examples/media/audio_formats/wav_4bit_ms_adpcm.wav +0 -0
  31. data/examples/media/beep.wav +0 -0
  32. data/examples/media/cptn_ruby.png +0 -0
  33. data/examples/media/cptn_ruby_map.txt +25 -0
  34. data/examples/media/earth.png +0 -0
  35. data/examples/media/explosion.wav +0 -0
  36. data/examples/media/gem.png +0 -0
  37. data/examples/media/header.psd +0 -0
  38. data/examples/media/image_formats/test.jpg +0 -0
  39. data/examples/media/image_formats/test.psd +0 -0
  40. data/examples/media/landscape.svg +10 -0
  41. data/examples/media/large_star.png +0 -0
  42. data/examples/media/smoke.png +0 -0
  43. data/examples/media/soldier.png +0 -0
  44. data/examples/media/space.png +0 -0
  45. data/examples/media/star.png +0 -0
  46. data/examples/media/starfighter.bmp +0 -0
  47. data/examples/media/tileset.png +0 -0
  48. data/examples/media/vera.ttf +0 -0
  49. data/examples/opengl_integration.rb +224 -0
  50. data/examples/rmagick_integration.rb +413 -0
  51. data/examples/tutorial.rb +129 -0
  52. data/examples/welcome.rb +59 -0
  53. data/lib/gosu-examples/example.rb +82 -0
  54. data/lib/gosu-examples/sidebar.rb +60 -0
  55. metadata +112 -0
@@ -0,0 +1,229 @@
1
+ # Encoding: UTF-8
2
+
3
+ # Basically, the tutorial game taken to a jump'n'run perspective.
4
+
5
+ # Shows how to
6
+ # * implement jumping/gravity
7
+ # * implement scrolling using Window#translate
8
+ # * implement a simple tile-based map
9
+ # * load levels from primitive text files
10
+
11
+ # Some exercises, starting at the real basics:
12
+ # 0) understand the existing code!
13
+ # As shown in the tutorial:
14
+ # 1) change it use Gosu's Z-ordering
15
+ # 2) add gamepad support
16
+ # 3) add a score as in the tutorial game
17
+ # 4) similarly, add sound effects for various events
18
+ # Exploring this game's code and Gosu:
19
+ # 5) make the player wider, so he doesn't fall off edges as easily
20
+ # 6) add background music (check if playing in Window#update to implement
21
+ # looping)
22
+ # 7) implement parallax scrolling for the star background!
23
+ # Getting tricky:
24
+ # 8) optimize Map#draw so only tiles on screen are drawn (needs modulo, a pen
25
+ # and paper to figure out)
26
+ # 9) add loading of next level when all gems are collected
27
+ # ...Enemies, a more sophisticated object system, weapons, title and credits
28
+ # screens...
29
+
30
+ require 'rubygems'
31
+ require 'gosu'
32
+
33
+ WIDTH, HEIGHT = 600, 600
34
+
35
+ module Tiles
36
+ Grass = 0
37
+ Earth = 1
38
+ end
39
+
40
+ class CollectibleGem
41
+ attr_reader :x, :y
42
+
43
+ def initialize(image, x, y)
44
+ @image = image
45
+ @x, @y = x, y
46
+ end
47
+
48
+ def draw
49
+ # Draw, slowly rotating
50
+ @image.draw_rot(@x, @y, 0, 25 * Math.sin(Gosu::milliseconds / 133.7))
51
+ end
52
+ end
53
+
54
+ # Player class.
55
+ class Player
56
+ attr_reader :x, :y
57
+
58
+ def initialize(map, x, y)
59
+ @x, @y = x, y
60
+ @dir = :left
61
+ @vy = 0 # Vertical velocity
62
+ @map = map
63
+ # Load all animation frames
64
+ @standing, @walk1, @walk2, @jump = *Gosu::Image.load_tiles("media/cptn_ruby.png", 50, 50)
65
+ # This always points to the frame that is currently drawn.
66
+ # This is set in update, and used in draw.
67
+ @cur_image = @standing
68
+ end
69
+
70
+ def draw
71
+ # Flip vertically when facing to the left.
72
+ if @dir == :left then
73
+ offs_x = -25
74
+ factor = 1.0
75
+ else
76
+ offs_x = 25
77
+ factor = -1.0
78
+ end
79
+ @cur_image.draw(@x + offs_x, @y - 49, 0, factor, 1.0)
80
+ end
81
+
82
+ # Could the object be placed at x + offs_x/y + offs_y without being stuck?
83
+ def would_fit(offs_x, offs_y)
84
+ # Check at the center/top and center/bottom for map collisions
85
+ not @map.solid?(@x + offs_x, @y + offs_y) and
86
+ not @map.solid?(@x + offs_x, @y + offs_y - 45)
87
+ end
88
+
89
+ def update(move_x)
90
+ # Select image depending on action
91
+ if (move_x == 0)
92
+ @cur_image = @standing
93
+ else
94
+ @cur_image = (Gosu::milliseconds / 175 % 2 == 0) ? @walk1 : @walk2
95
+ end
96
+ if (@vy < 0)
97
+ @cur_image = @jump
98
+ end
99
+
100
+ # Directional walking, horizontal movement
101
+ if move_x > 0 then
102
+ @dir = :right
103
+ move_x.times { if would_fit(1, 0) then @x += 1 end }
104
+ end
105
+ if move_x < 0 then
106
+ @dir = :left
107
+ (-move_x).times { if would_fit(-1, 0) then @x -= 1 end }
108
+ end
109
+
110
+ # Acceleration/gravity
111
+ # By adding 1 each frame, and (ideally) adding vy to y, the player's
112
+ # jumping curve will be the parabole we want it to be.
113
+ @vy += 1
114
+ # Vertical movement
115
+ if @vy > 0 then
116
+ @vy.times { if would_fit(0, 1) then @y += 1 else @vy = 0 end }
117
+ end
118
+ if @vy < 0 then
119
+ (-@vy).times { if would_fit(0, -1) then @y -= 1 else @vy = 0 end }
120
+ end
121
+ end
122
+
123
+ def try_to_jump
124
+ if @map.solid?(@x, @y + 1) then
125
+ @vy = -20
126
+ end
127
+ end
128
+
129
+ def collect_gems(gems)
130
+ # Same as in the tutorial game.
131
+ gems.reject! do |c|
132
+ (c.x - @x).abs < 50 and (c.y - @y).abs < 50
133
+ end
134
+ end
135
+ end
136
+
137
+ # Map class holds and draws tiles and gems.
138
+ class Map
139
+ attr_reader :width, :height, :gems
140
+
141
+ def initialize(filename)
142
+ # Load 60x60 tiles, 5px overlap in all four directions.
143
+ @tileset = Gosu::Image.load_tiles("media/tileset.png", 60, 60, :tileable => true)
144
+
145
+ gem_img = Gosu::Image.new("media/gem.png")
146
+ @gems = []
147
+
148
+ lines = File.readlines(filename).map { |line| line.chomp }
149
+ @height = lines.size
150
+ @width = lines[0].size
151
+ @tiles = Array.new(@width) do |x|
152
+ Array.new(@height) do |y|
153
+ case lines[y][x, 1]
154
+ when '"'
155
+ Tiles::Grass
156
+ when '#'
157
+ Tiles::Earth
158
+ when 'x'
159
+ @gems.push(CollectibleGem.new(gem_img, x * 50 + 25, y * 50 + 25))
160
+ nil
161
+ else
162
+ nil
163
+ end
164
+ end
165
+ end
166
+ end
167
+
168
+ def draw
169
+ # Very primitive drawing function:
170
+ # Draws all the tiles, some off-screen, some on-screen.
171
+ @height.times do |y|
172
+ @width.times do |x|
173
+ tile = @tiles[x][y]
174
+ if tile
175
+ # Draw the tile with an offset (tile images have some overlap)
176
+ # Scrolling is implemented here just as in the game objects.
177
+ @tileset[tile].draw(x * 50 - 5, y * 50 - 5, 0)
178
+ end
179
+ end
180
+ end
181
+ @gems.each { |c| c.draw }
182
+ end
183
+
184
+ # Solid at a given pixel position?
185
+ def solid?(x, y)
186
+ y < 0 || @tiles[x / 50][y / 50]
187
+ end
188
+ end
189
+
190
+ class CptnRuby < (Example rescue Gosu::Window)
191
+ def initialize
192
+ super WIDTH, HEIGHT
193
+
194
+ self.caption = "Cptn. Ruby"
195
+
196
+ @sky = Gosu::Image.new("media/space.png", :tileable => true)
197
+ @map = Map.new("media/cptn_ruby_map.txt")
198
+ @cptn = Player.new(@map, 400, 100)
199
+ # The scrolling position is stored as top left corner of the screen.
200
+ @camera_x = @camera_y = 0
201
+ end
202
+
203
+ def update
204
+ move_x = 0
205
+ move_x -= 5 if Gosu::button_down? Gosu::KbLeft
206
+ move_x += 5 if Gosu::button_down? Gosu::KbRight
207
+ @cptn.update(move_x)
208
+ @cptn.collect_gems(@map.gems)
209
+ # Scrolling follows player
210
+ @camera_x = [[@cptn.x - WIDTH / 2, 0].max, @map.width * 50 - WIDTH].min
211
+ @camera_y = [[@cptn.y - HEIGHT / 2, 0].max, @map.height * 50 - HEIGHT].min
212
+ end
213
+
214
+ def draw
215
+ @sky.draw 0, 0, 0
216
+ Gosu::translate(-@camera_x, -@camera_y) do
217
+ @map.draw
218
+ @cptn.draw
219
+ end
220
+ end
221
+
222
+ def button_down(id)
223
+ if id == Gosu::KbUp then
224
+ @cptn.try_to_jump
225
+ end
226
+ end
227
+ end
228
+
229
+ CptnRuby.new.show if __FILE__ == $0
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,25 @@
1
+ #....................................................#
2
+ #....................................................#
3
+ #.............xx......x.x............................#
4
+ #............x..x....................................#
5
+ #x....x...x..x.......#####..xxx....................x.#
6
+ #.x.........................xxx.........##.........x.#
7
+ #...............""..........###...##..........##.....#
8
+ #..##..###..##..##...................................#
9
+ #........................................xx........###
10
+ #.............................###....................#
11
+ ##....##.............................................#
12
+ #....................##....##......##....##....##....#
13
+ #.................................................x..#
14
+ #...x....##....##.......x...x.....................x..#
15
+ #.....x...............x...x...x...................x..#
16
+ #......x...##.....##.................................#
17
+ #.......x.........................................#..#
18
+ #...........##........#...#...#..#.......x...........#
19
+ #...#................................................#
20
+ #....."""".................x.......#..#####...###....#
21
+ #x....#......................##......................#
22
+ #"""""#.....#.....x..................#...............#
23
+ ##xxxx......#........................................#
24
+ ##xxxx...#####............."...""""".................#
25
+ ######"""#############################################
Binary file
Binary file
Binary file
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" clip-rule="evenodd" stroke-miterlimit="10" viewBox="0 0 850.39 637.80">
3
+ <desc>SVG generated by Lineform</desc>
4
+ <defs/>
5
+ <g>
6
+ <rect width="940.00" height="734.00" x="-25.50" y="-55.50" fill="#5FB7FF" stroke="#000000" stroke-width="2.20"/>
7
+ <path d="M 223.50 49.00 C 171.16 49.00 118.84 59.51 78.91 80.50 C -0.96 122.48 -0.96 190.52 78.91 232.50 C 134.24 261.59 213.37 270.50 283.34 259.28 C 350.32 290.78 452.18 289.47 516.06 255.19 C 582.65 219.45 582.65 161.55 516.06 125.81 C 482.95 108.04 439.59 99.12 396.19 99.03 C 388.26 92.46 378.99 86.23 368.09 80.50 C 328.16 59.51 275.84 49.00 223.50 49.00 Z M 223.50 49.00 " fill="#FFFFFF" stroke="#BFBFBF" stroke-width="6.00"/>
8
+ <path d="M 735.48 183.00 C 699.52 183.00 663.55 187.05 636.11 195.16 C 607.54 203.59 593.99 214.76 595.17 225.81 C 561.74 227.76 529.60 233.37 503.83 242.72 C 438.71 266.35 438.71 304.65 503.83 328.28 C 568.96 351.91 674.56 351.91 739.69 328.28 C 787.65 310.88 800.17 285.50 777.48 263.91 C 798.41 261.97 818.28 258.74 834.86 253.84 C 889.73 237.64 889.73 211.36 834.86 195.16 C 807.42 187.05 771.44 183.00 735.48 183.00 Z M 735.48 183.00 " fill="#FFFFFF" stroke="#BFBFBF" stroke-width="6.00"/>
9
+ </g>
10
+ </svg>
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,224 @@
1
+ # Encoding: UTF-8
2
+
3
+ # The tutorial game over a landscape rendered with OpenGL.
4
+ # Basically shows how arbitrary OpenGL calls can be put into
5
+ # the block given to Window#gl, and that Gosu Images can be
6
+ # used as textures using the gl_tex_info call.
7
+
8
+ require 'rubygems'
9
+ require 'gosu'
10
+ require 'gl'
11
+
12
+ WIDTH, HEIGHT = 600, 600
13
+
14
+ module ZOrder
15
+ Background, Stars, Player, UI = *0..3
16
+ end
17
+
18
+ # The only really new class here.
19
+ # Draws a scrolling, repeating texture with a randomized height map.
20
+ class GLBackground
21
+ # Height map size
22
+ POINTS_X = 7
23
+ POINTS_Y = 7
24
+ # Scrolling speed
25
+ SCROLLS_PER_STEP = 50
26
+
27
+ def initialize
28
+ @image = Gosu::Image.new("media/earth.png", :tileable => true)
29
+ @scrolls = 0
30
+ @height_map = Array.new(POINTS_Y) { Array.new(POINTS_X) { rand } }
31
+ end
32
+
33
+ def scroll
34
+ @scrolls += 1
35
+ if @scrolls == SCROLLS_PER_STEP then
36
+ @scrolls = 0
37
+ @height_map.shift
38
+ @height_map.push Array.new(POINTS_X) { rand }
39
+ end
40
+ end
41
+
42
+ def draw(z)
43
+ # gl will execute the given block in a clean OpenGL environment, then reset
44
+ # everything so Gosu's rendering can take place again.
45
+ Gosu::gl(z) { exec_gl }
46
+ end
47
+
48
+ private
49
+
50
+ include Gl
51
+
52
+ def exec_gl
53
+ glClearColor(0.0, 0.2, 0.5, 1.0)
54
+ glClearDepth(0)
55
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
56
+
57
+ # Get the name of the OpenGL texture the Image resides on, and the
58
+ # u/v coordinates of the rect it occupies.
59
+ # gl_tex_info can return nil if the image was too large to fit onto
60
+ # a single OpenGL texture and was internally split up.
61
+ info = @image.gl_tex_info
62
+ return unless info
63
+
64
+ # Pretty straightforward OpenGL code.
65
+
66
+ glDepthFunc(GL_GEQUAL)
67
+ glEnable(GL_DEPTH_TEST)
68
+ glEnable(GL_BLEND)
69
+
70
+ glMatrixMode(GL_PROJECTION)
71
+ glLoadIdentity
72
+ glFrustum(-0.10, 0.10, -0.075, 0.075, 1, 100)
73
+
74
+ glMatrixMode(GL_MODELVIEW)
75
+ glLoadIdentity
76
+ glTranslate(0, 0, -4)
77
+
78
+ glEnable(GL_TEXTURE_2D)
79
+ glBindTexture(GL_TEXTURE_2D, info.tex_name)
80
+
81
+ offs_y = 1.0 * @scrolls / SCROLLS_PER_STEP
82
+
83
+ 0.upto(POINTS_Y - 2) do |y|
84
+ 0.upto(POINTS_X - 2) do |x|
85
+ glBegin(GL_TRIANGLE_STRIP)
86
+ z = @height_map[y][x]
87
+ glColor4d(1, 1, 1, z)
88
+ glTexCoord2d(info.left, info.top)
89
+ glVertex3d(-0.5 + (x - 0.0) / (POINTS_X-1), -0.5 + (y - offs_y - 0.0) / (POINTS_Y-2), z)
90
+
91
+ z = @height_map[y+1][x]
92
+ glColor4d(1, 1, 1, z)
93
+ glTexCoord2d(info.left, info.bottom)
94
+ glVertex3d(-0.5 + (x - 0.0) / (POINTS_X-1), -0.5 + (y - offs_y + 1.0) / (POINTS_Y-2), z)
95
+
96
+ z = @height_map[y][x + 1]
97
+ glColor4d(1, 1, 1, z)
98
+ glTexCoord2d(info.right, info.top)
99
+ glVertex3d(-0.5 + (x + 1.0) / (POINTS_X-1), -0.5 + (y - offs_y - 0.0) / (POINTS_Y-2), z)
100
+
101
+ z = @height_map[y+1][x + 1]
102
+ glColor4d(1, 1, 1, z)
103
+ glTexCoord2d(info.right, info.bottom)
104
+ glVertex3d(-0.5 + (x + 1.0) / (POINTS_X-1), -0.5 + (y - offs_y + 1.0) / (POINTS_Y-2), z)
105
+ glEnd
106
+ end
107
+ end
108
+ end
109
+ end
110
+
111
+ # Roughly adapted from the tutorial game. Always faces north.
112
+ class Player
113
+ Speed = 7
114
+
115
+ attr_reader :score
116
+
117
+ def initialize(x, y)
118
+ @image = Gosu::Image.new("media/starfighter.bmp")
119
+ @beep = Gosu::Sample.new("media/beep.wav")
120
+ @x, @y = x, y
121
+ @score = 0
122
+ end
123
+
124
+ def move_left
125
+ @x = [@x - Speed, 0].max
126
+ end
127
+
128
+ def move_right
129
+ @x = [@x + Speed, WIDTH].min
130
+ end
131
+
132
+ def accelerate
133
+ @y = [@y - Speed, 50].max
134
+ end
135
+
136
+ def brake
137
+ @y = [@y + Speed, HEIGHT].min
138
+ end
139
+
140
+ def draw
141
+ @image.draw(@x - @image.width / 2, @y - @image.height / 2, ZOrder::Player)
142
+ end
143
+
144
+ def collect_stars(stars)
145
+ stars.reject! do |star|
146
+ if Gosu::distance(@x, @y, star.x, star.y) < 35 then
147
+ @score += 10
148
+ @beep.play
149
+ true
150
+ else
151
+ false
152
+ end
153
+ end
154
+ end
155
+ end
156
+
157
+ # Also taken from the tutorial, but drawn with draw_rot and an increasing angle
158
+ # for extra rotation coolness!
159
+ class Star
160
+ attr_reader :x, :y
161
+
162
+ def initialize(animation)
163
+ @animation = animation
164
+ @color = Gosu::Color.new(0xff_000000)
165
+ @color.red = rand(255 - 40) + 40
166
+ @color.green = rand(255 - 40) + 40
167
+ @color.blue = rand(255 - 40) + 40
168
+ @x = rand * 800
169
+ @y = 0
170
+ end
171
+
172
+ def draw
173
+ img = @animation[Gosu::milliseconds / 100 % @animation.size];
174
+ img.draw_rot(@x, @y, ZOrder::Stars, @y, 0.5, 0.5, 1, 1, @color, :add)
175
+ end
176
+
177
+ def update
178
+ # Move towards bottom of screen
179
+ @y += 3
180
+ # Return false when out of screen (gets deleted then)
181
+ @y < 650
182
+ end
183
+ end
184
+
185
+ class OpenGLIntegration < (Example rescue Gosu::Window)
186
+ def initialize
187
+ super WIDTH, HEIGHT
188
+
189
+ self.caption = "OpenGL Integration"
190
+
191
+ @gl_background = GLBackground.new
192
+
193
+ @player = Player.new(400, 500)
194
+
195
+ @star_anim = Gosu::Image::load_tiles("media/star.png", 25, 25)
196
+ @stars = Array.new
197
+
198
+ @font = Gosu::Font.new(20)
199
+ end
200
+
201
+ def update
202
+ @player.move_left if Gosu::button_down? Gosu::KbLeft or Gosu::button_down? Gosu::GpLeft
203
+ @player.move_right if Gosu::button_down? Gosu::KbRight or Gosu::button_down? Gosu::GpRight
204
+ @player.accelerate if Gosu::button_down? Gosu::KbUp or Gosu::button_down? Gosu::GpUp
205
+ @player.brake if Gosu::button_down? Gosu::KbDown or Gosu::button_down? Gosu::GpDown
206
+
207
+ @player.collect_stars(@stars)
208
+
209
+ @stars.reject! { |star| !star.update }
210
+
211
+ @gl_background.scroll
212
+
213
+ @stars.push(Star.new(@star_anim)) if rand(20) == 0
214
+ end
215
+
216
+ def draw
217
+ @player.draw
218
+ @stars.each { |star| star.draw }
219
+ @font.draw("Score: #{@player.score}", 10, 10, ZOrder::UI, 1.0, 1.0, 0xff_ffff00)
220
+ @gl_background.draw(ZOrder::Background)
221
+ end
222
+ end
223
+
224
+ OpenGLIntegration.new.show if __FILE__ == $0