tung-tea 0.0.4

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.
@@ -0,0 +1,56 @@
1
+ require 'tea'
2
+
3
+ class Smile
4
+ def initialize
5
+ @bitmap = Tea::Bitmap.new('smile.png')
6
+ @x = (Tea::Screen.w - @bitmap.w) / 2
7
+ @y = (Tea::Screen.h - @bitmap.h) / 2
8
+ @dx = @dy = 0
9
+ end
10
+
11
+ def n(move) @dy += move ? -1 : 1 end
12
+ def s(move) @dy += move ? 1 : -1 end
13
+ def e(move) @dx += move ? 1 : -1 end
14
+ def w(move) @dx += move ? -1 : 1 end
15
+ def stopped?; @dx == 0 && @dy == 0; end
16
+
17
+ def update
18
+ @x += @dx
19
+ @y += @dy
20
+ end
21
+
22
+ def draw
23
+ Tea::Screen.blit @bitmap, @x, @y
24
+ end
25
+ end
26
+
27
+ Tea.init
28
+ Tea::Screen.set_mode 640, 480
29
+ player = Smile.new
30
+ wait_for_event = true
31
+ loop do
32
+ player.update
33
+ Tea::Screen.clear
34
+ player.draw
35
+ Tea::Screen.update
36
+
37
+ if e = Tea::Event.get(wait_for_event)
38
+ break if e.class == Tea::App::Exit
39
+
40
+ case e
41
+ when Tea::Kbd::Down then move = true
42
+ when Tea::Kbd::Up then move = false
43
+ else next
44
+ end
45
+
46
+ case e.key
47
+ when Tea::Kbd::UP then player.n(move)
48
+ when Tea::Kbd::DOWN then player.s(move)
49
+ when Tea::Kbd::RIGHT then player.e(move)
50
+ when Tea::Kbd::LEFT then player.w(move)
51
+ when Tea::Kbd::ESCAPE then break
52
+ end
53
+
54
+ wait_for_event = player.stopped?
55
+ end
56
+ end
@@ -0,0 +1,33 @@
1
+ # Test that the app state is correctly reported.
2
+ # Expected results: minimized app state, keybord and mouse focus is correctly
3
+ # reported.
4
+
5
+ require 'tea'
6
+
7
+ puts <<TEST
8
+ Try...
9
+
10
+ * minimising/restoring the window
11
+ * moving the mouse in/out of the window
12
+ * changing focus in/out of the window
13
+
14
+ The app visibility, mouse and keyboard focus will be reported below.
15
+ TEST
16
+
17
+ Tea.init
18
+ Tea::Screen.set_mode 320, 240
19
+ e = nil
20
+ puts '%19s %20s%20s%20s' % ['EVENT', 'APP VISIBILITY', 'KEYBOARD', 'MOUSE']
21
+ puts '-' * 80
22
+ loop do
23
+ visible = Tea::App.visible? ? 'visible' : 'not visible'
24
+ kbd = Tea::Kbd.in_app? ? 'keyboard in' : 'keyboard not in'
25
+ mouse = Tea::Mouse.in_app? ? 'mouse in' : 'mouse not in'
26
+ puts '%19s:%20s%20s%20s' % [e.class, visible, kbd, mouse]
27
+ begin
28
+ e = Tea::Event.get(true)
29
+ exit if e.class == Tea::App::Exit
30
+ end until [Tea::App::Minimized, Tea::App::Restored,
31
+ Tea::Kbd::Lost, Tea::Kbd::Gained,
32
+ Tea::Mouse::Lost, Tea::Mouse::Gained].include?(e.class)
33
+ end
@@ -0,0 +1,23 @@
1
+ # Test that the keyboard state is being picked up.
2
+ # Expected output is that all keyboard events will print if the 'A' key is
3
+ # being pressed, and if Num Lock is active.
4
+
5
+ require 'tea'
6
+
7
+ puts <<TEST
8
+ Press some keys. Printed lines will tell if 'A' is being pressed,
9
+ and if Num Lock is active.
10
+ TEST
11
+
12
+ Tea.init
13
+ Tea::Screen.set_mode 320, 240
14
+ loop do
15
+ a_down = Tea::Kbd.key_down?(Tea::Kbd::A) ? 'DOWN' : 'UP'
16
+ num_lock_active = Tea::Kbd.mod_active?(Tea::Kbd::NUM_LOCK) ? 'ON' : 'OFF'
17
+ puts "'A' is #{a_down}; Num Lock is #{num_lock_active}"
18
+ begin
19
+ e = Tea::Event.get(true)
20
+ exit if e.class == Tea::App::Exit
21
+ end until e.class == Tea::Kbd::Down || e.class == Tea::Kbd::Up
22
+ print "(#{e.key}); "
23
+ end
@@ -0,0 +1,60 @@
1
+ # Test that the mouse status is correctly reported.
2
+ # Expected results include the mouse x, y, left, middle and right button down
3
+ # status, printed whenever the mouse is used in the 400x300 screen window.
4
+
5
+ require 'tea'
6
+
7
+ puts <<TEST
8
+ Move the mouse in the window. Mouse x, y, and left/middle/right button down
9
+ status should be reported here.
10
+ TEST
11
+
12
+ ##############################################################################
13
+ # Swiped from event_mouse.rb. I'd make a module, but I don't want to clutter
14
+ # this demo directory.
15
+
16
+ # We can avoid flooding the terminal with VT100 codes. Sorry Windows.
17
+ $windows = RUBY_PLATFORM =~ /w(?:in)?32/
18
+ SAVE_POSITION = "\x1b[s"
19
+ RESTORE_POSITION = "\x1b[u"
20
+ HIDE_CURSOR = "\x1b[?25l"
21
+ UNHIDE_CURSOR = "\x1b[?25h"
22
+ CLEAR_TO_LINE_END = "\x1b[K"
23
+
24
+ # VT100-enhanced printing function that overwrites the current terminal line.
25
+ def pr(*args)
26
+ print HIDE_CURSOR, SAVE_POSITION if !$windows
27
+ print *args
28
+ if $windows
29
+ puts
30
+ else
31
+ print CLEAR_TO_LINE_END, RESTORE_POSITION, UNHIDE_CURSOR
32
+ end
33
+ end
34
+
35
+ ##############################################################################
36
+
37
+ Tea.init
38
+ Tea::Screen.set_mode 400, 300
39
+ have_mouse = true
40
+ loop do
41
+ begin
42
+ e = Tea::Event.get(true)
43
+ exit if e.class == Tea::App::Exit
44
+ end until [Tea::Mouse::Move,
45
+ Tea::Mouse::Down,
46
+ Tea::Mouse::Up,
47
+ Tea::Mouse::Gained,
48
+ Tea::Mouse::Lost].include?(e.class)
49
+
50
+ case e
51
+ when Tea::Mouse::Gained then have_mouse = true
52
+ when Tea::Mouse::Lost then have_mouse = false
53
+ end
54
+
55
+ if have_mouse
56
+ pr "Mouse (#{Tea::Mouse.x}, #{Tea::Mouse.y}), [#{Tea::Mouse.left?}|#{Tea::Mouse.middle?}|#{Tea::Mouse.right?}]"
57
+ else
58
+ pr "Mouse is out of the house"
59
+ end
60
+ end
@@ -0,0 +1,55 @@
1
+ # This file holds the Bitmap class, which are grids of pixels that hold
2
+ # graphics.
3
+
4
+ require 'sdl'
5
+
6
+ require 'tea/m_blitting'
7
+ require 'tea/m_primitive_drawing'
8
+
9
+ #
10
+ module Tea
11
+
12
+ # A Bitmap is a grid of pixels that holds graphics.
13
+ class Bitmap
14
+
15
+ # Create a new Bitmap from an image file.
16
+ #
17
+ # May raise Tea::Error if it fails.
18
+ def initialize(image_path)
19
+ begin
20
+ @buffer = SDL::Surface.load(image_path)
21
+
22
+ # Optimise for the screen mode, potentially making screen blits faster.
23
+ if Tea::Screen.mode_set?
24
+ @buffer = @buffer.display_format_alpha
25
+ else
26
+ Tea::Screen.on_set_mode lambda { @buffer = @buffer.display_format_alpha }
27
+ end
28
+ rescue SDL::Error => e
29
+ raise Tea::Error, e.message, e.backtrace
30
+ end
31
+ end
32
+
33
+ # Get the width of the Bitmap in pixels.
34
+ def w
35
+ @buffer.w
36
+ end
37
+
38
+ # Get the height of the Bitmap in pixels.
39
+ def h
40
+ @buffer.h
41
+ end
42
+
43
+ include Tea::Blitting
44
+ def blittable_buffer
45
+ @buffer
46
+ end
47
+
48
+ include Tea::PrimitiveDrawing
49
+ def primitive_buffer
50
+ @buffer
51
+ end
52
+
53
+ end
54
+
55
+ end
@@ -0,0 +1,10 @@
1
+ # This file holds the Error class.
2
+
3
+ #
4
+ module Tea
5
+
6
+ # Error is the exception class raised when Bad Things happen in any of
7
+ # Tea's objects or methods.
8
+ class Error < StandardError; end
9
+
10
+ end
@@ -0,0 +1,31 @@
1
+ # This file contains the Blitting mixin.
2
+
3
+ require 'sdl'
4
+
5
+ #
6
+ module Tea
7
+
8
+ # The Blitting mixin allows objects with SDL::Surface to draw or 'blit' onto
9
+ # each other.
10
+ #
11
+ # To use this mixin, include it and write/alias a blittable_buffer method
12
+ # that gets the SDL::Surface.
13
+ #
14
+ # include Blitting
15
+ # def blittable_buffer
16
+ # @my_sdl_surface
17
+ # end
18
+ module Blitting
19
+
20
+ # Draw the source_blittable onto the current object at (x, y).
21
+ #
22
+ # source_blittable needs to include the Blitting mixin too.
23
+ def blit(source_blittable, x, y)
24
+ src = source_blittable.send(:blittable_buffer)
25
+ dest = blittable_buffer
26
+ SDL::Surface.blit src, 0, 0, src.w, src.h, dest, x, y
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,65 @@
1
+ # This file holds the core Event module.
2
+
3
+ require 'sdl'
4
+
5
+ require 'tea/c_error'
6
+ require 'tea/m_event_app'
7
+ require 'tea/m_event_keyboard'
8
+ require 'tea/m_event_mouse'
9
+
10
+ #
11
+ module Tea
12
+
13
+ # The Event module allows access to the event queue, and the classes of
14
+ # events that come out. Event handling is the heart and soul of most games,
15
+ # so this module is quite important.
16
+ module Event
17
+
18
+ # Tea's generated event queue. Add to the back, get from the front.
19
+ @@event_queue = []
20
+
21
+ # Get the next event in the event queue. If wait is true and there are no
22
+ # events to return, this method will wait until there is one and return it.
23
+ # Otherwise, an empty event queue will return nil.
24
+ #
25
+ # May raise Tea::Error if getting an event fails.
26
+ def Event.get(wait=false)
27
+ if @@event_queue.length == 0
28
+ if wait
29
+ begin
30
+ sdl_event = SDL::Event.wait
31
+ if (out_events = translate_event(sdl_event))
32
+ @@event_queue.push *out_events
33
+ end
34
+ end until @@event_queue.length > 0
35
+ else
36
+ if (out_events = translate_event(SDL::Event.poll))
37
+ @@event_queue.push *out_events
38
+ end
39
+ end
40
+ end
41
+
42
+ tea_event = @@event_queue.shift
43
+ [App, Mouse, Kbd].each { |state_holder| state_holder.update_state tea_event }
44
+ tea_event
45
+ rescue SDL::Error => e
46
+ raise Tea::Error, e.message, e.backtrace
47
+ end
48
+
49
+ # Convert an SDL::Event into one or more Tea events. May return nil, a
50
+ # single event object or multiple events in an array.
51
+ def Event.translate_event(sdl_event)
52
+ case sdl_event
53
+ when SDL::Event::Active, SDL::Event::Quit
54
+ translate_app_event sdl_event
55
+ when SDL::Event::MouseMotion, SDL::Event::MouseButtonDown, SDL::Event::MouseButtonUp
56
+ translate_mouse_event sdl_event
57
+ when SDL::Event::KeyDown, SDL::Event::KeyUp
58
+ translate_keyboard_event sdl_event
59
+ end
60
+ end
61
+ private_class_method :translate_event
62
+
63
+ end
64
+
65
+ end
@@ -0,0 +1,91 @@
1
+ # This file holds app-related event handling.
2
+
3
+ require 'sdl'
4
+
5
+ # A hot-patch to Ruby/SDL for missing SDL::Event::Active#state constants.
6
+ module SDL
7
+ class Event
8
+ APPMOUSEFOCUS = 0x01
9
+ APPINPUTFOCUS = 0x02
10
+ APPACTIVE = 0x04
11
+ end
12
+ end
13
+
14
+ #
15
+ module Tea
16
+
17
+ module Mouse
18
+ # Event generated when mouse focus is gained.
19
+ class Gained; end
20
+
21
+ # Event generated when mouse focus is lost.
22
+ class Lost; end
23
+ end
24
+
25
+ module Kbd
26
+ # Event generated when keyboard input focus is gained.
27
+ class Gained; end
28
+
29
+ # Event generated when keyboard input focus is lost.
30
+ class Lost; end
31
+ end
32
+
33
+ module App
34
+ # Event generated when the player acts to close the screen window.
35
+ class Exit; end
36
+
37
+ # Event generated when the screen window is minimised.
38
+ class Minimized; end
39
+
40
+ # Event generated when the screen window is restored from being minimised.
41
+ class Restored; end
42
+
43
+ # Returns true if the screen window has not been minimised, otherwise
44
+ # false.
45
+ def App.visible?
46
+ @visible = true if !instance_variable_defined?(:@visible)
47
+ @visible
48
+ end
49
+
50
+ # Update the reported app state when a Tea event is retrieved, so
51
+ # App.visible? returns the right status. Called automatically by
52
+ # Event.get.
53
+ def App.update_state(tea_event)
54
+ case tea_event
55
+ when Minimized then @visible = false
56
+ when Restored then @visible = true
57
+ end
58
+ @visible
59
+ end
60
+ end
61
+
62
+ module Event
63
+
64
+ # Translates an app-related SDL::Event into an array of Tea::Event
65
+ # objects. For internal use only.
66
+ def Event.translate_app_event(sdl_event)
67
+ out_events = []
68
+
69
+ case sdl_event
70
+ when SDL::Event::Quit
71
+ out_events.push App::Exit.new
72
+
73
+ when SDL::Event::Active
74
+ if (sdl_event.state & SDL::Event::APPACTIVE) != 0
75
+ out_events.push sdl_event.gain ? App::Restored.new : App::Minimized.new
76
+ end
77
+ if (sdl_event.state & SDL::Event::APPINPUTFOCUS) != 0
78
+ out_events.push sdl_event.gain ? Kbd::Gained.new : Kbd::Lost.new
79
+ end
80
+ if (sdl_event.state & SDL::Event::APPMOUSEFOCUS) != 0
81
+ out_events.push sdl_event.gain ? Mouse::Gained.new : Mouse::Lost.new
82
+ end
83
+ end
84
+
85
+ out_events
86
+ end
87
+ private_class_method :translate_app_event
88
+
89
+ end
90
+
91
+ end