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.
- data/COPYING +674 -0
- data/COPYING.LESSER +165 -0
- data/README.rdoc +99 -0
- data/doc/example/bitmap_draw.rb +21 -0
- data/doc/example/bitmap_load.rb +14 -0
- data/doc/example/circles.rb +24 -0
- data/doc/example/event_app.rb +45 -0
- data/doc/example/event_keyboard.rb +43 -0
- data/doc/example/event_mouse.rb +85 -0
- data/doc/example/init.rb +10 -0
- data/doc/example/lines.rb +49 -0
- data/doc/example/point.rb +26 -0
- data/doc/example/rect.rb +15 -0
- data/doc/example/screen_set_mode.rb +18 -0
- data/doc/example/screen_update.rb +14 -0
- data/doc/example/smile.png +0 -0
- data/doc/example/smile_bounce.rb +44 -0
- data/doc/example/smile_move.rb +56 -0
- data/doc/example/state_app.rb +33 -0
- data/doc/example/state_keyboard.rb +23 -0
- data/doc/example/state_mouse.rb +60 -0
- data/lib/tea/c_bitmap.rb +55 -0
- data/lib/tea/c_error.rb +10 -0
- data/lib/tea/m_blitting.rb +31 -0
- data/lib/tea/m_event.rb +65 -0
- data/lib/tea/m_event_app.rb +91 -0
- data/lib/tea/m_event_keyboard.rb +299 -0
- data/lib/tea/m_event_mouse.rb +190 -0
- data/lib/tea/m_primitive_drawing.rb +79 -0
- data/lib/tea/screen.rb +59 -0
- data/lib/tea.rb +29 -0
- metadata +92 -0
@@ -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
|
data/lib/tea/c_bitmap.rb
ADDED
@@ -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
|
data/lib/tea/c_error.rb
ADDED
@@ -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
|
data/lib/tea/m_event.rb
ADDED
@@ -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
|