tea 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/COPYING +674 -0
  2. data/COPYING.LESSER +165 -0
  3. data/README.rdoc +93 -0
  4. data/doc/example/bitmap_draw.rb +21 -0
  5. data/doc/example/bitmap_load.rb +14 -0
  6. data/doc/example/bitmap_new.rb +19 -0
  7. data/doc/example/circle.rb +24 -0
  8. data/doc/example/circle_alpha.rb +45 -0
  9. data/doc/example/circle_alpha_bitmap.rb +51 -0
  10. data/doc/example/circle_bitmap.rb +18 -0
  11. data/doc/example/clip.rb +46 -0
  12. data/doc/example/event_app.rb +45 -0
  13. data/doc/example/event_keyboard.rb +43 -0
  14. data/doc/example/event_mouse.rb +85 -0
  15. data/doc/example/font_hello.rb +22 -0
  16. data/doc/example/font_word_wrap.rb +44 -0
  17. data/doc/example/grab.rb +28 -0
  18. data/doc/example/init.rb +10 -0
  19. data/doc/example/lines.rb +49 -0
  20. data/doc/example/lines_aa.rb +44 -0
  21. data/doc/example/lines_alpha.rb +33 -0
  22. data/doc/example/point.rb +26 -0
  23. data/doc/example/rect.rb +15 -0
  24. data/doc/example/rect_alpha.rb +75 -0
  25. data/doc/example/screen_set_mode.rb +18 -0
  26. data/doc/example/screen_update.rb +14 -0
  27. data/doc/example/sfont_hello.rb +22 -0
  28. data/doc/example/smile.png +0 -0
  29. data/doc/example/smile_bounce.rb +44 -0
  30. data/doc/example/smile_move.rb +58 -0
  31. data/doc/example/smile_move_2.rb +78 -0
  32. data/doc/example/sound.rb +101 -0
  33. data/doc/example/state_app.rb +33 -0
  34. data/doc/example/state_keyboard.rb +23 -0
  35. data/doc/example/state_mouse.rb +60 -0
  36. data/doc/key_constants.textile +129 -0
  37. data/doc/key_modifiers.textile +19 -0
  38. data/doc/reference.textile +421 -0
  39. data/lib/tea.rb +34 -0
  40. data/lib/tea/c_bitmap.rb +122 -0
  41. data/lib/tea/c_error.rb +11 -0
  42. data/lib/tea/c_font.rb +302 -0
  43. data/lib/tea/c_sound.rb +144 -0
  44. data/lib/tea/m_color.rb +50 -0
  45. data/lib/tea/m_event.rb +65 -0
  46. data/lib/tea/m_event_app.rb +96 -0
  47. data/lib/tea/m_event_dispatch.rb +54 -0
  48. data/lib/tea/m_event_keyboard.rb +311 -0
  49. data/lib/tea/m_event_mouse.rb +189 -0
  50. data/lib/tea/mix_blitting.rb +31 -0
  51. data/lib/tea/mix_clipping.rb +71 -0
  52. data/lib/tea/mix_grabbing.rb +86 -0
  53. data/lib/tea/mix_image_saving.rb +70 -0
  54. data/lib/tea/mix_primitive.rb +613 -0
  55. data/lib/tea/o_screen.rb +98 -0
  56. metadata +137 -0
@@ -0,0 +1,46 @@
1
+ # Test that getting, setting and using the clip rectangle all work.
2
+ # Expected result is a rectangle of smileys, and one at the bottom-right
3
+ # corner.
4
+
5
+ require 'tea'
6
+
7
+ puts <<TEST
8
+ You should see a rectangle of smileys, and one in the bottom-right corner,
9
+ for 10 seconds.
10
+
11
+ Expected output:
12
+ Clip rect is 0, 0, 400, 300
13
+ Clip rect is now 50, 50, 290, 185
14
+ Clip rect is 0, 0, 400, 300 again
15
+ Clip rect is now 368, 268, 32, 32
16
+
17
+ Actual output:
18
+ TEST
19
+
20
+ Tea.init
21
+ Tea::Screen.set_mode 400, 300
22
+
23
+ puts "Clip rect is #{Tea::Screen.clip.join(", ")}"
24
+
25
+ smiley = Tea::Bitmap.new('smile.png')
26
+
27
+ Tea::Screen.clip(50, 50, 290, 185) do
28
+ puts "Clip rect is now #{Tea::Screen.clip.join(", ")}"
29
+
30
+ for y in 0..(Tea::Screen.h / smiley.h)
31
+ for x in 0..(Tea::Screen.w / smiley.w)
32
+ Tea::Screen.blit smiley, x * smiley.w, y * smiley.h
33
+ end
34
+ end
35
+ end
36
+
37
+ puts "Clip rect is #{Tea::Screen.clip.join(", ")} again"
38
+
39
+ Tea::Screen.clip Tea::Screen.w - smiley.w, Tea::Screen.h - smiley.h, smiley.w, smiley.h
40
+ Tea::Screen.blit smiley, Tea::Screen.w - smiley.w, Tea::Screen.h - smiley.h
41
+
42
+ puts "Clip rect is now #{Tea::Screen.clip.join(", ")}"
43
+
44
+ Tea::Screen.update
45
+
46
+ sleep 10
@@ -0,0 +1,45 @@
1
+ # Test that app events are being picked up.
2
+ # This test is interactive, and should display messages for:
3
+ #
4
+ # * Gaining and losing mouse focus
5
+ # * Gaining and losing keyboard focus
6
+ # * Minimising and restoring the screen window
7
+ # * App exit
8
+
9
+ require 'tea'
10
+
11
+ puts <<TEST
12
+ This is an interactive event test. It should display messages for:
13
+
14
+ * Gaining and losing mouse focus
15
+ * Gaining and losing keyboard focus
16
+ * Minimising and restoring the screen window
17
+ * App exit
18
+
19
+ Go ahead and start doing things like changing focus.
20
+
21
+ TEST
22
+
23
+ Tea.init
24
+ Tea::Screen.set_mode 320, 240
25
+
26
+ loop do
27
+ case (e = Tea::Event.get)
28
+ when Tea::Mouse::Gained
29
+ puts 'Mouse::Gained event received'
30
+ when Tea::Mouse::Lost
31
+ puts 'Mouse::Lost event received'
32
+ when Tea::Kbd::Gained
33
+ puts 'Kbd::Gained event received'
34
+ when Tea::Kbd::Lost
35
+ puts 'Kbd::Lost event received'
36
+ when Tea::App::Restored
37
+ puts 'App::Restored event received'
38
+ when Tea::App::Minimized
39
+ puts 'App::Minimized event received'
40
+ when Tea::App::Exit
41
+ puts 'App::Exit event received'
42
+ exit
43
+ end
44
+ sleep 0.01
45
+ end
@@ -0,0 +1,43 @@
1
+ # Test that keyboard events are being picked up.
2
+ # Expected results are messages responding to key presses.
3
+
4
+ require 'tea'
5
+
6
+ puts <<TEST
7
+ You should see a small window. Try pressing some keys, or Esc to exit.
8
+ TEST
9
+
10
+ Tea.init
11
+ Tea::Screen.set_mode 320, 240
12
+
13
+ loop do
14
+ e = Tea::Event.get(true)
15
+
16
+ break if e.class == Tea::App::Exit
17
+ next unless e.class == Tea::Kbd::Down || e.class == Tea::Kbd::Up
18
+ break if e.key == Tea::Kbd::ESCAPE
19
+
20
+ out = []
21
+
22
+ if e.class == Tea::Kbd::Down
23
+ out << 'down:'
24
+ else
25
+ out << ' up:'
26
+ end
27
+
28
+ out << '(' << e.key.to_s << ')'
29
+
30
+ if RUBY_VERSION =~ /1\.8/
31
+ mods = (e.mods.select { |mod, down| down }).map { |pair| pair[0] }
32
+ else
33
+ mods = (e.mods.select { |mod, down| down }).keys
34
+ end
35
+ out << "++ #{mods.join(' + ')}" if mods.length > 0
36
+
37
+ if e.respond_to?(:char)
38
+ out << '='
39
+ out << "\"#{e.char}\""
40
+ end
41
+
42
+ puts out.join(' ')
43
+ end
@@ -0,0 +1,85 @@
1
+ # Test that mouse events are being picked up.
2
+ # Expected output is reporting of mouse move/down/up/scroll events, with
3
+ # position and relevant buttons.
4
+
5
+ require 'tea'
6
+
7
+ puts <<TEST
8
+ Move the mouse in the window. Mouse move/down/up events should be reported,
9
+ with position and relevant buttons. Mouse wheel scrolling should also be
10
+ picked up, with at least the cursor position.
11
+ TEST
12
+
13
+ ##############################################################################
14
+
15
+ # We can avoid flooding the terminal with VT100 codes. Sorry Windows.
16
+ $windows = RUBY_PLATFORM =~ /w(?:in)?32/
17
+ SAVE_POSITION = "\x1b[s"
18
+ RESTORE_POSITION = "\x1b[u"
19
+ HIDE_CURSOR = "\x1b[?25l"
20
+ UNHIDE_CURSOR = "\x1b[?25h"
21
+ CLEAR_TO_LINE_END = "\x1b[K"
22
+
23
+ # VT100-enhanced printing function that overwrites the current terminal line.
24
+ def pr(*args)
25
+ print HIDE_CURSOR, SAVE_POSITION if !$windows
26
+ print *args
27
+ if $windows
28
+ puts
29
+ else
30
+ print CLEAR_TO_LINE_END, RESTORE_POSITION, UNHIDE_CURSOR
31
+ end
32
+ end
33
+
34
+ ##############################################################################
35
+
36
+ Tea.init
37
+ Tea::Screen.set_mode 400, 300
38
+
39
+ # Event tracking to only put newlines when the event class changes.
40
+ mouse_events = [Tea::Mouse::Move,
41
+ Tea::Mouse::Down,
42
+ Tea::Mouse::Up,
43
+ Tea::Mouse::Scroll]
44
+ handled = false
45
+ last_event_class = Tea::Mouse::Move
46
+
47
+ # Track repeated scrolling in the same direction.
48
+ scroll_pos = 0
49
+
50
+ loop do
51
+ e = Tea::Event.get(true)
52
+
53
+ if e.class == Tea::App::Exit
54
+ puts
55
+ break
56
+ end
57
+
58
+ # Put a newline when the event class changes.
59
+ if handled && mouse_events.include?(e.class) && e.class != last_event_class
60
+ puts
61
+ last_event_class = e.class
62
+ scroll_pos = 0
63
+ end
64
+
65
+ handled = true
66
+ case e
67
+ when Tea::Mouse::Move
68
+ if RUBY_VERSION =~ /1\.8/
69
+ buttons = (e.buttons.select { |button, down| down }).map { |pair| pair[0] }
70
+ else
71
+ buttons = (e.buttons.select { |button, down| down }).keys
72
+ end
73
+ pr "mouse move : x = #{e.x}, y = #{e.y}, buttons = #{buttons.join(',')}"
74
+ when Tea::Mouse::Down
75
+ pr "mouse down : x = #{e.x}, y = #{e.y}, button = #{e.button}"
76
+ when Tea::Mouse::Up
77
+ pr "mouse up : x = #{e.x}, y = #{e.y}, button = #{e.button}"
78
+ when Tea::Mouse::Scroll
79
+ dir = e.delta == 1 ? 'down' : 'up '
80
+ scroll_pos += e.delta
81
+ pr "scroll #{dir}: x = #{e.x}, y = #{e.y}, position = #{scroll_pos} (#{e.delta})"
82
+ else
83
+ handled = false
84
+ end
85
+ end
@@ -0,0 +1,22 @@
1
+ # This tests that fonts can be loaded, rendered and drawn.
2
+ # Expected result: 'hello' in a small window for 5 seconds.
3
+
4
+ require 'tea'
5
+
6
+ puts <<TEST
7
+ You should see 'hello' in a small window for 5 seconds.
8
+ TEST
9
+
10
+ Tea.init
11
+ Tea::Screen.set_mode 320, 240
12
+
13
+ font = Tea::Font.new('font.bmp', Tea::Font::BITMAP_FONT, :transparent_color => Tea::Color::MAGENTA)
14
+ message = 'hello'
15
+
16
+ x = (Tea::Screen.w - font.string_w(message)) / 2
17
+ y = (Tea::Screen.h - font.h) / 2
18
+ font.draw_to Tea::Screen, x, y, message
19
+
20
+ Tea::Screen.update
21
+
22
+ sleep 5
@@ -0,0 +1,44 @@
1
+ # Test that word-wrapping works.
2
+
3
+ require 'tea'
4
+
5
+ puts <<TEST
6
+ You should see several lines of bitmapped and SFont text.
7
+ Magenta lines indicate the end of the final lines.
8
+ Press any key to exit.
9
+ TEST
10
+
11
+ Tea.init
12
+ Tea::Screen.set_mode 400, 300
13
+
14
+ message = "This is a long line. " +
15
+ "I hope it's long enough to wrap around. " +
16
+ "If it wraps, then font word wrapping is working."
17
+
18
+ font_a = Tea::Font.new('font.bmp', Tea::Font::BITMAP_FONT, :transparent_color => Tea::Color::MAGENTA)
19
+ font_b = Tea::Font.new('sfont.png', Tea::Font::SFONT)
20
+
21
+ lines_a = font_a.word_wrap(message, Tea::Screen.w)
22
+ lines_b = font_b.word_wrap(message, Tea::Screen.w)
23
+
24
+ y_pos = 0
25
+ lines_a.each do |line|
26
+ break if y_pos + font_a.h >= Tea::Screen.h / 2
27
+ font_a.draw_to Tea::Screen, 0, y_pos, line
28
+ y_pos += font_a.h
29
+ end
30
+ Tea::Screen.line lines_a.end_x, 0, lines_a.end_x, y_pos, Tea::Color::MAGENTA
31
+
32
+ old_y_pos = y_pos
33
+ lines_b.each do |line|
34
+ break if y_pos + font_b.h >= Tea::Screen.h
35
+ font_b.draw_to Tea::Screen, 0, y_pos, line
36
+ y_pos += font_b.h
37
+ end
38
+ Tea::Screen.line lines_b.end_x, old_y_pos, lines_b.end_x, y_pos, Tea::Color::MAGENTA
39
+
40
+ Tea::Screen.update
41
+
42
+ begin
43
+ e = Tea::Event.get(true)
44
+ end until e.class == Tea::App::Exit || e.class == Tea::Kbd::Down
@@ -0,0 +1,28 @@
1
+ # Test that grabbing from bitmaps works.
2
+ # Expected results are a smiley on the screen, but with its quarters swapped.
3
+
4
+ require 'tea'
5
+
6
+ puts <<TEST
7
+ You should see a smiley in the centre of the screen for 5 seconds, but with its
8
+ quarters swapped.
9
+ TEST
10
+
11
+ Tea.init
12
+ Tea::Screen.set_mode 320, 240
13
+
14
+ smiley = Tea::Bitmap.new("smile.png")
15
+ sw2 = smiley.w / 2
16
+ sh2 = smiley.h / 2
17
+ top_left = smiley.grab( 0, 0, sw2, sh2)
18
+ top_right = smiley.grab(sw2, 0, sw2, sh2)
19
+ bottom_left = smiley.grab( 0, sh2, sw2, sh2)
20
+ bottom_right = smiley.grab(sw2, sh2, sw2, sh2)
21
+
22
+ Tea::Screen.blit bottom_right, Tea::Screen.w / 2 - sw2, Tea::Screen.h / 2 - sh2
23
+ Tea::Screen.blit bottom_left, Tea::Screen.w / 2, Tea::Screen.h / 2 - sh2
24
+ Tea::Screen.blit top_right, Tea::Screen.w / 2 - sw2, Tea::Screen.h / 2
25
+ Tea::Screen.blit top_left, Tea::Screen.w / 2, Tea::Screen.h / 2
26
+ Tea::Screen.update
27
+
28
+ sleep 5
@@ -0,0 +1,10 @@
1
+ # Test if Tea can initialise.
2
+ # Expected result is nothing.
3
+
4
+ require 'tea'
5
+
6
+ puts <<TEST
7
+ This line should be the only output of this test.
8
+ TEST
9
+
10
+ Tea.init
@@ -0,0 +1,49 @@
1
+ # Test that lines of various colours can be drawn.
2
+ # Expected results are a 400x300 for 5 seconds with:
3
+ #
4
+ # * 3 vertical lines on the left: red, green, blue
5
+ # * 3 horizontal lines at the top-right: yellow, magenta, cyan
6
+ # * 2 diagonal lines at the bottom-right: white and grey
7
+ #
8
+ # The white line should be antialiased.
9
+
10
+ require 'tea'
11
+
12
+ puts <<TEST
13
+ You should see a 400x300 window for 5 seconds with:
14
+
15
+ * 3 vertical lines on the left: red, green, blue
16
+ * 3 horizontal lines at the top-right: yellow, magenta, cyan
17
+ * 2 diagonal lines at the bottom-right: white and grey
18
+
19
+ The white line should be antialiased.
20
+ TEST
21
+
22
+ Tea.init
23
+ Tea::Screen.set_mode 400, 300
24
+
25
+ grid_x = Tea::Screen.w / 10
26
+ grid_y = Tea::Screen.h / 10
27
+
28
+ lines = [[1, 1, 1, 9, Tea::Color::RED],
29
+ [2, 1, 2, 9, Tea::Color::GREEN],
30
+ [3, 1, 3, 9, Tea::Color::BLUE],
31
+ [6, 1, 9, 1, Tea::Color::YELLOW],
32
+ [6, 2, 9, 2, Tea::Color::MAGENTA],
33
+ [6, 3, 9, 3, Tea::Color::CYAN],
34
+ [6, 9, 9, 6, Tea::Color::DARK_GRAY]]
35
+
36
+ lines.each do |line|
37
+ Tea::Screen.line grid_x * line[0], grid_y * line[1],
38
+ grid_x * line[2], grid_y * line[3],
39
+ line[4]
40
+ end
41
+
42
+ Tea::Screen.line grid_x * 6, grid_y * 6,
43
+ grid_x * 9, grid_y * 9,
44
+ Tea::Color::WHITE,
45
+ :antialias => true
46
+
47
+ Tea::Screen.update
48
+
49
+ sleep 5
@@ -0,0 +1,44 @@
1
+ # Test that anti-aliased lines work as expected.
2
+ # Anti-aliased lines in replace mode should just overwrite the RGBA of the
3
+ # pixels it affects. In blend mode, the line RGB and destination RGB should be
4
+ # blended according to their ratio, while the final alpha should be the sum of
5
+ # the line and destination alpha values.
6
+
7
+ require 'tea'
8
+
9
+ puts <<TEST
10
+ You should see 16 green lines in a wheel, with a green dot in the center,
11
+ against a grey square.
12
+
13
+ Press any key to exit.
14
+ TEST
15
+
16
+ Tea.init
17
+ Tea::Screen.set_mode 400, 300
18
+
19
+ b = Tea::Bitmap.new(250, 250, Tea::Color.mix(0, 0, 0, 0))
20
+ CENTER_X = b.w / 2
21
+ CENTER_Y = b.h / 2
22
+ LINE_CENTER_CLEARANCE = 10
23
+ LINE_LENGTH = 100
24
+ LINE_COLOR = Tea::Color.mix(0, 255, 0, 128)
25
+ SPOKES = 16
26
+
27
+ Tea::Screen.rect 150, 100, 100, 100, Tea::Color.mix(64, 64, 64)
28
+
29
+ b.line CENTER_X, CENTER_Y, CENTER_X, CENTER_Y, LINE_COLOR, :antialias => true, :mix => :replace
30
+
31
+ SPOKES.times do |n|
32
+ angle = n * Math::PI * 2 / SPOKES
33
+ x1 = CENTER_X + LINE_CENTER_CLEARANCE * Math.cos(angle)
34
+ y1 = CENTER_Y + LINE_CENTER_CLEARANCE * Math.sin(angle)
35
+ x2 = CENTER_X + (LINE_CENTER_CLEARANCE + LINE_LENGTH) * Math.cos(angle)
36
+ y2 = CENTER_Y + (LINE_CENTER_CLEARANCE + LINE_LENGTH) * Math.sin(angle)
37
+ b.line x1, y1, x2, y2, LINE_COLOR, :antialias => true, :mix => n.even? ? :blend : :replace
38
+ end
39
+
40
+ Tea::Screen.blit b, (Tea::Screen.w - b.w) / 2, (Tea::Screen.h - b.h) / 2
41
+ Tea::Screen.update
42
+ begin
43
+ e = Tea::Event.get(true)
44
+ end until e.class == Tea::App::Exit || e.class == Tea::Kbd::Down
@@ -0,0 +1,33 @@
1
+ # Test that line alpha mixes properly.
2
+ # Expected results:
3
+ #
4
+ # * half-red background
5
+ # * green line, translucent
6
+ # * blue line, translucent
7
+ # * white line, solid
8
+
9
+ require 'tea'
10
+
11
+ puts <<TEST
12
+ You should see for 5 seconds:
13
+
14
+ * half-red background
15
+ * green line, translucent
16
+ * blue line, translucent
17
+ * white line, solid
18
+ TEST
19
+
20
+ Tea.init
21
+ Tea::Screen.set_mode 400, 300
22
+
23
+ tl_green = Tea::Color.mix( 0, 255, 0, 128)
24
+ tl_blue = Tea::Color.mix( 0, 0, 255, 128)
25
+ tl_white = Tea::Color.mix(255, 255, 255, 128)
26
+
27
+ Tea::Screen.rect 200, 0, 200, 300, Tea::Color::RED
28
+ 20.times { |n| Tea::Screen.line 10, 10 + n, 390, 10 + n, tl_green }
29
+ 20.times { |n| Tea::Screen.line 10, 100 + n, 390, 100 + n, tl_blue, :mix => :blend }
30
+ 20.times { |n| Tea::Screen.line 10, 200 + n, 390, 200 + n, tl_white, :mix => :replace }
31
+
32
+ Tea::Screen.update
33
+ sleep 5